This is my take on a battery node for temperature and humidity
I have used the slim 2AA battery node board from https://www.openhardware.io/view/10/My-Slim-2AA-Battery-Node
For the boot loader I used Gert Sanders bootloaders from https://www.openhardware.io/view/33/Various-bootloader-files-based-on-Optiboot-62
I used the 1Mhz internal clock with brown out detection disabled. In the arduino IDE these options were used:-
Board: "atmega328p based -28 pin DIL"
CPU Frequency, upload speed, LED: 1Mhz -9k6 -D13
Clock source: "1Mhz - internal 8Mhz CDIV 8"
Brown Out Detection: "Disabled"
I burned the boot loader using a Arduino Uno with my own hat based on the minimal arduino on a breadboard circuit https://www.arduino.cc/en/Tutorial/ArduinoToBreadboard. The UNO is loaded with the "Arduino as an ISP" sketch.
The image below is the top of the hat, the LED's are utilising the standard status indicators in the sketch. Green: Ready
Blue (middle): Programing
Red: Error.
Orange: linked to D13 for basic testing of chip, some bootloaders also load a basic blink program that also blinks this LED
The 6 pin header accepts a standard ftdi usb-serial programmer to load the code on the arduino chip
Bottom shows more of the wiring
The enclosure I used is a really handy little box with a builtin 2xAA or 1x9V battery holder available from my local (Australian) electronics supplier Jaycar
https://www.jaycar.com.au/black-hand-held-electronic-enclosure/p/HB5610
For battery monitoring I chose to use a voltage devider because I could not get any stabilty or accuracy with the internal vcc library when running the arduino at 1Mhz (or 8Mhz) internal occilator.
Here is my current code, it is based on https://forum.mysensors.org/topic/3049/slim-node-si7021-sensor-example/2
// Enable debug prints
#define MY_DEBUG
#define MY_BAUD_RATE 9600
// Enable and select radio type attached
#define MY_RADIO_NRF24
#include <Wire.h>
#include <Adafruit_Si7021.h>
#include <SPI.h>
#include <MySensors.h>
#define CHILD_ID_HUM 0
#define CHILD_ID_TEMP 1
//#define SLEEP_TIME 15000 // 15s for DEBUG
#define SLEEP_TIME 300000 // 5 min
#define FORCE_TRANSMIT_CYCLE 12 // 5min*12=1 hour
#define BATTERY_REPORT_CYCLE 12 // 5min*12=1 hour
#define VMIN 2000
#define VMAX 3200
#define HUMI_TRANSMIT_THRESHOLD 3.0 // THRESHOLD tells how much the value should have changed since last time it was transmitted.
#define TEMP_TRANSMIT_THRESHOLD 0.5
// to make it report the first time.
int measureCount = 0;
float lastTemperature = -100;
int lastHumidity = -100;
int batteryReportCounter = BATTERY_REPORT_CYCLE;
Adafruit_Si7021 sensor = Adafruit_Si7021();
int BATTERY_SENSE_PIN = A0; // select the input pin for the battery sense point
MyMessage msgHum(CHILD_ID_HUM, V_HUM);
MyMessage msgTemp(CHILD_ID_TEMP, V_TEMP);
void presentation()
{
// Send the sketch version information to the gateway
sendSketchInfo("TemperatureAndHumidity", "2.1");
// Register all sensors to gw (they will be created as child devices)
present(CHILD_ID_HUM, S_HUM);
present(CHILD_ID_TEMP, S_TEMP);
}
void setup()
{
analogReference(INTERNAL);
if (!sensor.begin()) {
Serial.println("Did not find Si7021 sensor!");
while (true);
}
}
void loop() {
measureCount ++;
batteryReportCounter ++;
bool forceTransmit = false;
#ifdef MY_DEBUG
Serial.print("Measure Count: "); Serial.println(measureCount);
Serial.print("Battery Report Count: "); Serial.println(batteryReportCounter);
#endif
if (measureCount > FORCE_TRANSMIT_CYCLE) {
forceTransmit = true;
#ifdef MY_DEBUG
Serial.println("Force Transmit");
#endif
}
sendTempHumidityMeasurements(forceTransmit);
// get the battery Voltage
int BatterysensorValue = analogRead(BATTERY_SENSE_PIN);
//float batteryVolt = BatterysensorValue * 0.003363075;
float batteryVolt = BatterysensorValue * 3.363075;
uint8_t batteryPcnt = constrain(map(batteryVolt,VMIN,VMAX,0,100),0,255);
#ifdef MY_DEBUG
Serial.print("Battery voltage: "); Serial.print(batteryVolt); Serial.println(" mV");
Serial.print("Battery percent: "); Serial.print(batteryPcnt); Serial.println(" %");
#endif
if (batteryReportCounter >= BATTERY_REPORT_CYCLE) {
#ifdef MY_DEBUG
Serial.println("Sending Battery Voltage");
#endif
sendBatteryLevel(batteryPcnt);
batteryReportCounter = 0;
}
sleep(SLEEP_TIME);
}
void sendTempHumidityMeasurements(bool force) {
#ifdef MY_DEBUG
Serial.println("Read Temp Sensor");
#endif
bool tx = force;
float temperature = sensor.readTemperature();
float diffTemp = abs(lastTemperature - temperature);
#ifdef MY_DEBUG
Serial.print("T: ");Serial.println(temperature);
Serial.print("TempDiff :");Serial.println(diffTemp);
#endif
if (diffTemp > TEMP_TRANSMIT_THRESHOLD || tx) {
//send(msgTemp.set(temperature,1));
resend((msgTemp.set(temperature, 1)), 5);
lastTemperature = temperature;
measureCount = 0;
#ifdef MY_DEBUG
Serial.println("T sent");
#endif
}
int humidity = sensor.readHumidity();
// raHum.addValue(humidity);
// humidity = raHum.getAverage(); // MA sample imply reasonable fast sample frequency
float diffHum = abs(lastHumidity - humidity);
#ifdef MY_DEBUG
Serial.print("H: ");Serial.println(humidity);
Serial.print("HumDiff :");Serial.println(diffHum);
#endif
if (diffHum > HUMI_TRANSMIT_THRESHOLD || tx) {
//send(msgHum.set(humidity));
resend((msgHum.set(humidity, 1)), 5);
lastHumidity = humidity;
measureCount = 0;
#ifdef MY_DEBUG
Serial.println("H sent");
#endif
}
}
// function to resend to gateway on failure
void resend(MyMessage & msg, int repeats) {
int repeat = 0;
int repeatdelay = 0;
boolean sendOK = false;
while ((sendOK == false) and(repeat < repeats))
{
if (send(msg))
{
sendOK = true;
}
else
{
sendOK = false;
Serial.print("Error ");
Serial.println(repeat);
repeatdelay += 250;
repeat++;
sleep(repeatdelay);
}
}
}
Here are a few more pictures of the sensor.
Looks a bit different here because this is my first build already in the case