Low Power WiFi Datalogger

Remote datalogging system based on Wemos D1 Mini


These plans for a Wemos D1 mini (ESP8266) based datalogging system are a few years old. Back then, the ESP32 was rather new and I went with the Wemos D1 mini instead which features 4MB of flash memory, 80MHz of system clock, around 50k of usable RAM and an on chip WiFi Transceiver. This might still be of advantage today as the ESP8266 has a lower power consumption than the ESP32. With WiFi on, the current consumption is around 40 mA. The system has to sleep most of the time to limit power consumption. This design uses the TPL5110 timer (Adafruit module) to switch the system power completely off. The deepsleep current is 20 µA. With three alkaline AA batteries (~2000 mAh) and 1-2 "wake-ups" per hour, the battery lifetime is about one year. (The Wemos board would otherwise use too much current for the power regulator, LED and USB-chip even with the ESP8266 in deep-sleep mode).

Compared to 433 MHz, a WiFi datalogger has the big advantage that the data can be logged directly to the cloud. Today, there are many cloud-based IoT platforms that let you create dashboards to visualise your data. I have used Ubidots for a few years. They let you use one logger for free and start charging from the second logger. They have an interesting feature: you can get alarms on email and sms if for example a temperature exceeds a set value. I used this feature to monitor my fridge when I was on vacation.

