硬件说明
ESP8266使用的是3.3V供电, 和Arduino不一样, ESP8266的I/O脚是不能防5V的, 连上就烧. 其输出只有12mA, 而Arduino是20-40mA. ESP8266又一个模拟->数据的转换器, 电压范围为0-1V, 高于1V的电压可能会把片子烧掉.
ESP8266的WIFI是软驱动, 会占用CPU时间, PWM, 中断及I²C都是模拟的, 都会占CPU时间.
开发板选择
参考 https://makeradvisor.com/best-esp8266-wi-fi-development-board/
常见的有ESP-01/ESP-01S, 12E/12F NodeMCU, Wemos D1 Mini这三种.
ESP-01/ESP-01S
引脚定义
ESP-01尺寸为24.75mm x 14.5mm, 适合实际部署. 现在市面上的版本都是1MB存储. 带4个GPIO, 其中两个用于串口TX和RX, 板子不带调压, 需要自备3.3V电源. 板子不带USB2TTL芯片, 需要自备转接头用于烧录.
ESP-01和ESP-01S的区别
- 两者尺寸一样, 8个管脚定义也一样
- 指示灯的管脚由ESP-01的TXD0变成了ESP-01S的GPIO2
- ESP-01S的IO0、RST、EN管脚增加了上拉电阻,
带来的好处有两个
- 烧录时, 不再需要连接RST与3.3V
- 简化了应用电路. 下面是两者对比, 上面是ESP-01, 下面是ESP-01S
可以看出ESP-01S的应用电路简化了, 省掉了两个上拉电阻.
ESP-01S的串口测试
不需要下载各种串口助手软件, 直接用putty就可以了. putty的使用:
- 选择serial, 填入COM编号, 例如COM5, 波特率设为115200, 直接连接.
- 发送命令的操作: 输入命令例如
AT
, 然后回车
, 然后按Ctrl+J
发送.
关于Ctrl+J的说明
因为一些模块的AT指令需要以
结束, 这两个分别代表了CR
和LF
, 在putty中, 回车时会输出CR, 也可以通过Ctrl+M输出CR, 但是要输出LF, 需要使用Ctrl+J
- Ctrl+M : Carriage Return(“ ”)
- Ctrl+J : Line Feed(“ ”)
如果你需要输出上面的AT指令, 就需要这样进行输入 A
-> T
-> Ctrl+M
或Enter
-> Ctrl+J
12E/12F NodeMCU
The ESP12-E NodeMCU Kit is one of the most used ESP8266 development boards. It features 4MB of flash memory, access to 11 GPIO pins, and one analog-to-digital converter (ADC) pin with 10 bit resolution. The board has a built-in voltage regulator and you can power up the module using the mini USB socket or the Vin pin.
引脚定义
使用12E/12F模块自建电路时需要添加外部元件. 使用USB2TTL供电时要注意电流是否满足, 如果USB2TTL接在了USB Hub上, 与其他USB设备共用一个USB口, 容易出现供电不足的问题, 现象就是模块不断重启.
环境配置
安装软件
根据文档安装软件, 文档中列出需要安装的python和python-serial是有问题的, 在Ubuntu20.04中只有python3没有python, 而python3已经安装, 另外没有python-serial, 这个要在后面通过pip安装
sudo apt install gcc git wget make libncurses-dev flex bison gperf
安装工具链
tar zxvf xtensa-lx106-elf-gcc8_4_0-esp-2020r3-linux-amd64.tar.gz
cd /opt/
sudo mkdir esp8266
cd esp8266/
sudo mv ~/Backup/linux/xtensa-lx106-elf .
sudo chown -R root:root xtensa-lx106-elf/
回到用户home目录, 将这个路径添加到PATH
```bash
vi .profile
# append start
export PATH="$PATH:/opt/esp8266/xtensa-lx106-elf/bin"
# append end
安装SDK
在用户home目录下
mkdir Esp
cd Esp/
# 这一步会下载超过190M大小的源代码, 需要提前设置好代理
git clone --recursive https://github.com/espressif/ESP8266_RTOS_SDK.git
将IDF_PATH添加到环境变量
vi ~/.profile
# append start
export IDF_PATH="/home/milton/Esp/ESP8266_RTOS_SDK"
# append end
通过以下方式验证
printenv IDF_PATH
printenv PATH
安装python库
# 如果python命令不存在, 需要提前设置好ln或alias
cd /usr/bin/
sudo ln -s python3.8 python
# 检查python版本
python --version
# 安装
python -m pip install --user -r $IDF_PATH/requirements.txt
连接开发板
本文使用的是一块好几年前购买的ESP8266 12E开发板, CH340 USB TTL, 带Rest和Flash两个按钮.
直接通过microUSB线连接, 通过dmesg可以看到创建的虚拟串口为ttyUSB0
[ 4348.546767] usbcore: registered new interface driver usbserial_generic
[ 4348.546778] usbserial: USB Serial support registered for generic
[ 4348.549509] usbcore: registered new interface driver ch341
[ 4348.549994] usbserial: USB Serial support registered for ch341-uart
[ 4348.550112] ch341 2-2:1.0: ch341-uart converter detected
[ 4348.552247] usb 2-2: ch341-uart converter now attached to ttyUSB0
运行示例
get-started/hello_world
这是一个基础的代码示例, 运行后会输出硬件环境信息然后进行10秒倒计时, 倒计时结束后重启板子.
编译步骤
到SDK目录下, 将hello world项目复制到最上一层
cp -r ESP8266_RTOS_SDK/examples/get-started/hello_world/ .
cd hello_world/
首先执行make menuconfig
, 在这里选择菜单Serial flasher config
, 设置
- Default serial port: /dev/ttyUSB0
- Default baud rate: 115200 baud
- Use compressed upload: Yes
- Flash SPI mode: DOUT
- Flash SPI speed: 40 MHz
- Flash size: 4MB
- Before flashing: Reset to bootloader
- After flashing: Hard reset after flashing
- make monitor baud rate: 74880 bps
然后save, exit.
编译+烧录: make flash
, 查看串口输出make monitor
, 编译+烧录+查看串口输出make flash monitor
运行输出
ets Jan 8 2013,rst cause:2, boot mode:(3,6)
load 0x40100000, len 7032, room 16
tail 8
chksum 0x9e
load 0x3ffe8408, len 24, room 0
tail 8
chksum 0x77
load 0x3ffe8420, len 3324, room 0
tail 12
chksum 0x32
csum 0x32
I (80) boot: ESP-IDF v3.4-4-gd4507156 2nd stage bootloader
I (81) boot: compile time 00:50:46
I (81) boot: SPI Speed : 40MHz
I (93) boot: SPI Mode : DOUT
I (106) boot: SPI Flash Size : 4MB
I (118) boot: Partition Table:
I (130) boot: ## Label Usage Type ST Offset Length
I (152) boot: 0 nvs WiFi data 01 02 00009000 00006000
I (176) boot: 1 phy_init RF data 01 01 0000f000 00001000
I (199) boot: 2 factory factory app 00 00 00010000 000f0000
I (222) boot: End of partition table
I (235) esp_image: segment 0: paddr=0x00010010 vaddr=0x40210010 size=0x1b2b8 (111288) map
0x40210010: _stext at ??:?
I (337) esp_image: segment 1: paddr=0x0002b2d0 vaddr=0x4022b2c8 size=0x06f24 ( 28452) map
I (357) esp_image: segment 2: paddr=0x000321fc vaddr=0x3ffe8000 size=0x00554 ( 1364) load
I (360) esp_image: segment 3: paddr=0x00032758 vaddr=0x40100000 size=0x00080 ( 128) load
I (387) esp_image: segment 4: paddr=0x000327e0 vaddr=0x40100080 size=0x04f6c ( 20332) load
I (427) boot: Loaded app from partition at offset 0x10000
Hello world!
This is ESP8266 chip with 1 CPU cores, WiFi, silicon revision 1, 4MB external flash
Restarting in 10 seconds...
peripherals/uart_echo
这个项目用于演示ESP8266对于UART0的串口数据接收和发送. 因为UART0就是用于烧录板子的串口, 所以烧录后, 直接monitor就能进行操作.
为了使输入输出更加明显, 可以对代码进行一些修改,
- 将
20 / portTICK_RATE_MS
修改为1000 / portTICK_RATE_MS
, 即每20ms刷新一次变为每秒刷新一次 - 输出一个换行符使得定时更明显
while (1) {
// Read data from the UART
int len = uart_read_bytes(UART_NUM_0, data, BUF_SIZE, 1000 / portTICK_RATE_MS);
// Write data back to the UART
uart_write_bytes(UART_NUM_0, (const char *) data, len);
char* test_str = ".
";
uart_write_bytes(UART_NUM_0, (const char*)test_str, strlen(test_str));
}
在monitor的过程中, 可以看到对于键盘的输入, 板子会每隔一秒将收集到的输入的信息返回, 同时显示一个回车.
wifi/getting_started/station
这个项目用于演示如何将板子接入一个带密码的WIFI网络并获得IP.
编译步骤
- 先运行
make menuconfig
, 在界面的Example Configuration
中配置SSID和password. - 运行
make flash monitor
编译烧录并观察输出
输出
I (43) boot: compile time 17:36:40
I (43) boot: SPI Speed : 40MHz
I (49) boot: SPI Mode : DOUT
I (56) boot: SPI Flash Size : 4MB
...
I (380) wifi station: ESP_WIFI_MODE_STA
I (384) system_api: Base MAC address is not set, read default base MAC address from EFUSE
I (390) system_api: Base MAC address is not set, read default base MAC address from EFUSE
phy_version: 1163.0, 665d56c, Jun 24 2020, 10:00:08, RTOS new
I (457) phy_init: phy ver: 1163_0
I (519) wifi station: wifi_init_sta finished.
I (3594) wifi:state: 0 -> 2 (b0)
I (3597) wifi:state: 2 -> 3 (0)
I (3601) wifi:state: 3 -> 5 (10)
I (3624) wifi:connected with ND2, aid = 1, channel 7, HT20, bssid = 20:76:93:43:01:40
I (7600) tcpip_adapter: sta ip: 192.168.17.111, mask: 255.255.255.0, gw: 192.168I (7605) wifi station: got ip:192.168.15.123
I (7610) wifi station: connected to ap SSID:ND2 password:12345678
如果要修改板子的hostname, 那么在事件处理的方法中加入这行
ESP_ERROR_CHECK(tcpip_adapter_set_hostname(TCPIP_ADAPTER_IF_STA, "testing"));
if (event_base == WIFI_EVENT && event_id == WIFI_EVENT_STA_START) {
ESP_ERROR_CHECK(tcpip_adapter_set_hostname(TCPIP_ADAPTER_IF_STA, "testing"));
esp_wifi_connect();
...
protocols/sockets/udp_client
这个项目演示如何通过UDP发送和接收消息
- 先找一台局域网机器, 假设IP为192.168.15.15, 运行UDP服务, 接收请求并直接返回
# 返回固定字符串
nc -u -l 3333 -k -c "echo "Received""
# 返回收到的字符串
nc -u -l 3333 -k -c "/bin/cat"
- 运行
make menuconfig
,
- 界面的
Example Configuration
中配置服务器的IPv版本, IP地址和端口 - 界面的
Example Connection Configuration
中配置SSID, password等WIFI连接信息
- 运行
make flash monitor
编译烧录并观察输出
评估
ESP8266以station的方式与AP建立连接, 其ping的延迟较大且不稳定, 在网络很好的情况下结果如下, ping值延迟在24~124ms之间波动.
# first round
PING 192.168.8.232 (192.168.8.232): 56 data bytes
64 bytes from 192.168.8.232: seq=0 ttl=255 time=23.925 ms
64 bytes from 192.168.8.232: seq=1 ttl=255 time=48.103 ms
64 bytes from 192.168.8.232: seq=2 ttl=255 time=70.783 ms
64 bytes from 192.168.8.232: seq=3 ttl=255 time=94.698 ms
64 bytes from 192.168.8.232: seq=4 ttl=255 time=118.095 ms
64 bytes from 192.168.8.232: seq=5 ttl=255 time=39.515 ms
64 bytes from 192.168.8.232: seq=6 ttl=255 time=64.213 ms
64 bytes from 192.168.8.232: seq=7 ttl=255 time=88.089 ms
64 bytes from 192.168.8.232: seq=8 ttl=255 time=111.300 ms
64 bytes from 192.168.8.232: seq=9 ttl=255 time=32.766 ms
64 bytes from 192.168.8.232: seq=10 ttl=255 time=56.775 ms
64 bytes from 192.168.8.232: seq=11 ttl=255 time=80.540 ms
64 bytes from 192.168.8.232: seq=12 ttl=255 time=103.953 ms
64 bytes from 192.168.8.232: seq=13 ttl=255 time=25.493 ms
64 bytes from 192.168.8.232: seq=14 ttl=255 time=49.115 ms
64 bytes from 192.168.8.232: seq=15 ttl=255 time=73.213 ms
64 bytes from 192.168.8.232: seq=16 ttl=255 time=97.223 ms
64 bytes from 192.168.8.232: seq=17 ttl=255 time=120.821 ms
64 bytes from 192.168.8.232: seq=18 ttl=255 time=41.917 ms
64 bytes from 192.168.8.232: seq=19 ttl=255 time=66.030 ms
64 bytes from 192.168.8.232: seq=20 ttl=255 time=89.736 ms
64 bytes from 192.168.8.232: seq=21 ttl=255 time=115.033 ms
64 bytes from 192.168.8.232: seq=22 ttl=255 time=34.937 ms
64 bytes from 192.168.8.232: seq=23 ttl=255 time=58.816 ms
64 bytes from 192.168.8.232: seq=24 ttl=255 time=83.114 ms
64 bytes from 192.168.8.232: seq=25 ttl=255 time=106.258 ms
64 bytes from 192.168.8.232: seq=26 ttl=255 time=27.669 ms
64 bytes from 192.168.8.232: seq=27 ttl=255 time=51.536 ms
64 bytes from 192.168.8.232: seq=28 ttl=255 time=75.806 ms
64 bytes from 192.168.8.232: seq=29 ttl=255 time=99.316 ms
64 bytes from 192.168.8.232: seq=30 ttl=255 time=123.205 ms
64 bytes from 192.168.8.232: seq=31 ttl=255 time=44.493 ms
64 bytes from 192.168.8.232: seq=32 ttl=255 time=68.095 ms
33 packets transmitted, 33 packets received, 0% packet loss
round-trip min/avg/max = 23.925/72.260/123.205 ms
# second round
46 packets transmitted, 45 packets received, 2% packet loss
round-trip min/avg/max = 23.770/73.276/123.395 ms
参考
- 官网ESP8266环境搭建, RTOS SDK
https://docs.espressif.com/projects/esp8266-rtos-sdk/en/latest/ - ESP6288和ESP32的区别
https://makeradvisor.com/esp32-vs-esp8266/ - ESP6288 Beginner's Guide 带代码例子
https://tttapa.github.io/ESP8266/Chap01 - ESP8266.html