創作者:KanameAimu | 更新日期:2022-04-14 | 在線時長:146天
西安天氣
簡介
本項目是一個基于Arduino和NRF24L01的環境監測硬件。
能實時獲取當前氣溫,氣壓,光照,濕度,降水,PM2.5值,以及自身的電池電量,使用2.4G模塊傳到網關節點,再由節點上傳到云。
節點本身不接受信息,僅以40s的間隔采集并發送數據。
硬件構成
主控:Arduino Pro Mini(5V/16MHz)
通信:NRF24L01+
氣溫:BMP180(0.01) DS18B20(0.50)
氣壓:BMP180(0.01)
光照:GY-30(IC為BH1750FVI)
濕度:DHT11(1)
降水:PCB 雨滴模塊(他的編號是YL-83)
PM2.5:GP2Y1010AU0F
供電:18650一節
關于節電
由于設備處于陽臺的位置,因此有線供電較為麻煩,太陽能供電也麻煩,所以采用可更換的18650鋰電池供電;
電池供電方案顯然要考慮能耗問題,因此有通信選擇的問題:有esp01(WiFi)和NRF24L01(2.4G)可供選擇。
ESP8266是耗電模塊(工作:80mA(264mW),最高:200mA(660mW)),而NRF24L01+工作電流只有11.3mA(TX,0dbm)和13.5mA(RX),掉電模式電流僅為900nA,顯然是一個比較好的選擇。
一個合理的選擇是設備用NRF將數據發送到室內的節點,這個節點再將數據傳到云。室內節點可以使用電源供電,不存在能耗問題。
Promini和3v3和雨滴模塊上都有LED,這些也很耗電(每個10到20mA),因此全部焊掉。
空氣質量之前采用的是MQ135,但是這個東西由于要電熱,非常耗電。資料上提到加熱功率居然有900mW(!)。于是用低功耗的粉塵模塊替換之。
為減小工作電流以獲得盡可能長的工作時間,設備絕大多數時間進入睡眠模式(使用LowPower庫),利用watchdog周期性醒來發送數據,然后立刻回到睡眠模式。
nrf24l01模塊也需要同時睡眠和醒來,使用Mirf庫里的powerDown()命令。
這樣設計的待機電流:9.6mA(36mW),工作電流31mA(120mW),一節3000mAh的電池能工作12天左右。
電路設計
用EasyEDA畫了下原理圖,先在面包板上搭建了實驗電路,再焊到一塊5x7cm的洞洞板上。所有模塊都采用可更換式的設計,同時保證布局盡可能緊湊。
由于雨滴模塊和光照模塊都要安裝在陽臺邊,因此預留了接口。使用的時候用線連接出去。
EasyEDA鏈接:https://easyeda.com/KanameAimu/WeatherStation-e9dae2dacdea4157baf0bea2717fbf6c
原理圖
成品圖
室內節點
室內節點使用了一個ArduinoProMini+NRF24L01用于接收NRF鏈路數據并處理,以及一個Wemos D1用來提供WiFi通信。二者之間用I2C總線實現通信。由于工作電壓不同,中間使用一個txs0108e模塊做電平轉換。
基本的功能是存儲轉發,還有一些附加的功能,例如在1602上顯示收到的數據等。
Wemos D1是一個Arduino兼容的ESP8266開發板,可以直接使用Arduino IDE和很多的庫,非常方便。這里用來從promini拿數據并上傳到bigiot。
外形設計
接下來就是3D打印個盒子來安裝電路板和固定傳感器。模型設計使用OpenSCAD,生成STL切片后打印。
盒子
上面的部分用來固定18650電池盒,左下用來固定GP2Y1010傳感器,右下用來固定DHT11模塊。懸空的地方設計了支撐方便打印。
盒蓋
采用卡扣式設計,將DHT11線,下載口和BMP180口留了出來。
完成后如圖。
成品圖
軟件設計
設備需要采集數據并放入緩沖區,用nrf模塊發送,然后再用LowPower.powerDown。
電池電壓數據在傳感器工作前采集一次,傳感器工作后再采集一次取平均。
DS18B20是備用溫度計。BMP180出問題后才使用,實際硬件可以不用。
另外注意ArduinoProMini(ATMega328P-AU)的int是16位,float=double=32位,要注意數據包和32位系統的兼容性。
數據包格式:
字節 | 類型 | 數據 |
0 | byte | 設備ID |
1 | byte | 包ID |
2 | uint16_t | 電池電壓 |
4 | uint16_t | 雨滴傳感器電壓 |
6 | float | 粉塵傳感器電壓 |
10 | uint16_t | 光照數值 |
12 | float | 氣壓 |
16 | float | 氣溫 |
20 | byte | 濕度 |
21~31 | 保留 |
代碼摘要:
void loop() {
char data[Mirf.payload];
data[0] = device_id;
data[1] = packet_id;
packet_id++;
int battery_value_1 = analogRead(PIN_BatteryVoltage);
int rain_value = analogRead(PIN_RAIN_SENSOR);
data[4] = *(((byte *)&rain_value)+0);
data[5] = *(((byte *)&rain_value)+1);
float dust_volt = getSharpDustSensorVoltage();
data[6] = *(((byte *)&dust_volt)+0);
data[7] = *(((byte *)&dust_volt)+1);
data[8] = *(((byte *)&dust_volt)+2);
data[9] = *(((byte *)&dust_volt)+3);
unsigned int brightness_val = (unsigned int)getGY30Reading();
data[10] = *(((byte *)&brightness_val)+0);
data[11] = *(((byte *)&brightness_val)+1);
float pres,temp;
if(!getBMP180Readings(&pres, &temp))
{
pres = 0;
temp = getDS18B20Temp();
}
data[12] = *(((byte *)&pres)+0);
data[13] = *(((byte *)&pres)+1);
data[14] = *(((byte *)&pres)+2);
data[15] = *(((byte *)&pres)+3);
data[16] = *(((byte *)&temp)+0);
data[17] = *(((byte *)&temp)+1);
data[18] = *(((byte *)&temp)+2);
data[19] = *(((byte *)&temp)+3);
data[20] = getDHT11Humidity();
int battery_value_2 = analogRead(PIN_BatteryVoltage);
int battery_value = (battery_value_1 + battery_value_2) / 2;
data[2] = *(((byte *)&battery_value)+0);
data[3] = *(((byte *)&battery_value)+1);
for(int i=21;i<32;i++)
{
data[i] = 0;
}
Mirf.setTADDR((byte *)"iotc1");
Mirf.send(data);
while(Mirf.isSending());
Mirf.powerDown();
LowPower.powerDown(SLEEP_8S, ADC_OFF, BOD_OFF);
LowPower.powerDown(SLEEP_8S, ADC_OFF, BOD_OFF);
LowPower.powerDown(SLEEP_8S, ADC_OFF, BOD_OFF);
LowPower.powerDown(SLEEP_8S, ADC_OFF, BOD_OFF);
LowPower.powerDown(SLEEP_8S, ADC_OFF, BOD_OFF);
}
全部代碼和設計文件可以在我的GitHub上找到:https://github.com/KanameAimu/WeatherStation
此文章歡迎轉載,轉載請注明作者和原始鏈接。
2016-11-28
查了下ESP8266的功耗。DeepSleep有10mA(33mW),有個待機模式似乎是0.9uA,不過問題是8266只有1個ADC,本項目至少需要2個。
而且不想用那么多WiFi設備連路由器,個人認為還是控制中心這種設計比較好。各設備用nrf構成局域網。
8266的3.3v電壓也是個問題,因為GP2Y要5v,還有dht11什么的東西,還是用arduino比較方便。
2019-10-9
數據包裝其實可以用union解決。理論上可以用三極管給模塊供電,可以進一步降低功耗。
還是不想拿8266當節點。可能是怕麻煩吧。
近期打算畫個pcb來整合器件和接口。