911浏览
查看: 911|回复: 2

[ESP8266/ESP32] FireBeetle 2 ESP32 C6 试用——制作一个室外的温湿度气象站

[复制链接]
本帖最后由 aramy 于 2024-4-3 20:51 编辑

FireBeetle 2 ESP32 C6到手把玩了几天了。是时候去实现申请时定下的目标了:尝试一下esp32系列的低功耗功能。用太阳能电池板,制作一个室外的温湿度气象站。
首先分析使用场景:计划在房屋外边搭建一个气象站。离房屋不会太远,所以WiFi是能够覆盖到,计划使用物联网通讯,收集温湿度信息。虽然离房屋不远,但是室外是没有电源的,使用电池供电,就存在更换电池的问题,所以打算使用电池加太阳能板补能的方式解决能源问题。白天通过太阳能给锂电池补能,夜间就通过锂电池给单片机供电,同时单片机必须实现低功耗,用来节约电能。

ESP32低功耗可以通过睡眠模式实现。可以进入light-sleep和deep-sleep模式。
light-sleep:CPU暂停运行,wifi/蓝牙基带和射频关闭。RTC、ULP运行,任何唤醒事件都会唤醒芯片。数字外设、大部分内存和CPU都会被停用(停用时钟),电源功耗也会降低,从light-sleep模式下唤醒后外设和CPU会接回时钟源并继续工作,他们的外部状态会被保存。
deep-sleep:CPU、大部分外设掉电,wifi/蓝牙基带和射频关闭,进有RTC、ULP运行,wifi和蓝牙连接数据被转移到RTC内存中。仅有一部分中断源会唤醒芯片。由APB_CLK时钟提供是时钟源的CPU、大部分内存和所有数字外设都会掉电;只有片上RTC控制器、RTC外设、ULP和RTC内存会被保留电源。
了解了两种睡眠模式,这里当然就是去使用最节能的deep-sleep模式啦!有睡眠就要有唤醒,这里选用的是时间唤醒。
  1. esp_sleep_enable_timer_wakeup(time_in_us)
复制代码

FireBeetle 2 ESP32 C6 试用——制作一个室外的温湿度气象站图1

为了适应低功耗,就去掉了自制的扩展板。接了个额外的SHT30模块,使用板载的I2C接口,和模块连接起来。这里我使用了Arduino-sht的库,用来驱动SHT30;还使用了adafruit_mqtt库,这样收集到的信息就通过mqtt上传到物联网上了,这里物联网选用了百度的物联网平台。

FireBeetle 2 ESP32 C6 试用——制作一个室外的温湿度气象站图2

FireBeetle 2 ESP32 C6 试用——制作一个室外的温湿度气象站图3


与传统的Arduino编程方式有所区别。传统的Arduino运行方式为:step方法中对系统进行初始化,然后程序在loop方法中不停的循环。而使用deep-sleep方式工作,则每次唤醒都需要对系统进行初始化,包括连wifi、连mqtt、读取温湿度、上传传感器信息,然后进入deep-sleep状态,不停地重复。

FireBeetle 2 ESP32 C6 试用——制作一个室外的温湿度气象站图4

