ESP32 应用实践:ethernet 转 WiFi 实现

一:简介

Ethernet 转 WiFi 用于实现以太网口的设备通过 WiFi 进行无线互联。将从设备 发出的 802.3 帧数据转化为 802.11 帧数据发送出去,接收到的 802.11 帧数据转换为 802.3 帧数据发送给设备,其跳过了 ESP32 的 lwip,直接在物理层进行了数据的转发,提高了数据转发的效率。

在本 Demo 中,Ethernet 转 WiFi 主要有两种使用方式:STATION 模式和 SOFTAP 模式,

二:硬件准备

实现 Ethernet 转 WiFi 需使用带有 phy 功能的 ESP32 开发板,本 Demo 使用的是 ESP32_Ethernet_v3。对于普通的 ESP32 开发板,想要实现本 Demo 需外接 PHY,目前 ESP32 Ethernt driver 支持的 phy 有 TLK110 和 LAN8720,而在 ESP32_Ethernet_v3 中集成的是 TLK110 。

image

image

三:配置说明

3.1 PHY 配置

用户可以在 make menuconfig 中对 PHY 进行配置。如果使用 ESP32_Ethernet_v3 开发板,只需要使用默认配置即可;对于外接 phy 的用户,可以参照 Ethernet Demo 中的要求对 phy 进行修改。

3.2 WiFi 配置

WiFi 的配置主要是为了提高数据的吞吐率,在本 Demo 中,增加了 WiFi RX 和 TX 的 buffer 数量,并调整了 ESP32 的 CPU 时钟,具体优化信息请参照默认配置项 sdkconfig.defaults。

Note: 用户可以根据自己需要通过make menuconfig调整相关参数,但是 STATIC_RX_BUFFER_NUM和 TX/RX BA Window(the size of WiFi Block Ack TX window) 均不要超过 16 ,否则可能会因为内存问题引起 crash,其中这些参数位于 Component config -> Wi-Fi 下。

四:Demo 使用步骤

通过如下方式获取此 Demo

$ git clone  https://github.com/espressif/esp-iot-solution
$ cd esp-iot-solution
$ git submodule update --init --recursive

本 Demo 位于 esp-iot-solution/examples/eth2wifi 下,Demo 提供了 ethernet 转 WiFi 的两种模式:ESP32 作为 STATION 模式和 ESP32 作为 SOFTAP 模式。

4.1 STATION 模式

STATION 模式是设备将 Ethernet 帧数据转化为 WiFi station 帧数据,然后将 WiFi station 数据无线发送给 AP ,从而实现类似于无线网卡的功能。

a) 使用 USB 转串口线将开发板连接到 PC 上

b) 进入 esp-iot-solution/examples/eth2wifi 所在目录

c) 选择配置

$ make menuconfig
  • 在 Serial flasher config - Default serial port 中,配置需要下载的串口
  • 在 Component config - IoT Example - Ethernet to WiFi Demo Configuration - The SSID for demo 中设置 SSID
  • 在 Component config - IoT Example - Ethernet to WiFi Demo Configuration - The PASSWORD for demo 中设置 WiFi 密码
  • 在 Component config - IoT Example - Ethernet to WiFi Demo Configuration - WiFi station mode 中,输入 y,选择 STA 模式(默认即为 Y )

esp

d) 编译并烧录程序

$ make flash

e) 运行

  1. 烧录成功后,打开串口工具,此时会打印 log,根据 SSID 连接 AP,然后 PC 会发起 DHCP 请求

  2. 查看是否拿到 IP,并尝试 ping 网关来测试是否正常

4.2 SOFTAP 模式

SOFTAP 模式是利用 ESP32 所属的设备作为一个 AP,从而可以组建一个小型的局域网,因为交互需要 IP 信息,所以需要设备具备 DHCP Server 的能力,在本 Demo 中,使用 PC 来作为 DHCP Server。

4.2.1 Ubuntu DHCP server 配置

Ubuntu 配置 dhcp 服务器需要:计算机设置静态 ip ,(充当 dhcp 服务器的计算机的 ip 需要是静态 ip,不可以是通过动态获得,设置静态 ip 需要设置在对应的网卡:如 eth0 )设置子网掩码,默认网关,以及配置 dhcp。

