460|0

5

帖子

3

TA的资源

一粒金砂(中级)

楼主
 

【得捷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

 

点赞 关注
 
 

回复
举报
您需要登录后才可以回帖 登录 | 注册

随便看看
查找数据手册?

EEWorld Datasheet 技术支持

相关文章 更多>>
关闭
站长推荐上一条 1/7 下一条

 
EEWorld订阅号

 
EEWorld服务号

 
汽车开发圈

About Us 关于我们 客户服务 联系方式 器件索引 网站地图 最新更新 手机版

站点相关: 国产芯 安防电子 汽车电子 手机便携 工业控制 家用电子 医疗电子 测试测量 网络通信 物联网

北京市海淀区中关村大街18号B座15层1530室 电话:(010)82350740 邮编:100190

电子工程世界版权所有 京B2-20211791 京ICP备10001474号-1 电信业务审批[2006]字第258号函 京公网安备 11010802033920号 Copyright © 2005-2025 EEWORLD.com.cn, Inc. All rights reserved
快速回复 返回顶部 返回列表