Temperature and Humidity with SI7021 on Slim 2AA Battery Node 1Mhz

  • 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

    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.
    // 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()
      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);
      if (measureCount > FORCE_TRANSMIT_CYCLE) {
        forceTransmit = true; 
        #ifdef MY_DEBUG
          Serial.println("Force Transmit");
      // 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(" %");
      if (batteryReportCounter >= BATTERY_REPORT_CYCLE) {
        #ifdef MY_DEBUG
        Serial.println("Sending Battery Voltage");
        batteryReportCounter = 0;
    void sendTempHumidityMeasurements(bool force) {
      #ifdef MY_DEBUG
        Serial.println("Read Temp Sensor");
      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);
      if (diffTemp > TEMP_TRANSMIT_THRESHOLD || tx) {
        resend((msgTemp.set(temperature, 1)), 5);
        lastTemperature = temperature;
        measureCount = 0;
        #ifdef MY_DEBUG
        Serial.println("T sent");
      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); 
      if (diffHum > HUMI_TRANSMIT_THRESHOLD || tx) {
      resend((msgHum.set(humidity, 1)), 5);
      lastHumidity = humidity;
      measureCount = 0;
      #ifdef MY_DEBUG
      Serial.println("H sent");
    // 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;
          sendOK = false;
          Serial.print("Error ");
          repeatdelay += 250;

    Here are a few more pictures of the sensor.







    Looks a bit different here because this is my first build already in the case