a) PC 设置静态 ip/子网掩码/网关

静态 ip 的配置:
设置–>系统设置–>网络–>选项–> ipv4 –>方法:手动;添加–> address, subnet, netmask.

我设置的静态ip地址:192.168.5.0,子网掩码:255.255.255.0,网关:192.168.5.1。

$ sudo vim /etc/network/interfaces

设置成如下内容:

 auto lo
 iface lo inet loopback
 auto eth0
 iface eth0 inet static
 address 192.168.5.0
 gateway 192.168.5.1
 netmask 255.255.255.0

Note: eth0 是测试 PC 上的网卡名称,不同的电脑网卡名称不同,可通过 ipconfig 查看,替换成自己的网卡名称即可
配置完成后重启网络服务:

sudo /etc/init.d/networking restart

b) 配置 DHCP 服务器

  • 首先安装 DHCP 服务器
$ sudo apt-get install isc-dhcpd-server
  • 配置 DHCP 的网卡
$ sudo vim /etc/default/isc-dhcp-server

设置使用网卡(我的是 eth0 )作为 DHCP Server

$ INTERFACES = "eth0"
  • 编辑当前配置
$ sudo vim /etc/dhcp/dhcpd.conf

在文件末尾添加如下几项

subnet 192.168.5.0  netmask 255.255.255.0 {
  range 192.168.5.0 192.168.5.100;
#  option domain-name-servers 210.30.100.2;
#  option domain-name "internal.example.org";
#  option routers 172.6.1.1;
  option broadcast-address 192.168.5.255;
  default-lease-time 600;
  max-lease-time 7200;  
}
  • 配置完成后,重启 dhcp 服务:
$ sudo /etc/init.d/isc-dhcpd-server restart

Note: /etc/dhcp/dhcpd.conf中的 subnet 一定要包含 server 本机的 ip 在内,否则启动不了

最后可以通过 ifconfig eth0 查看是否静态 IP 设置成功

c) 烧写步骤

烧写 softap 的步骤与 STA 基本相同,只需要在第 4 步时将 Ethernet to wifi station forwarding data 设置为 n 即为 softap 模式。

d) 运行

  1. 将 ESP32 连接到 PC 设备上,确保 PC 设备已经开启了 DHCP Server,配置方法请参照前文 Ubuntu 配置 DHCP server
  2. 给 ESP32 上电,并打开 PC 上的串口工具,此时串口会打印 log
  3. 用手机连接 ESP32 的 SSID(默认为 DEMO_TEST),成功后会在步骤 2 中打印 STA 连接成功的 Log
  4. 尝试 ping 手机拿到的 IP 地址测试是否正常

五:核心代码分析

5.1 事件处理

ESP32 代码中将网络中的各种状态全部封装成了事件,所以 Ethernet 转 WiFi 的核心是网络事件( Event )的处理;在本次 Demo 中,主要做了如下事件的处理:

