ESP32 应用实践:ethernet 转 WiFi 实现_esp32以太网转wifi-程序员宅基地

技术标签: 应用实践 (Applications)  ESP32  无线网卡  以太网转WiFi  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 吞吐量可能会下降。

版权声明:本文为博主原创文章,遵循 CC 4.0 BY-SA 版权协议,转载请附上原文出处链接和本声明。
本文链接:https://blog.csdn.net/espressif/article/details/78608462

智能推荐

推荐一个在线反编译的website_exe在线反编译网站-程序员宅基地

文章浏览阅读3.3k次。最近在研究代码生成器,目前有几个生成java web 代码的generater,但都没有源码,用jd工具反编译,有些类会有error tag,在网上查了一下,说是jd反编译不了,于是找到了这个在线反编译java字节码的网站,使用很简单,上传class文件即可,反编译完成之后还提供下载功能。网址:http://www.showmycode.com/这个成功反编译了很多jd饭编译不了的类,甚是强大_exe在线反编译网站

基于Java+Swing实现中国象棋游戏_java中国象棋-程序员宅基地

文章浏览阅读845次。1、寻找棋盘界面和对应的棋子图片,程序设计棋盘界面和功能菜单2、设计不同的棋子的移动逻辑3、棋子移动时,要有音效4、对局开始前,双方棋子在棋盘上的摆法。5、对局时,由执红棋的一方先走,双方轮流走一步。6、轮到走棋的一方,将某个棋子从一个交叉点走到另一个交叉点,或者吃掉对方的棋子而占领其交叉点,都算走了一着。7、双方各走一着,称为一个回合。8、走一着棋时,如果己方棋子能够走到的位置有对方棋子存在,就可以把对方棋子吃掉而占领那个位置。_java中国象棋

cannot bind 'tcp:5037' 完美解决方法-程序员宅基地

文章浏览阅读10w+次,点赞2次,收藏5次。我们用adb连接Android设备时会出现:adb devicesadb server is out of date. killing…ADB server didn’t ACK* failed to start daemon *error: unknown host service这是因为 adb的端口(5037)被占用了在命令行输入C:\Users\lizy>netstat ..._cannot bind 'tcp:5037

单片机c语言 oxfe,AVR单片机入门及C语言高效设计实践(五)-程序员宅基地

文章浏览阅读853次。ATMEAGl6L的中断系统什么是“中断”?顾名思义中断就是中断某一工作过程去处理一些与本工作过程无关或间接相关或临时发生的事件,处理完后,则继续原工作过程。比如:你在看书,电话响了,你在书上做个记号后去接电话,接完后在原记号处继续往下看书。如有多个中断发生,依优先法则,中断还具有嵌套特性。又比如:看书时,电话响了,你在书上做个记号后去接电话,你拿起电话和对方通话,这时门铃响了,你让打电话的对方稍..._0xfe在单片机中是什么意思

vue + ivew 校验form表单俩次密码输入是否一致_iview form怎么判断两次密码是否一样-程序员宅基地

文章浏览阅读963次。实现代码如下<Form ref="resetPwdForm" :model="resetPwdForm" :rules="resetPwdRules"> <FormItem prop="password"> <p> <Icon slot="prefix" class="iconfont iconPC-2" /> <span>密码</span> </p> <Input v-mod_iview form怎么判断两次密码是否一样

在vscode使用anaconda_vscode用anaconda作为解释器-程序员宅基地

文章浏览阅读2.8k次。个人经验,仅供参考下载Anaconda,我下载时未添加环境变量,是下载好之后把…/script路径手动添加到环境变量中的用户变量下载vscode在Anaconda中创建一个新环境打开vscode:file->reference->setting搜索python.pythonPath添加你的Anaconda下env的路径左下角这里点击可选择interpreter,选择xxx:conda(你的虚拟环境对应的解释器),建议选择前先重开vscode中断出现(base)说明操作成功,_vscode用anaconda作为解释器

随便推点

组态王7.5SP4版软件与加密狗匹配开发版+运行版使用分享-程序员宅基地

文章浏览阅读3.9k次。组态软件与加密狗匹配开发版+运行版使用分享,组态软件按照文章这样样操作就可以正常打开和运行了。希望对大家有帮助。_组态王7.5

jdk1.8 下载,安装,配置_安装jdk1.8下载-程序员宅基地

文章浏览阅读457次,点赞22次,收藏6次。JDK下载安装配置_安装jdk1.8下载

kubernetes/k8s重启实体服务器后集群启动异常The connection to the server xxx:6443 was refused - did you specify..._kubelet的6443端口未启动-程序员宅基地

文章浏览阅读571次,点赞6次,收藏10次。例如:项目场景:示例:通过蓝牙芯片(HC-05)与手机 APP 通信,每隔 5s 传输一批传感器数据(不是很大)_kubelet的6443端口未启动

怎么用c语言让电脑定时开关机,电脑定时开关机如何设置?小编教你设置电脑定时开机和关机...-程序员宅基地

文章浏览阅读1.2k次。经常使用电脑的朋友由于工作需要可能会需要设置定时开关机,那么定时关机设置起来比较简单,使用系统自带的或是软件都可以,定时开机会相对复杂一些,不管如何,下面小编就把电脑定时关机开机的方法分享给大家。一、电脑定时关机A:使用系统自带定时关机命令方法一:运行输入 at 18:00 shutdown -f -s1、打开开始菜单,选择运行2、输入 at 18:00 shutdown -f -s 即可在下午6..._c语言怎样把一个开机时间和一个关机时间的

java addslashes_php addslashes()函数的使用-程序员宅基地

文章浏览阅读253次。用户评论:roysimke atmicrosoftsfirstmailprovider dot com (18-Jun-201004:35)Never useaddslashes function to escape values you are goingto send to mysql. use mysql_real_escape_string or pg_escape atleast if ..._addslashes函数 java

ElasticSearch的常用命令操作_elasticsearch命令-程序员宅基地

文章浏览阅读4.8k次。本文采用的ElasticSearch和kibana的版本为7.17.3。在ElasticSearch的操作中:搜索Dev Tools 进入到命令栏,即可对Elastic Search进行操作。green 表示健康, yellow 表示亚健康, red 表示有问题。三、ElasticSearch的增删查改操作1、创建数据库创建game库、consoleGame表、向id为1添加数据PUT对应的修改内容为全局修改,是新的内容直接覆盖了旧的内容,如果要保持键的内容及数量不变,需要与旧的数据一_elasticsearch命令