【得捷Follow me第3期】基于wifi的边缘数据记录仪
[复制链接]
本帖最后由 林太太 于 2023-12-11 12:08 编辑
必做任务1:使用MicroPython系统
首先先去micropython官方网站下载固件,下载C3的通用generic固件即可,记得下载的固件文件格式为bin,方便后续使用esptool进行安装。
接下来去乐鑫的官方github下载esptool,这是一个cmd工具,用来给C3刷写bin固件。
完成后把之前下载的bin文件移动到esptool根目录下,并重命名为firmware.bin。
插入XIAO C3,并在设备管理器里查看到相应的端口号,假设端口号为COM3
最后只需要在esptool根目录下打开cmd,并输入命令 esptool.exe --chip esp32c3 --port COM3 --baud 921600 --before default_reset --after hard_reset --no-stub write_flash --flash_mode dio --flash_freq 80m 0x0 firmware.bin 即可完成刷写,看到如下界面就算刷写成功
完成烧写后我们可以写一个简单的命令看看micropython有没有正常运行。我使用的是Thonny,在命令窗口写下一个python命令,可以收到反馈,说明micropython已正常工作。
必做任务2:驱动扩展板上的OLED屏幕
这里需要一个第三方库来驱动OLED,将ssd1306.py文件上传到开发板根目录,或lib目录都可。这里我们把后续任务需要的另一个库umqttsimple.py也一并放入。接下来进入我们的主程序文件main.py,导入整个项目所需的所有库文件:
import machine
import network
import ntptime
import time
from umqttsimple import MQTTClient
import json
from ssd1306 import SSD1306_I2C
import dht
接着写入以下初始化,就可以使用屏幕。我们简单在屏幕四周画两个框,并在中间显示文字,以验证功能。
i2c = machine.SoftI2C(sda=machine.Pin(9), scl=machine.Pin(10))
print(i2c.scan())
oled = SSD1306_I2C(128, 64, i2c)
oled.fill(1)
oled.rect(1, 1, 126, 62, 0)
oled.rect(3, 3, 122, 58, 0)
oled.text('Hello World!', 17, 29, 0)
oled.show()
必做任务3:控制蜂鸣器播放音乐
要实现蜂鸣器播放音乐,记得一定要使用无源蜂鸣器。有源蜂鸣器内置了震荡源,只能发出固定频率的声响。而无源蜂鸣器的震荡频率来源于单片机,因此可以发出不同频率的声音。这里我们使用micropython内置的PWM方法实现。首先先定义各个音高所代表的对应频率,接着我们封装一个函数,函数的功能是可以按字符串顺序一个一个的发出对应的频率。接下来我们将谱子以简谱方式写下,最后用我们自己封装的函数播放即可。
由于我使用的是面包板,而且又不想额外飞线,因此这里做了一个比较特殊的处理,我把GPIO引脚当作供电和地来使用:
vcc0 = machine.Pin(3, mode=machine.Pin.OUT, value=1, drive=machine.Pin.DRIVE_3)
gnd0 = machine.Pin(2, mode=machine.Pin.OUT, value=0, drive=machine.Pin.DRIVE_3)
将引脚设为数字输出模式,并将驱动力调至最大,一个引脚输出1,另一个输出0,就可以在供电要求不高的场合作为vcc和gnd来使用。目前测试下来一切正常。
def play(pin, melody):
tones = {'1': 262, '2': 294, '3': 330, '4': 349, '5': 392, '6': 440, '7': 494, '-': 0}
beeper = machine.PWM(machine.Pin(pin, machine.Pin.OUT))
for tone in melody:
freq = tones[tone]
if freq:
beeper.init(duty=1000, freq=freq) # 调整PWM的频率,使其发出指定的音调
else:
beeper.duty(0) # 空拍时不上电
# 停顿一下 (四四拍每秒两个音,每个音节中间稍微停顿一下)
time.sleep_ms(400)
beeper.duty(0) # 设备占空比为0,即不上电
time.sleep_ms(100)
beeper.deinit() # 释放PWM
melody = "1155665-4433221-5544332-5544332-1155665-4433221"
vcc0 = machine.Pin(3, mode=machine.Pin.OUT, value=1, drive=machine.Pin.DRIVE_3)
gnd0 = machine.Pin(2, mode=machine.Pin.OUT, value=0, drive=machine.Pin.DRIVE_3)
play(4, melody)
必做任务4:连接WiFi网络
由于micropython自身的一些问题,wifi可能会卡在显示未连接,实际也未连接,但无法再次连接的情况。因此在wifi连接的函数中加入了一些异常处理的代码。连接上wifi后,会显示出ip,mac等相关信息,方便我们观察到已连接。随后,为了验证wifi功能,我使用了micropython内置的ntp库在互联网上同步了一下时间,并将时间显示在屏幕上。
def wifi():
sta_if = network.WLAN(network.STA_IF)
if not sta_if.isconnected():
print('connecting to network...')
try:
sta_if.active(True)
sta_if.disconnect()
sta_if.connect(ssid, password)
except Exception as error:
print(error)
sta_if.disconnect()
sta_if.active(False)
while not sta_if.isconnected():
pass
print('WiFi Connected:', sta_if.ifconfig())
print("")
def ntp_get():
for i in range(10): # 最多尝试获取10次
try:
ntptime.settime() # 获取网络时间
_t=machine.RTC().datetime()
machine.RTC().datetime((_t[0],_t[1],_t[2],_t[3],_t[4]+8,_t[5],_t[6],_t[7]))
print("ntp time(BeiJing): ", machine.RTC().datetime())
return True
except:
print("Can not get time!")
time.sleep_ms(500)
wifi()
ntp_get()
datetime = machine.RTC().datetime()
oled.fill(1)
oled.rect(1, 1, 126, 62, 0)
oled.rect(3, 3, 122, 58, 0)
oled.text('Date:', 5, 6, 0)
oled.text(str(datetime[0]) + "-" + str(datetime[1]) + "-" + str(datetime[2]), 5, 6 + 12, 0)
oled.text('Time:', 5, 33, 0)
oled.text(str(datetime[4]) + ":" + str(datetime[5]) + ":" + str(datetime[6]), 5, 33 + 12, 0)
oled.show()
必做任务5:使用外部传感器
这个项目我选用的外部传感器是arduino常用的DHT11,这个传感器在3.3V下也可以正常工作。但需要注意的是这个传感器速度比较慢,每秒只可读取一次数值,而且micropython中如果读取数值出错,会直接报错并终止程序运行。为了避免一定概率会发生的出错导致整个系统宕机,这里使用了try方法。并且,如果是连续读取,不要忘记确保每次读取间隔不小于1秒。
d = dht.DHT11(machine.Pin(7))
vcc1 = machine.Pin(21, mode=machine.Pin.OUT, value=1, drive=machine.Pin.DRIVE_3)
gnd1 = machine.Pin(6, mode=machine.Pin.OUT, value=0, drive=machine.Pin.DRIVE_3)
def measure():
d.measure()
oled.fill(1)
oled.rect(1, 1, 126, 62, 0)
oled.rect(3, 3, 122, 58, 0)
oled.text('Temperature:', 5, 6, 0)
oled.text(str(d.temperature()) + " degree", 5, 6 + 12, 0)
oled.text('Humidity:', 5, 33, 0)
oled.text(str(d.humidity()) + " %", 5, 33 + 12, 0)
oled.show()
return d.temperature(), d.humidity()
while True:
try:
measure()
break
except Exception as error:
print(error)
time.sleep(1)
可选任务6:温湿度数据记录仪
这次项目的硬件除了XIAO C3外,我还带了两块树莓派zero,打算用在数据记录仪的制作中。因为xiao C3作为传感器模块,工作环境较为恶劣,不适合用作数据储存记录。一般的做法是xiao c3作为边缘传感器仅负责数据测量,测量到数据后通过网络发送回服务器,服务器配有专门的数据记录硬件,负责进行记录。这里两块树莓派zero就是充当了中央服务器的功能,一个树莓派作为MQTT服务器,负责数据的发送及接受;另一块树莓派和XIAO C3一样,作为MQTT客户端,负责数据的记录。
先看下XIAO C3部分的代码。数据以JSON字符串的形式进行发送:
def callback(topic, msg):
print((topic, msg))
if topic == topic_sub and msg == b'hello':
print('ESP received hello message')
def connect_and_subscribe():
client = MQTTClient(
client_id = client_id,
server = mqtt_server,
port = port,
user = user,
password = pwd,
keepalive = 10,
lw_topic = topic_availability,
lw_msg = "offline"
)
client.set_callback(callback)
client.connect()
client.subscribe(topic_sub)
client.publish(topic_availability, "online")
print('Connected to %s MQTT broker, subscribed to %s topic' % (mqtt_server, topic_sub))
return client
def restart_and_reconnect():
print('Failed to connect to MQTT broker. Reconnecting...')
machine.reset()
try:
client = connect_and_subscribe()
except:
restart_and_reconnect()
def loop():
time.sleep(1)
client.check_msg()
temperature, humidity = measure()
msg = json.dumps({"temperature" : temperature, "humidity" : humidity})
client.publish(topic_pub, msg)
print("Published: " + msg)
while True:
try:
loop()
except Exception as error:
print(error)
try:
wifi()
client = connect_and_subscribe()
except:
restart_and_reconnect()
接着我们需要在第一块树莓派上搭建一个MQTT服务器,搭建方法比较简单,先运行以下命令完成安装:
sudo apt update
sudo apt upgrade
sudo apt install mosquitto
sudo echo "listener 1883" >> /etc/mosquitto/mosquitto.conf
sudo echo "allow_anonymous true" >> /etc/mosquitto/mosquitto.conf
sudo systemctl restart mosquitto
接着在第二块树莓派上安装MQTT客户端,并订阅对应的topic,并将收到的数据记录到log文件中:
sudo apt update
sudo apt upgrade
sudo apt install mosquitto-clients
mosquitto_sub -h 192.168.50.231 -t "sensor/c3/pub" | tee -a log.txt
收到一段数据后,我们随时停止,并查看log记录,发现所有数据都有被正常记录。
源码下载:https://download.eeworld.com.cn/detail/%E6%9E%97%E5%A4%AA%E5%A4%AA/630254
|