My little project:
Temperature/humidity sensor with a sonoff si7021.
You can find the sonoff si7021 sensors quite cheap on aliexpress (about 4,5€/piece).
Pro's: has sensor and housing
Con's: needs some tinkering to use it in low power application.
The build:
Arduino mini pro 8mhz 3.3v
Sonoff si7021 sensor
Lipo 3.7v battery
nrf24l01+ radio
I modded the arduino nano clone for low low power.
First I tried with the one-wire protocol of the sonoff, but no luck in there.
Next I soldered sda/scl lines directy and the sensor worked, but sleeping current was 1ma and way out of specs for the si7021 + mini pro.
Next I modded the si7021
- I removed the transistor Q1
- I remove capacitor C4
- I cut all traces from the mcu
After this the sleeping current is about 15 uA.
The sketch sends temperature, humidity, batterylevel and batteryvoltage.
My code:
// Enable debug prints to serial monitor
//#define MY_DEBUG
// Enable and select radio type attached
#define MY_RADIO_NRF24
//#define MY_RADIO_RFM69
// Set LOW transmit power level as default, if you have an amplified NRF-module and
// power your radio separately with a good regulator you can turn up PA level.
// #define MY_RF24_PA_LEVEL RF24_PA_LOW
#define MY_RF24_PA_LEVEL RF24_PA_HIGH
//#define MY_DEBUG_VERBOSE_RF24
// RF channel for the sensor net, 0-127
#define RF24_CHANNEL 125
//PiHome Node ID
#define MY_NODE_ID 23
//RF24_250KBPS for 250kbs, RF24_1MBPS for 1Mbps, or RF24_2MBPS for 2Mbps
#define RF24_DATARATE RF24_250KBPS
#include <MySensors.h>
#include "Adafruit_Si7021.h"
Adafruit_Si7021 sensor = Adafruit_Si7021();
// Define sensor node childs
#define CHILD_ID_TEMP 0
#define CHILD_ID_HUM 1
#define CHILD_ID_BATT 2
#define CHILD_ID_BATT_VOLTAGE 3
#define COMPARE_TEMP 1 // Send temperature only if changed? 1 = Yes 0 = No
#define COMPARE_BVOLT 1 // Send battery voltage only if changed? 1 = Yes 0 = No
#define READ_SAMPLE_INTERVAL (10) //define how many samples you are going to take in normal operation
#define READ_SAMPLE_TIMES (5) //define the time interal(in milisecond) between each samples in
// Set this offset if the sensor has a permanent small offset to the real temperatures
#define SENSOR_TEMP_OFFSET 0
static const uint64_t UPDATE_INTERVAL = 10000;
unsigned long SLEEP_TIME = 56000; // Sleep time between reads (in milliseconds)
// Battery related init
int BATTERY_SENSE_PIN = A6; // select the input pin for the battery sense point
float oldBatteryV = 0;
#define SKETCH_NAME "Temp_Humid_Bat_Uterum" // Change to a fancy name you like
#define SKETCH_VERSION "2.1" // Your version
float lastTemp;
float lastHum;
uint8_t nNoUpdatesTemp;
uint8_t nNoUpdatesHum;
bool metric = true;
//Definition messages
MyMessage msgHum(CHILD_ID_HUM, V_HUM);
MyMessage msgTemp(CHILD_ID_TEMP, V_TEMP);
MyMessage msgBattVolt(CHILD_ID_BATT_VOLTAGE, V_VOLTAGE);
MyMessage msgBatt(CHILD_ID_BATT, V_VOLTAGE);
static const uint8_t FORCE_UPDATE_N_READS = 10;
//Variables
int chk;
float hum; //Stores humidity value
float temp; //Stores temperature value
void setup()
{
if (!sensor.begin()) {
Serial.println("Did not find Si7021 sensor!");
while (true);
}
// needed for battery soc
// use the 1.1 V internal reference
#if defined(__AVR_ATmega2560__)
analogReference(INTERNAL1V1);
#else
analogReference(INTERNAL);
#endif
delay(2000);
#ifdef MY_DEBUG
Serial.println("***Debug Activated***");
Serial.print("Sleep_Time: ");
Serial.print((SLEEP_TIME / 1000)/60);
Serial.println(" min");
#else
Serial.println("***Debug Deactivated***");
Serial.print("Sleep_Time: ");
Serial.print((SLEEP_TIME / 1000)/60);
Serial.println(" min");
#endif
}
void presentation() {
// Send the sketch version information to the gateway and Controller
sendSketchInfo("Temperature Sensor", "1.34");
// Register all sensors to gw (they will be created as child devices)
present(CHILD_ID_HUM, S_HUM);
present(CHILD_ID_TEMP, S_TEMP);
present(CHILD_ID_BATT, S_POWER);
present(CHILD_ID_BATT_VOLTAGE, S_MULTIMETER , "Battery ");
}
void loop()
{
// disable ADC
// get the battery Voltage
int battSensorValue = analogRead(BATTERY_SENSE_PIN);
float batteryV = battSensorValue * 0.011828;
// 1M, 100K divider across battery and using internal ADC ref of 1.1V
// Sense point is bypassed with 0.1 uF cap to reduce noise at that point
// ((1e6+100e3)/100e3)*1.1 = Vmax = 12.1 Volts
// 12.1/1023 = Volts per bit = 0.011828
int batteryPcnt = (batteryV / 4.2) * 100;
#ifdef MY_DEBUG
Serial.print("Pin Reading: ");
Serial.println(battSensorValue);
Serial.print("Battery Voltage: ");
Serial.print(batteryV);
Serial.println(" v");
//Print Battery Percentage
Serial.print("Battery percent: ");
Serial.print(batteryPcnt);
Serial.println(" %");
#endif
#if COMPARE_BVOLT == 1
send(msgBatt.set(batteryV, 2));
send(msgBattVolt.set(batteryV,2));
sendBatteryLevel(batteryPcnt);
#else
if (oldBatteryV != batteryV) {
send(msgBatt.set(batteryV, 2));
sendBatteryLevel(batteryPcnt);
send(msgBattVolt.set(batteryV,2));
oldBatteryV = batteryV;
}
#endif
delay(500);
//Read data and store it to variables hum and temp
hum = sensor.readHumidity();
temp= sensor.readTemperature();
#ifdef MY_DEBUG
//Print temp and humidity values to serial monitor
Serial.print("Humidity: ");
Serial.print(hum);
Serial.print(" %, Temp: ");
Serial.print(temp);
Serial.println(" Celsius");
#endif
if (isnan(temp)) {
Serial.println("Failed reading temperature from DHT!");
} else if (temp != lastTemp || nNoUpdatesTemp == FORCE_UPDATE_N_READS) {
// Only send temperature if it changed since the last measurement or if we didn't send an update for n times
lastTemp = temp;
// Reset no updates counter
nNoUpdatesTemp = 0;
temp += SENSOR_TEMP_OFFSET;
send(msgTemp.set(temp, 1));
#ifdef MY_DEBUG
Serial.print("T: ");
Serial.println(temp);
#endif
} else {
// Increase no update counter if the temperature stayed the same
nNoUpdatesTemp++;
}
// Get humidity from DHT library
if (isnan(hum)) {
Serial.println("Failed reading humidity from DHT");
} else if (hum != lastHum || nNoUpdatesHum == FORCE_UPDATE_N_READS) {
// Only send humidity if it changed since the last measurement or if we didn't send an update for n times
lastHum = hum;
// Reset no updates counter
nNoUpdatesHum = 0;
send(msgHum.set(hum, 1));
#ifdef MY_DEBUG
Serial.print("H: ");
Serial.println(hum);
#endif
} else {
// Increase no update counter if the humidity stayed the same
nNoUpdatesHum++;
}
sleep(SLEEP_TIME);
}
My inspirations:
- low power arduino
- pi home battery ds18b20 sensor
- many others