I built four dataloggers. The top-right datalogger with the white perfboard is the protoype. I then developed a custom (green) PCB for the circuit. The Wemos D1 Mini is an interesting platform as there exist a number of sensor shields (https://www.wemos.cc/en/latest/d1_mini_shield/index.html) that can be plugged on top of the microcontroller board. If you just want to measure temperature and humidity, you can go with the SHT30 Shield. It contains a Swiss Sensirion SHT30 sensor: typical accuracy ±3%RH and ±0.3°C (https://www.sensirion.com/fileadmin/user_upload/customers/sensirion/Dokumente/2_Humidity_Sensors/Sensirion_Humidity_Sensors_SHT3x_Datasheet_digital.pdf)

In addition, the green PCB allows to plug in three I2C sensors. The top-left datalogger shows an example with a TSL2591 Lux sensor. Further, there is a connector for waterproof 1-wire DS18B20 compatible digital temperature sensors.

One additional feature is the measurement of the battery voltage with A0 to know when the battery voltage is low. The Wemos D1 Mini has a built-in voltage divider R1/R2 (220k/100k) for pin A0. That's why you can connect 3.3V to pin A0 even though the datasheet for the ESP8266 says that the max voltage for A0 is 1V. However, in order to read 5 Volt, we need to add a further resitor in series with R1 to increase the max voltage range.

Adafruit TPL5110 Low Power Timer board

https://www.adafruit.com/product/3435

Digikey part number 1528-1917-ND

Measure resistance between pins DELAY and GND. Adjust trim potentiometer to change delay time:

5 min 42.9 Ohm

0.5 hr 92.4 kOhm

1 hr 124.9 kOhm

1.5 hr 149.4 kOhm

Example program for logging to Ubidots

You have to open an account at Ubidots and get a Ubidots Authentications Token which is a unique key that authorizes your device to ingest data inside your Ubidots account.

It is possible to use the MQTT protocol to transfer sensor data but in the example below I built the required HTTP requests (https://ubidots.com/docs/hw/#http) to communicate with the Ubidots REST API from scratch. This helped me understanding what is going on in detail.

The Wemos D1 mini V2.2.0 was used. This version was ported from an earlier design with an Arduino Uno with WiFi shield (obsolete today).

For this program to work, a SHT30 shield is needed. (https://wiki.wemos.cc/products:d1_mini_shields:sht30_shield)

The logged sensor values are:

/*

Ubidots client - data logging of sensor signals to ubidots

Ported from version with Arduino with Wifi shield.


The measured data is posted to the ubidots website

Data includes room temperature, humidity, dew point and battery voltage

In addition if a Maxim sensor is included: fridge temperature


Circuit:

* Wemos D1 mini http://wemos.cc

* Wemos D1 SHT30 shield relative humidity(%RH) and temperature(°C) uses digital input pins D1 D2 I2C(0x45)

* Swiss Sensirion SHT30 sensor: typical accuracy ±3%RH and ±0.3°C

* Datasheet: https://www.sensirion.com/fileadmin/user_upload/customers/sensirion/Dokumente/2_Humidity_Sensors/Sensirion_Humidity_Sensors_SHT3x_Datasheet_digital.pdf

* https://wiki.wemos.cc/products:d1_mini_shields:sht30_shield

* Wemos example programs: https://github.com/wemos/D1_mini_Examples/tree/master/examples/04.Shields/DHT_Shield

*

* Fridge temperature:

* Maxim (earlier called Dallas Semic.) DS18B20 digital temperature sensor https://datasheets.maximintegrated.com/en/ds/DS18B20.pdf

* Normal (external supply - 3 wire) mode for temperature sensor:

* DATA (green) is attached to Wemos digital input pin D3 - YELLOW PLUG - this is the bus wire

* VCC (red) is attached to Wemos 3.3V pin - RED PLUG

* GND (yellow) is attached to Wemos GND - BLACK PLUG

* 4.7 kOhm pull-up resistor between DATA and VCC is required !!


Commented out below: alternative code for a DHT22 temp humidity sensor

*/


// Used libraries:

#include <Math.h>

#include <ESP8266WiFi.h>

//Code for WifiManager is commented out - didn't work properly

//#include <DNSServer.h>

//#include <ESP8266WebServer.h>

//#include <WiFiManager.h> //https://github.com/tzapu/WiFiManager

//WiFiManager didn't remember credentials after power loss

//#include <SPI.h> // Serial Peripheral Interface Library

#include <Wire.h> // 2-wire (I2C) protocoll


//if Maxim sensor for fridge temp is included:

#include <OneWire.h> // 1-wire protocoll for serial communication with thermometer

#include <DallasTemperature.h> // Communication with DS18B20 digital thermometer https://milesburton.com/Dallas_Temperature_Control_Library

//Wemos SHT30 sensor:

#include <WEMOS_SHT3X.h> // 2-wire (I2C) communication with SHT30 humidity temp sensor


//uncomment if DHT22 sensor:

//#include "DHT.h"

//#define DHTPIN D4

//#define DHTTYPE DHT22

//DHT dht(DHTPIN, DHTTYPE);


//Wifi credentials

const char* ssid = "your wifi id";

const char* password = "your password";


//Ubidots device name

const char* device = "arduino-kitchen";

//Ubidots Authentications Default Token (Account information - API credentials)

const char* token = "your unique token";



float humidity, temperature, dewpoint, fridgetemp, voltage, condensertemp;


#define ONE_WIRE_BUS 0 // Maxim data wire is plugged into pin D3 which is GPIO0 of ESP8266

#define DONEPIN D5 // D5 is GPIO14 which is connected to TPL5110 DONE pin

// D5 works as DonePin in combination with a 10k pulldown resistor


#define TIMEOUT 20000 // 20 seconds timeout on ubidots server


OneWire oneWire(ONE_WIRE_BUS); // Maxim: setup a oneWire instance to communicate with any OneWire devices

DallasTemperature sensors(&oneWire); // Maxim: Pass oneWire reference to Dallas Temperature

SHT3X sht30(0x45); // Setup a SHT30 object on address 0x45 2-wire (I2C)


String TempString ="0.0"; // Global strings that contains the values with one decimal place

String HumidString ="0.0";

String VoltString ="0.0";

String DewPointString ="0.0";

String FridgeTempString ="0.0";

String CondenserTempString ="0.0";


unsigned long timer2 = 0; // Global timer: time (in ms) for timeout of ubidots server

unsigned long timer = 0; // Global timer: time (in ms) for timeout wifi


WiFiClient client; // create a client that can connect to ubidots



void postdatatoubidots() // ICACHE_FLASH_ATTR

{

//build JSON

int num=0;

String json = "{\"temperature\":";

json += TempString;

json += ", \"humidity\":";

json += HumidString;

json += ", \"dewpoint\":";

json += DewPointString;

json += ", \"fridge-temperature\":";

json += FridgeTempString;

json += ", \"voltage\":";

json += VoltString;

json += ", \"condenser-temperature\":";

json += CondenserTempString;

json += "}";

num = json.length();

Serial.println(json);


//build HTTP request line

String httpRequest = "POST /api/v1.6/devices/";

httpRequest += device;

httpRequest += "/?token=";

httpRequest += token;

httpRequest += " HTTP/1.1";


Serial.println("\nConnecting to ubidots server...");

if (client.connect("http://things.ubidots.com", 80))

{

// if you get a connection, report back via serial:

Serial.println("Connected to ubidots server");

// Make a HTTP request -- ends with HTTP/1.1 CR LF: \r\n or use println

client.println(httpRequest);

// Make HTTP header fields -- end with CR LF: \r\n or use println

client.println("Connection: close");

client.println("Content-Type: application/json");

client.println("Content-Length: "+String(num));

// After last header double CR LF CR LF - empty line before HTTP body

client.println("Host: things.ubidots.com\r\n");

// HTTP message body -- no CR LF at end

client.print(json);


// Report back temp over serial:

Serial.print("Posted temp data: ");

Serial.println(TempString);

// Wait until server responds or timeout:

timer2 = millis() + TIMEOUT;

while( (client.available() == 0) && (millis() < timer2) )

{

; // wait here until server responds or timeout

}

// if there are incoming bytes available,

// read them and print them:

while (client.available() > 0)

{

char c = client.read();

Serial.write(c);

}

Serial.println();

Serial.println("disconnecting from ubidots server");

client.flush();

client.stop();

}

}



void setup()

{

// Initialise DONEPIN

pinMode(DONEPIN, OUTPUT);

digitalWrite(DONEPIN, LOW);


// Start up the library for the Maxim sensor:

sensors.begin();


// initialize serial and wait for port to open:

Serial.begin(115200);

// Serial.println("Starting WiFiManager");

// connect to the local wifi network:

// WiFiManager wifiManager;

// wifiManager.autoConnect("AutoConnectAP");

timer = millis() + TIMEOUT;

WiFi.begin(ssid,password);

while((WiFi.status()!=WL_CONNECTED) && (millis() < timer))

{

Serial.print(".");

delay(500);

}

Serial.println("Connected. Local IP address:");

Serial.println(WiFi.localIP());


Serial.println();


Serial.println("Read sensors and voltage");

sht30.get();

humidity = sht30.humidity;

temperature = sht30.cTemp;


//Maxim fridgetemp sensor:

sensors.requestTemperatures();

fridgetemp = sensors.getTempCByIndex(1);

condensertemp = sensors.getTempCByIndex(0);


//Alternative code to SHT30 if DHT22 sensor used:

//humidity = dht.readHumidity();

//temperature = dht.readTemperature();

//if (isnan(humidity) || isnan(temperature)) {

// Serial.println("Failed to read from DHT sensor!");

// }


//The August-Roche-Magnus equation, as described in Alduchov and Eskridge (1996)

// https://en.wikipedia.org/wiki/Vapour_pressure_of_water#Accuracy_of_different_formulations

// http://andrew.rsmas.miami.edu/bmcnoldy/Humidity.html

//Alternative formulas: http://www.decatur.de/javascript/dew/index.html

dewpoint = 243.04*(log(humidity/100)+((17.625*temperature)/(243.04+temperature)))/(17.625-log(humidity/100)-((17.625*temperature)/(243.04+temperature)));


voltage = (analogRead(A0)/1023.0)*5.33;


Serial.print("Humidity: ");

Serial.print(humidity);

Serial.println(" %");

Serial.print("Temp: ");

Serial.print(temperature);

Serial.println(" *C");

Serial.print("Dew point: ");

Serial.print(dewpoint);

Serial.println(" *C");

Serial.print("Fridge temp: ");

Serial.print(fridgetemp);

Serial.println(" *C");

// Serial.print("Condenser temp: ");

// Serial.print(condensertemp);

// Serial.println(" *C");

Serial.println("Voltage: ");

Serial.print(voltage);

Serial.println(" V");


TempString = String(temperature, 1); // string of temperature with one decimal place

HumidString = String(humidity,1);

DewPointString = String(dewpoint,1);

FridgeTempString = String(fridgetemp,1);

CondenserTempString = String(condensertemp,1);

VoltString = String(voltage,2);

postdatatoubidots(); // upload temperature string to ubidots server

WiFi.disconnect();

delay(1000);

}




void ICACHE_FLASH_ATTR loop()

{

// Toggle DONEPIN so TPL5110 cuts power

digitalWrite(DONEPIN, HIGH);

delay(100);

digitalWrite(DONEPIN, LOW);

delay(100);

}

© 2021 notthemarsian