I recently configured multiple Whispernode sensors (https://wisen.com.au/) around the house but the power handling is not so good. Whispernode is based on Atmel AVR ATMega328p. I am using CR2032 battery and the battery is drained in approximately 8 days allthough I know people have got better results with this setup.
Here is my code from a node that measures temperature and humidity via a DHT22 sensor and sends it to a master node using 433MHZ radio: https://p.dnaip.fi/a3jz8vPzCdnZ4pbU
Is there anything I can improve / optimize the code to make the battery last longer?
Ok, my apologies I see the secure aspect on that. Here is the code:
/*
* Bedroom node
*/
#include <T2WhisperNode.h>
#include <LowPower.h>
#include <DHT.h>
#include <RH_RF69.h>
// DHT 22
#define DHT_PWD_PIN A2 // We power the DHT11 via a MCU GPIO so we can control when it's up or not
#define DHT_DATA_PIN A1
#define DHT_TYPE DHT22
DHT dht(DHT_DATA_PIN, DHT_TYPE);
// SPI Flash
T2Flash myFlash;
// RFM69 Radio
#define RADIO_FREQUENCY 433.0
#define RADIO_TX_POWER 13
#define RADIO_ENCRYPTION_KEY { 0x00, 0x03, 0x01, 0x00, 0x01, 0x09, 0x08, 0x06, 0x02, 0x05, 0x00, 0x05, 0x01, 0x09, 0x08, 0x05 }
RH_RF69 myRadio;
uint8_t radioBuf[(T2_MESSAGE_HEADERS_LEN + T2_MESSAGE_MAX_DATA_LEN)];
// T2 Message
T2Message myMsg;
#define nodeAddr 0x88
#define baseAddr 0x0B
void setup()
{
// Serial
Serial.begin(115200);
Serial.println(F("Example: DHT22 Sensor Node"));
Serial.println(F("Putting Radio and SPI Flash to Sleep"));
// Radio - Initialize the radio and put it to sleep to save energy
myRadio.init();
myRadio.setModemConfig(RH_RF69::FSK_Rb125Fd125);
myRadio.setFrequency(RADIO_FREQUENCY);
uint8_t myRadioEncryptionKey[] = RADIO_ENCRYPTION_KEY;
myRadio.setEncryptionKey(myRadioEncryptionKey);
myRadio.setTxPower(RADIO_TX_POWER);
myRadio.sleep();
// Flash - We're not using, so just power it down to save energy
myFlash.init(T2_WPN_FLASH_SPI_CS);
myFlash.powerDown();
// DHT22
digitalWrite(DHT_PWD_PIN, LOW);
pinMode(DHT_PWD_PIN, OUTPUT);
dht.begin();
// Setup the Blue LED pin
digitalWrite(T2_WPN_LED_1, LOW); // Set LED to Off
pinMode(T2_WPN_LED_1, OUTPUT); // Set LED pint to OUTPUT
// Blink the blue led once at the boot
digitalWrite(T2_WPN_LED_1, HIGH);
delay(5);
digitalWrite(T2_WPN_LED_1, LOW);
}
uint8_t loopCount = 75;
void loop()
{
// We only do something every 38 sleep cycles (38 * 8 = 300 seconds)
if(loopCount == 75)
{
// Do some work!
sendTestVoltage(1);
sendTestVoltage(2);
sendTempHumidity();
loopCount = 0;
}
// Using Low-Power library to put the MCU to Sleep
LowPower.powerDown(SLEEP_8S, ADC_OFF, BOD_OFF);
loopCount++;
}
void sendTempHumidity()
{
// Turn the Sensor ON
digitalWrite(DHT_PWD_PIN, HIGH);
//Wait a bit for the sensor to wake up
delay(750);
// Read temperature as Celsius * 100 to remove any decimals
// False, True means we don't want Fahrenheit and we want to force the reading.
int16_t t = dht.readTemperature(false, true) * 100;
// * 100 to remove any decimals. We do not force the reading, so we use the last info
uint16_t h = dht.readHumidity() * 100;
//Turn the Sensor OFF
digitalWrite(DHT_PWD_PIN, LOW);
// For Debbuging only
//Serial.println(t);
//Serial.println(h);
//delay(10);
// Prepare Temperature Message and send
myMsg.cmd = 0x03; // Return Data
myMsg.idx = 0x05; // HID and Sensors
myMsg.sdx = 0x0a; // Temperature
myMsg.data[0] = 0x01; // Operation Temp in Celcius * 100
myMsg.data[1] = 0x01; // Sensor ID - we only have 1 in this case
myMsg.data[2] = t >> 8;
myMsg.data[3] = t;
myMsg.len = 4; // Update length
sendMessage();
// Now change message details with the Humidity details and send it
myMsg.cmd = 0x03; // Return Data
myMsg.idx = 0x05; // HID and Sensors
myMsg.sdx = 0x0b; // Humidity
myMsg.data[0] = 0x01; // Operation Humidity in % * 100
myMsg.data[1] = 0x01; // Sensor ID - we only have 1 in this case
myMsg.data[2] = h >> 8;
myMsg.data[3] = h;
myMsg.len = 4; // Update length
sendMessage();
}
void sendTestVoltage(uint8_t supply)
{
uint16_t voltage = 0;
// Get Voltage readings from supply/battery
if(supply == 1)
{
voltage = T2Utils::readVoltage(T2_WPN_VBAT_VOLTAGE, T2_WPN_VBAT_CONTROL);
myMsg.sdx = 0x64; // Battery
}
if(supply == 2)
{
voltage = T2Utils::readVoltage(T2_WPN_VIN_VOLTAGE, T2_WPN_VIN_CONTROL);
myMsg.sdx = 0x65; // Supply
}
// Fill the message details and send it
myMsg.cmd = 0x03; // Return Data
myMsg.idx = 0x06; // Node Info
myMsg.data[0] = 0x01; // Operation Last Reading
myMsg.data[1] = 0x01; // Battery/Supply Index, if multiple supplies
myMsg.data[2] = voltage >> 8;
myMsg.data[3] = voltage;
myMsg.len = 4; // Update length
sendMessage();
}
void sendMessage()
{
uint8_t radioBufLen = 0;
// Prepare the Message headers
myMsg.src = nodeAddr;
myMsg.dst = baseAddr;
// Encode Message and get the full length
myMsg.getSerializedMessage(radioBuf, &radioBufLen);
// Send it
myRadio.send(radioBuf, radioBufLen);
myRadio.waitPacketSent(100);
myRadio.sleep();
}