ESP32搭建环境监测站


开始之前

请认真阅读以下内容 http://www.1zlab.com/wiki/micropython-esp32/

一、准本工作

面包板、电源、ESP32、HT22、一大把面包线 、还有一颗勇往无前的心 ✿

二、ESP32刷写系统

1、开发环境介绍

ESP32支持的开发环境较多,列举部分如下,本文以Micro Python为开发语言。

Native C,官方提供的方案,可以选择裸机或者 FreeRTOS 进行开发;
Arduino,官方支持,使用 Arduino IDE 即可进行开发;
Python 固件,第三方支持,使用 MicroPython 进行开发;
nodemcu 固件,社区支持,使用 Lua 进行开发;
Espruino 固件,社区支持,使用 JavaScript 进行开发;

Micropython快速参考乐鑫官方ESP-IDF 编程指南Micro Python简介

2、安装Python、esptool

下载python,安装后进入cmd执行pip install esptool安装esptool;pip install adafruit-ampy安装ampy文件上传工具。

3、下载适合ESP32的Micro Python固件并完成烧录

这里下载适合的固件,选择GENERIC对应最新版本,本文使用的是 GENERIC : esp32-idf3-20191220-v1.12.bin

CP210xUSB驱动 选择符合当前操作系统的版本; PUTTY 后续连接ESP32用。

通过开始之前的链接 相信你已经解决了ESP32连接电脑的问题,cmd执行 esptool.py --port COM3 erase_flash擦除flash; esptool.py --chip esp32 --port COM3 write_flash -z 0x1000 C:\esp32-idf3-20191220-v1.12.bin刷入flash。

4、接入WiFi为开发做准备

首先通过putty连接到ESP32,选择serial 波特率115200 端口COM3,连接后如下图:

执行以下代码连接WiFi:

>>> import network # 导入network模块
>>> wifi = network.WLAN(network.STA_IF)  # 设置为STA_IF模式,即接入wifi路由器的模式,AP_IF为热点模式
>>> wifi.active(True) # 将wifi激活
>>> wifi.connect('Mr.Han','1234500890') #连接至wifi

安装EMP模块:

>>> import upip 
I (240305) modsocket: Initializing 
>>> upip.install('emp-1zlab') 
Installing to: /lib/
Warning: micropython.org SSL certificate is not validated
Installing emp-1zlab 0.2.7 from https://files.pythonhosted.org/packages/78/84/a15769640950d1f0afd7759e61a1696f201b00dbbf32d5747c2d8fa633db/emp-1zlab-0.2.7.tar.gz
>>> 

设置启动模式,注意:该操作会覆盖boot.py中的所有内容

>>> from emp_boot import set_boot_mode
>>> set_boot_mode()
[0]   Boot with nothing
      attention: this option will clear up boot.py, careful!
[1]   Boot with wifi startup
      this mode will auto start wifi connect program.
[2]   Easy to develop
      this mode is for developers.In this mode you can develop much easier via EMP-IDE(emp.1zlab.com)
Please input your choice [0-2]:
    #选择2

参考文章:MicroPython-ESP32之更合理的建立wifi连接-1Z实验室How

摘抄文章内部分连接WiFi代码如下:

def do_connect():
    import json
    import network
    # 尝试读取配置文件wifi_confi.json,这里我们以json的方式来存储WIFI配置
    # wifi_config.json在根目录下

    # 若不是初次运行,则将文件中的内容读取并加载到字典变量 config
    try:
        with open('wifi_config.json','r') as f:
            config = json.loads(f.read())
    # 若初次运行,则将进入excpet,执行配置文件的创建        
    except:
        essid = input('wifi name:') # 输入essid
        password = input('wifi passwrod:') # 输入password
        config = dict(essid=essid, password=password) # 创建字典
        with open('wifi_config.json','w') as f:
            f.write(json.dumps(config)) # 将字典序列化为json字符串,存入wifi_config.json

    #以下为正常的WIFI连接流程        
    wifi = network.WLAN(network.STA_IF)  
    if not wifi.isconnected(): 
        print('connecting to network...')
        wifi.active(True) 
        wifi.connect(config['essid'], config['password']) 
        while not wifi.isconnected():
            pass 
    print('network config:', wifi.ifconfig()) 

if __name__ == '__main__':
    do_connect()
import sys

# 添加路径
sys.path.append('examples')

def is_legal_wifi(essid, password):
    '''
    判断WIFI密码是否合法
    '''
    if len(essid) == 0 or len(password) == 0:
        return False
    return True

