前回はMakerfabs 様よりいただいたLora通信 土壌センサの基本動作を堪能し、300m以上の伝達を確認いたしました。
土壌センサは単4電池2本で動作可能です。
ここでは、センサの長期動作を目指して消費電力を観測し低消費電力化を目指しました。
待機時の電流
通信していないときの待機電源電流を測定いたしました。
電源電圧は3.3Vとしました。
① デフォルト
サンプルコード LoraTransmitterADCAHT10.ino をそのまま書き込んだ時の待機電流です。
16.5 mA
② センサ電源OFF
サンプルコード LoraTransmitterADCAHT10.ino のL. 149のコメントアウトを解除して、測定後に温度湿度センサAHT10の電源を切ります。
15.5 mA
若干電流が低下しました。
③ マイコンスリープ
更に待機時にセンサ制御マイコンATmega328Pをスリープさせました。
Adafruitのウォッチドッグタイマでスリープを制御するライブラリを使用しました。
https://github.com/adafruit/Adafruit_SleepyDog
11.2 mA
④ Loraモジュール リセット
更にマイコンSleep前にLoraモジュール をリセットしてOFFしました。
0.1 mA以下
以上により大幅に待機電流を減らすことができました。
通信1回の消費電力
送信パワー 23dBm:約12.0 μW
送信パワー 5dBm: 約 1.2 μW
通信による消費は非常に小さかったです。
さすがLora!
伝送距離に応じて送信パワーを下げたり通信回数を制限するとより低消費電力化が見込めますね(あたりまえ)。
消費電力
1分間の消費電力を測定したしました。
それぞれ約9秒に1回センサ値を送信するように設定しました。
① デフォルト
サンプルコード LoraTransmitterADCAHT10.ino をそのまま書き込んだ時
1分当たり 1.1 mW 消費
④ Loraモジュール リセット
サンプルコードにセンサOFF、マイコンスリープ、Loraモジュールリセットを追加しました。
1分当たり 0.3 mW 消費
1/3以下の低消費電力化に成功いたしました。
Arduinoコード ④ Loraモジュール リセット
低消費電力版のArduinoコードを記載します。
サンプルコード LoraTransmitterADCAHT10.ino を元に
Adafruitのウォッチドッグタイマスリープライブラリを導入しコディングしました。
https://github.com/adafruit/Adafruit_SleepyDog
#include <SPI.h> #include "RH_RF95.h" #include <Adafruit_SleepyDog.h> #include "I2C_AHT10.h" #include <Wire.h> AHT10 humiditySensor; int sensorPin = A2; // select the input pin for the potentiometer int sensorValue = 0; // variable to store the value coming from the sensor int sensorPowerCtrlPin = 5; void sensorPowerOn(void){ digitalWrite(sensorPowerCtrlPin, HIGH);//Sensor power on } void sensorPowerOff(void){ digitalWrite(sensorPowerCtrlPin, LOW);//Sensor power on } #define RFM95_CS 10 #define RFM95_RST 4 #define RFM95_INT 2 // Change to 434.0 or other frequency, must match RX's freq! #define RF95_FREQ 915.0 // Singleton instance of the radio driver RH_RF95 rf95(RFM95_CS, RFM95_INT); void setup() { pinMode(RFM95_RST, OUTPUT); digitalWrite(RFM95_RST, LOW); delay(100); digitalWrite(RFM95_RST, HIGH); pinMode(sensorPowerCtrlPin, OUTPUT); sensorPowerOn(); //while (!Serial); Serial.begin(115200); delay(100); Wire.begin(); //Join I2C bus //Check if the AHT10 will acknowledge if (humiditySensor.begin() == false){ Serial.println("AHT10 not detected. Please check wiring. Freezing."); //while (1); } else Serial.println("AHT10 acknowledged."); Serial.println("Marduino LoRa TX Test!"); } int16_t packetnum = 0; // packet counter, we increment per xmission float temperature=0.0;// float humidity=0.0; void loop(){ setModule(); sensorPowerOn(); delay(100); sensorValue = analogRead(sensorPin); delay(200); if (humiditySensor.available() == true){ //Get the new temperature and humidity value temperature = humiditySensor.getTemperature(); humidity = humiditySensor.getHumidity(); //Print the results Serial.print("Temperature: "); Serial.print(temperature, 2); Serial.print(" C\t"); Serial.print("Humidity: "); Serial.print(humidity, 2); Serial.println("% RH"); //sensor off sensorPowerOff(); Serial.print(F("Moisture ADC : ")); Serial.println(sensorValue); //Serial.print(F("Humidity: ")); //Serial.print(humidity); //Serial.print(F("% Temperature: ")); //Serial.print(temperature); //Serial.println("Humidity is " + (String)humidity); //Serial.println("Temperature is " + (String)temperature); String message = "#"+(String)packetnum+" Humidity:"+(String)humidity+"% Temperature:"+(String)temperature+"C"+" ADC:"+(String)sensorValue; Serial.println(message); packetnum++; Serial.println("Transmit: Sending to rf95_server"); // Send a message to rf95_server uint8_t radioPacket[message.length()+1]; message.toCharArray(radioPacket, message.length()+1); radioPacket[message.length()+1]= '\0'; Serial.println("Sending..."); delay(10); rf95.send((uint8_t *)radioPacket, message.length()+1); Serial.println("Waiting for packet to complete..."); delay(10); rf95.waitPacketSent(); // Now wait for a reply uint8_t buf[RH_RF95_MAX_MESSAGE_LEN]; uint8_t len = sizeof(buf); Serial.println("Waiting for reply..."); delay(10); if(rf95.waitAvailableTimeout(8000)){ // Should be a reply message for us now if (rf95.recv(buf, &len)){ Serial.print("Got reply: "); Serial.println((char*)buf); Serial.print("RSSI: "); Serial.println(rf95.lastRssi(), DEC); } else{ Serial.println("Receive failed"); } } else{ Serial.println("No reply, is there a listener around?"); } Serial.print("Sleep!!"); // Lora module reset digitalWrite(RFM95_RST, LOW); delay(10); digitalWrite(RFM95_RST, HIGH); delay(10); //8sec sleep int sleepMS = Watchdog.sleep(); } } void setModule(void){ // manual reset digitalWrite(RFM95_RST, LOW); delay(10); digitalWrite(RFM95_RST, HIGH); delay(10); while(!rf95.init()) { Serial.println("LoRa radio init failed"); while (1); } Serial.println("LoRa radio init OK!"); //rf95.setModemConfig(Bw125Cr48Sf4096); //Defaults after init are 434.0MHz, modulation GFSK_Rb250Fd250, +13dbM if (!rf95.setFrequency(RF95_FREQ)) { Serial.println("setFrequency failed"); while (1); } Serial.print("Set Freq to: "); Serial.println(RF95_FREQ); // Defaults after init are 434.0MHz, 13dBm, Bw = 125 kHz, Cr = 4/5, Sf = 128chips/symbol, CRC on // The default transmitter power is 13dBm, using PA_BOOST. // If you are using RFM95/96/97/98 modules which uses the PA_BOOST transmitter pin, then // you can set transmitter powers from 5 to 23 dBm: rf95.setTxPower(23, false); }
センサ測定後、L. 84で温度湿度センサをOFFします。
測定データ送信後、L. 137-140でLoraモジュールをリセットします。
Loraモジュールをリセット後、L. 143でマイコンをSleepさせて
8秒後(ウォッチドッグタイマ最大値)にSleep解除されます。
Sleep解除後に、L. 63でLoraモジュールを初期化し
L. 65で温度湿度センサをONします。
以上を繰り返し約9秒おきにセンサデータを送信します。
おわりに
Lora通信 土壌センサの低消費電力化ができたので単4電池でどれほど持つのか
実験してみたいと思います。
技適未取得機器を用いた実験等の特例の届出の期限が来年1月までなので
どっちが先に切れるのか楽しみでございます。