• <table id="0ws66"></table>
  • <noscript id="0ws66"><source id="0ws66"></source></noscript>
    貓-氣象站

    貓-氣象站的詳細介紹

    創作者: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來整合器件和接口。

    国产综合在线