基本流程就比较简单,在连接wifi和连接mqtt过程中,遇到错误会重试,重试一定次数依然失败就进入睡眠状态,等待时钟的唤醒。
  1. #include<WiFi.h>
  2. #include <esp_sleep.h>
  3. #include "driver/rtc_io.h"
  4. #include "WiFiClient.h"
  5. #include "Adafruit_MQTT.h"
  6. #include "Adafruit_MQTT_Client.h"
  7. #include <Wire.h>
  8. #include "SHTSensor.h"
  9. #define WIFI_SSID "AAA"
  10. #define WIFI_PASSWORD "xxxxxxxx"
  11. const char *MQTT_SERVER = "afgsmmu.iot.gz.baidubce.com";
  12. const int MQTT_PORT = 1883;
  13. const char *MQTT_USRNAME = "your_mqtt_username";
  14. const char *MQTT_PASSWD = "your_mqtt_passwd";
  15. const char *TOPIC = "$iot/AICAM/user/ismask";
  16. WiFiClient espClient;
  17. Adafruit_MQTT_Client mqtt(&espClient, MQTT_SERVER, MQTT_PORT, MQTT_USRNAME, MQTT_PASSWD);
  18. Adafruit_MQTT_Publish pub = Adafruit_MQTT_Publish(&mqtt, TOPIC); // 发布主题
  19. #define ANALOG_PIN_0   0   //电池AD管脚
  20. SHTSensor sht;
  21. #define uS_TO_S_FACTOR 1000000ULL   //计时单位 秒
  22. void mcusleep() {
  23.   digitalWrite(15, LOW);      //关灯
  24.   Serial.flush();
  25.   esp_deep_sleep_start();
  26. }
  27. void MQTT_connect()//连接mqtt服务器,5s连接一次  连接超过5次还连不上 就休眠
  28. {
  29.   int8_t ret;
  30.   if (mqtt.connected())
  31.   {
  32.     return;
  33.   }
  34.   Serial.print("Connecting to MQTT... ");
  35.   uint8_t retries = 5;//尝试5次
  36.   while ((ret = mqtt.connect()) != 0)
  37.   {
  38.     Serial.println(mqtt.connectErrorString(ret));
  39.     Serial.println("Retying MQTT connection in 5 seconds...");
  40.     mqtt.disconnect();
  41. //    digitalWrite(15, LOW);      //关灯
  42.     delay(5000);
  43.     retries--;
  44.     if (retries == 0) //如果五次都没连接上进入死循环
  45.     {
  46.       esp_sleep_enable_timer_wakeup(60 * uS_TO_S_FACTOR);
  47.       Serial.println("MQTT connect fail! Going to sleep now");
  48.       mcusleep();
  49.     }
  50.     Serial.println("MQTT Connected!");
  51.   }
  52. }
  53. void setup() {
  54.   Serial.begin(115200);
  55.   pinMode(15, OUTPUT);
  56.   digitalWrite(15, HIGH);       //亮灯
  57.   //  rtc_gpio_isolate(GPIO_NUM_15);
  58.   Wire.begin();
  59.   pinMode(ANALOG_PIN_0, INPUT);     //电源电池电压测量
  60.   uint8_t retries = 10;//尝试连接wifi 10次
  61.   WiFi.begin(WIFI_SSID, WIFI_PASSWORD);
  62.   while (!WiFi.isConnected())
  63.   {
  64.     digitalWrite(15, LOW);      //关灯
  65.     delay(5000);
  66.     digitalWrite(15, HIGH);       //亮灯
  67.     retries--;
  68.     Serial.print(".");
  69.     if (retries == 0) //如果五次都没连接上进入死循环
  70.     {
  71.       esp_sleep_enable_timer_wakeup(60 * uS_TO_S_FACTOR);
  72.       Serial.println("wifi connect fail! Going to sleep now");
  73.       mcusleep();
  74.     }
  75.   }
  76.   Serial.println("WIFI connect success!");
  77.   MQTT_connect();
  78.   sht.init();
  79.   sht.setAccuracy(SHTSensor::SHT_ACCURACY_MEDIUM); // only supported by SHT3x
  80. }
  81. void loop() {             //空循环
  82.   uint analog_value = 0;
  83.   char msg[100];
  84.   analog_value = analogRead(ANALOG_PIN_0);  //读取电池电压
  85.   sht.readSample();                     //读取sht30
  86.   Serial.printf("bat:%.1f\t RH:%.2f\t T:%.2f\n", float(analog_value) / 497.5, sht.getHumidity(), sht.getTemperature());
  87.   sprintf(msg, "{"Bat":%.2f,"Humidity":%.2f,"Temperature":%.2f}", float(analog_value) / 497.5, sht.getHumidity(), sht.getTemperature());
  88.   Serial.println(msg);
  89.   pub.publish(msg);
  90.   esp_sleep_enable_timer_wakeup(30 * uS_TO_S_FACTOR);
  91.   Serial.println("Finsh work! Going to sleep now");
  92.   delay(100);
  93.   mcusleep();
  94.   delay(10000);     //代码到不了这里
  95. }