static esp_err_t event_handler(void* ctx, system_event_t* event)
{
    switch (event->event_id) {
        case SYSTEM_EVENT_STA_START:
            printf("SYSTEM_EVENT_STA_START\r\n");
            break;

        case SYSTEM_EVENT_STA_CONNECTED:
            printf("SYSTEM_EVENT_STA_CONNECTED\r\n");
            wifi_is_connected = true;

            esp_wifi_internal_reg_rxcb(ESP_IF_WIFI_STA, (wifi_rxcb_t)tcpip_adapter_sta_input_eth_output);

对于 SYSTEM_EVENT_STA_START 事件,我们并没有进行常见的 esp_wifi_connect() 操作,而是放在 Ethernet task 中进行,这么做主要是为了获取 PC 的 MAC 地址,然后将 sta 的 MAC 替换为 PC 的 MAC。
对于 SYSTEM_EVENT_STA_CONNECTED 事件,ESP32 连接上 AP 后,会进入此事件,在一般的网络交互中,此时开始进行 DHCP 请求操作,但因为此时 ESP32 只是作为一个管道,所以在这里我们并不是将数据抛给 lwip 而是将数据“窃取”并转发 给 Ethernet。

       case SYSTEM_EVENT_STA_GOT_IP:
            printf("SYSTEM_EVENT_STA_GOT_IP\r\n");
            break;

        case SYSTEM_EVENT_STA_DISCONNECTED:
            printf("SlYSTEM_EVENT_STA_DISCONNECTED\r\n");
            wifi_is_connected = false;
            esp_wifi_internal_reg_rxcb(ESP_IF_WIFI_STA, NULL);
            esp_wifi_connect();
            break;

对于事件 SYSTEM_EVENT_STA_GOT_IP ,好吧,这个事件在这个 Demo 是不会被触发了,因为我们没使用 lwip 中的 DHCP client 功能。
当事件 SYSTEM_EVENT_STA_DISCONNECTED 被触发,我们要做的是让 Ethernet 收到的数据将不会通过 WiFi 进行转发,同时重连网络。


        case SYSTEM_EVENT_AP_STACONNECTED:
            printf("SYSTEM_EVENT_AP_STACONNECTED\r\n");
            wifi_is_connected = true;

            esp_wifi_internal_reg_rxcb(ESP_IF_WIFI_AP, (wifi_rxcb_t)tcpip_adapter_ap_input_eth_output);
            break;

        case SYSTEM_EVENT_AP_STADISCONNECTED:
            printf("SYSTEM_EVENT_AP_STADISCONNECTED\r\n");
            wifi_is_connected = false;
            esp_wifi_internal_reg_rxcb(ESP_IF_WIFI_AP, NULL);
            break;

作为 AP 时事件处理和 STA 相同,区别是这里设置为 AP 模式,而不是 STA 模式。

        case SYSTEM_EVENT_ETH_CONNECTED:
            printf("SYSTEM_EVENT_ETH_CONNECTED\r\n");
            ethernet_is_connected = true;
            break;

        case SYSTEM_EVENT_ETH_DISCONNECTED:
            printf("SYSTEM_EVENT_ETH_DISCONNECTED\r\n");
            ethernet2wifi_mac_status_set(false);
            ethernet_is_connected = false;
            break;

Ethernet 事件的处理主要是探测以太网是否连接或者断开,同时在断开时,ethernet2wifi_mac_status_set 还要置为 false,以保证下次重新连接时重新替换 sta 的 mac 地址。

5.2 MAC地址设置

因为 Ethernet 转 WiFi 牵涉到 3 个 MAC(PC、Etherner 和 STA/AP ),而网络很多操作需要校验 MAC,为了确保在网络交互时 MAC 还能保持 PC 的 MAC,在本 Demo 中将 STA 的 MAC 设置为 PC 的 MAC。

if (!ethernet2wifi_mac_status_get()) {
   memcpy(eth_mac, (uint8_t*)msg.buffer + 6, sizeof(eth_mac));
   ESP_ERROR_CHECK(esp_wifi_start());
#ifdef CONFIG_ETH_TO_STATION_MODE
   esp_wifi_set_mac(WIFI_IF_STA, eth_mac);
   esp_wifi_connect();
#else
   esp_wifi_set_mac(WIFI_IF_AP, eth_mac);
#endif
   ethernet2wifi_mac_status_set(true);
 }

在 SYSTEM_EVENT_ETH_CONNECTED 事件被触发之后,PC 开始发送包含 MAC 地址的网络数据,如下图所示:

image

我们截取之后将 STA 的 MAC 地址设置为 PC 的 MAC 地址,此时再连接 AP,并将状态置为 true,以避免下次 PC 发送数据时重复设置 MAC。
在连接到 AP 之后,PC 再进行 DHCP 请求时,sta 就会使用 PC的 MAC 地址和 AP 进行交互,以此保证正常通讯。

六:性能指标分析

我们使用了 iperf 对吞吐率进行了简单的测试,在开放工作环境下,其 TCP 吞吐量稳定在 45Mbps 左右。但周围环境会对 WiFi 吞吐量造成较大影响,在环境较差时,WiFi 吞吐量可能会下降。

评论 21
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值