def do_connect():
    import json
    import network
    # 尝试读取配置文件wifi_confi.json,这里我们以json的方式来存储WIFI配置
    # wifi_config.json在根目录下

    # 若不是初次运行,则将文件中的内容读取并加载到字典变量 config
    try:
        with open('wifi_config.json','r') as f:
            config = json.loads(f.read())
    # 若初次运行,则将进入excpet,执行配置文件的创建        
    except:
        essid = ''
        password = ''

        while True:
            essid = input('wifi name:') # 输入essid
            password = input('wifi passwrod:') # 输入password

            if is_legal_wifi(essid, password):
                config = dict(essid=essid, password=password) # 创建字典
                with open('wifi_config.json','w') as f:
                    f.write(json.dumps(config)) # 将字典序列化为json字符串,存入wifi_config.json
                break
            else:
                print('ERROR, Please Input Right WIFI')

    #以下为正常的WIFI连接流程        
    wifi = network.WLAN(network.STA_IF)  
    if not wifi.isconnected(): 
        print('connecting to network...')
        wifi.active(True) 
        wifi.connect(config['essid'], config['password']) 
        import utime

        for i in range(200):
            print('第{}次尝试连接WIFI热点'.format(i))
            if wifi.isconnected():
                break
            utime.sleep_ms(100) #一般睡个5-10秒,应该绰绰有余

        if not wifi.isconnected():
            wifi.active(False) #关掉连接,免得repl死循环输出
            print('wifi connection error, please reconnect')
            import os
            # 连续输错essid和password会导致wifi_config.json不存在
            try:
                os.remove('wifi_config.json') # 删除配置文件
            except:
                pass
            do_connect() # 重新连接
        else:
            print('network config:', wifi.ifconfig()) 

if __name__ == '__main__':
    do_connect()

5、GPIO针脚分布及介绍

ESP32使用Micro Python 开发时GPIO引脚定义如上图,参考来源1Zlab。由于封装原因并不是所有的引脚都引出。

功能简介 缩写 可用的GPIO编号 备注
模拟信号采样 ADC 32, 33, 34, 35, 36, 39
模拟信号输出 DAC 25, 26
串行通信 UART 1(TX0),3(RX0), 10(TX1),9(RX1) ,17(TX2),16(RX2) 共三组
探测由手指或其他物品直接接触或接近而产生的电容差异 TOUCHPAD 0, 2, 4, 12, 13, 14, 15, 27, 32, 33
SPI总线接口 SPI hspi(14,12,13,15) vspi(23,19,18,5)
I2C总线接口 I2C SDA(21) SCL(22) MicroPython并未实现硬件的I2C

6、连接ESP32、1306OLED、DHT22

根据GPIO引脚定义,OLED屏幕I2C连线如下

I2COLED:VCC -----> 3V3 ;GND -----> GND ;SCL -----> GPIO22;SDA -----> GPIO23

DHT22:+ -----> 3V3 ;- -----> GND ;Data -----> GPIO21

接口位置在规范下是可以随意使用的,只需要在程序中做对应改动就可以了。

7、驱动OLED

目前淘宝上0.96英寸的oled基本上都是ssd1306芯片,部分1.3寸oled屏是sh1106芯片。

通过EMPIDE(推荐)或者ampy把文件上传到ESP32,需要注意的是ampy上传文件的时候需要提前断开putty和ESP32的连接,因为COM口同一时间只能有一个程序占用。

I、把以下三个驱动文件上传到ESP32

ssd1306.pysh1106.pydht.py

ampy --port COM3 put C:\ssd1306.py
ampy --port COM3 put C:\sh1106.py
ampy --port COM3 put C:\dht.py
# ampy put上传、run运行、rm删除、终端查看文件内容 print(open('main.py').read()) 列出目录内容 os.listdir()

II、编写驱动程序

#I2C SH1106 OLED
from sh1106 import SH1106_I2C
from machine import Pin, I2C
i2c = I2C(scl=Pin(22), sda=Pin(23),freq=100000)
oled = SH1106_I2C(128, 64, i2c)
oled.line(0,32,128,32,1)
oled.text('Hello',36,2)
oled.text('Micropython',24,54)
oled.show()
#I2C SSD1306 OLED
from machine import Pin,I2C
from ssd1306 import SSD1306_I2C
i2c = I2C(scl=Pin(22), sda=Pin(23),freq=100000)
oled = SSD1306_I2C(128, 64, i2c)
oled.text('Hello',36,2)
oled.text('Micropython',24,54)
oled.show()

OLED购买前需要和卖家核对驱动芯片是SH1106还是SSD1306。同时OLED有I2C和SPI模式,区分就是一个四线一个七线。

8、驱动DHT22

dht22也被称为AM2302是一款具有标准单总线接口,含有已校准数字信号输出的温湿度复合传感器。

得益于Python的精简,驱动起来异常简单

import dht
import machine
from machine import Pin
from dht import DHT22
d = dht.DHT22(machine.Pin(21))
d.measure()
print("temperature:",d.temperature())
print("humidity:",d.humidity())

9、整合各系统完成最终产品

#main.py
import time
import dht
import machine
from sh1106 import SH1106_I2C
from machine import Pin, I2C
from dht import DHT22
i2c = I2C(scl=Pin(22), sda=Pin(23),freq=100000)
d = dht.DHT22(machine.Pin(21))
oled = SH1106_I2C(128, 64, i2c)
while True:
    d.measure()
    temp_ = str(d.temperature())
    hum_ = str(d.humidity())
    oled.text('temp:'+ temp_ +'C',10,2)
    oled.line(0,32,128,32,1)
    oled.text('hum:'+ hum_ +'%',10,18)
    oled.text('--Rc4x',80,50)
    oled.show()
    time.sleep(10)
    oled.fill(0)
    oled.show()

ESP32启动时会先从boot.py引导然后启动main.py,用户程序可以放到main.py

嗯、下雨了。


文章作者: Rc4x
版权声明: 本博客所有文章除特別声明外,均采用 CC BY 4.0 许可协议。转载请注明来源 Rc4x !