复制代码

FireBeetle 2 ESP32 C6 试用——制作一个室外的温湿度气象站图7
这里有几个地方需要注意的:
1、管脚0,是接到通过电阻分压后的电源上,可以通过管脚0测量电源电池的电压。
2、板子一旦进入deep-sleep状态了,那么就是连串口都会消失掉的。所以在调试烧写代码时,会找不到串口号,无法烧写。此时烧写板子就需要按住板子上的BOOT按键,再按下RST按键,然后松开,进入烧写模式,即可有串口出现,此时可以正常烧写。
FireBeetle 2 ESP32 C6 试用——制作一个室外的温湿度气象站图5

FireBeetle 2 ESP32 C6 试用——制作一个室外的温湿度气象站图6




使用Python写个简单的上位机,用来接收mqtt的消息,只是简单地测试一下物联网。接下来就是要使用电池做测试,看看一天能耗电池多少电量,然后决定用多大的太阳能板进行补能。
  1. #!/usr/bin/env python
  2. # -*- coding:utf-8 -*-
  3. # @FileName  :mqtt_recvmsg.py
  4. # @Time      :2024/3/25 11:20
  5. # @Author    :aramy
  6. import paho.mqtt.client as mqtt
  7. from unit.mqttinfo import MQTT_INFO
  8. class MqttMsg():
  9.     def __init__(self):
  10.         super(MqttMsg, self).__init__()
  11.         self.mqttinfo=MQTT_INFO()
  12.         self.client=mqtt.Client()
  13.         self.message=""
  14.     def on_connect(self,client, userdata, flags, rc):
  15.         print("Connected with result code: " + str(rc))
  16.     def on_message(self,client, userdata, msg):
  17.         print(msg.topic + " " + str(msg.payload))
  18.         # self.sinGetNewMsg.emit(str(msg.payload,encoding = "utf-8"))
  19.     def run(self):
  20.         self.client.username_pw_set(self.mqttinfo.mqtt_name, self.mqttinfo.mqtt_pwd)  # 设置用户名,密码
  21.         self.client.connect(self.mqttinfo.broker_address, self.mqttinfo.port, 60)  # 连接服务 keepalive=60
  22.         self.client.on_connect = self.on_connect
  23.         self.client.on_message = self.on_message
  24.         self.client.subscribe(self.mqttinfo.publishtopic[0], qos=0)
  25.         self.client.loop_forever()  # 保持连接
  26. if __name__ == "__main__":
  27.     mqtt=MqttMsg()
  28.     mqtt.run()
复制代码




余老师  见习技师

发表于 2024-4-6 20:31:33

如果我想从I2C接口获取其他的传感器数据,是不是还得用其他的库文件?
回复

使用道具 举报

aramy  初级技师
 楼主|

发表于 2024-4-8 22:13:44

余老师 发表于 2024-4-6 20:31
如果我想从I2C接口获取其他的传感器数据,是不是还得用其他的库文件?

库文件 一般是针对具体传感器的。走i2c协议都是试用wire文件了。所以 要是能找到具体的库文件,就要加载库文件,找不到的话,就用wire自己写方法了。
回复

使用道具 举报

您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

为本项目制作心愿单
购买心愿单
心愿单 编辑
[[wsData.name]]

硬件清单

  • [[d.name]]
btnicon
我也要做!
点击进入购买页面
上海智位机器人股份有限公司 沪ICP备09038501号-4

© 2013-2024 Comsenz Inc. Powered by Discuz! X3.4 Licensed

mail