ESP8266 Sleeping Temperature Station

This is a project for a small temperature, humidity, and batter voltage monitor so I can track what the weather is doing outside using the Wemos D1 Mini Pro. It uses the esp8266 library to sleep for 10 min (just changed to 20 min) and then wake, take readings, transmit to cayenne, and then sleep again. I use the EEPROM to store the sleep value (if it sleeps or not) and it reads it when the chip resets. The thing about the ESP8266 in this instance is that rather than just waking up, it triggers a reset so thats why I had to use the EEPROM to store the value. It uses the SHT3x temp/hum sensor which is I2C. I also used a D1 Mini shield to do a voltage divider so I can monitor the battery voltage and a Charger Shield to charge the battery. To get the chip out of a sleep loop, one either has to wait till it comes online briefly and unselect the sleep button or you can put a jumper GRD → D7 to disable the sleep cycle. You also need a jumper from D0 (GPIO16 aka wake pin) —> RST to enable the chip to wake itself up. I also thought the ESP8266 only read between 0-1v on the analog pin but I tested it and it definitely reads all the way to 3.3v on this chip anyway. Weird

// #define CAYENNE_DEBUG Serial
// #define CAYENNE_PRINT Serial
#include <Wire.h>
#include <CayenneMQTTESP8266.h>
#include <ESP8266WiFi.h>
#include <EEPROM.h>


RF_MODE(RF_NO_CAL) // tells the ESP to just turn on radio, no calibration which extra takes power

char ssid[] = "IoT";
char wifiPassword[] = "";

char username[] = "";
char password[] = "";
char clientID[] = "";

#define Address         0x45 // wire address for the SHT3x
#define eepromAddress   0 // where sleep cycle status is stored
#define voltPin         A0
#define sleepDisablePin D7

// resistor values for volt divider
// R1 = 11910;
// R2 = 3260;
// voltFactor = R2 / (R1 + R2);

float voltFactor = 0.212;
float voltage;

bool online;

unsigned long onlineTime;
unsigned long prevTime;
unsigned long time1;

unsigned int data[6];
unsigned int disco = 0;

byte buttonEnabled = 0;
byte sleepDisabled = 1;
byte sleepNow = 0;
byte restartChip = 0;

float cTemp = 0.0;
float fTemp = 0.0;
float humidity = 0.0;




void setup()
{
	pinMode(BUILTIN_LED, OUTPUT);
	pinMode(sleepDisablePin, INPUT_PULLUP);  // jumper for sleep override

	for (int i = 0; i < 3; i++)              // LED blinks to show booting
	{
		digitalWrite(BUILTIN_LED, 0);
		delay(100);
		digitalWrite(BUILTIN_LED, 1);
		delay(100);
	}

	Wire.begin();
	EEPROM.begin(512);                            // to store sleep state
	// Serial.begin(9600);

	// voltFactor = R2 / (R1 + R2);
	voltFactor = 0.212;                           // for voltage divider

	buttonEnabled = EEPROM.read(eepromAddress);   // checks if it is in a sleep cycle
	sleepDisabled = digitalRead(sleepDisablePin); // checks for sleep cycle bypass

	Cayenne.begin(username, password, clientID, ssid, wifiPassword);

	if (sleepDisabled == 0)                       // stops sleep cycle if jumper LOW
	{
		sleepNow = 0;
		buttonEnabled = 0;
		Cayenne.virtualWrite(0, 0, "digital_sensor", "d");          // sends sleep cycle status to sleep button on dashboard
	}

	time1 = millis();

} // setup


void loop()
{
	Cayenne.loop();

	if (millis() - time1 > 20000)    // loop to get & send data every 20 seconds
	{
		getTemp();
		execute();
	}

	if (online == true)              // blinks LED if online about every 1 sec
	{
		digitalWrite(BUILTIN_LED, LOW);
		delay(10);
		digitalWrite(BUILTIN_LED, HIGH);
	}
	else
	{
		digitalWrite(BUILTIN_LED, HIGH);
	}

} // loop


void getTemp()  // pulls temp & humidity via i2c per datasheet, gets voltage
{
	Wire.beginTransmission(Address);

	Wire.write(0x2C);
	Wire.write(0x06);

	Wire.endTransmission();
	delay(500);

	Wire.requestFrom(Address, 6);              // get data

	if (Wire.available() == 6)
	{
		data[0] = Wire.read();
		data[1] = Wire.read();
		data[2] = Wire.read();
		data[3] = Wire.read();
		data[4] = Wire.read();
		data[5] = Wire.read();
	}


	cTemp = ((((data[0] * 256.0) + data[1]) * 175) / 65535.0) - 45;
	fTemp = (cTemp * 1.8) + 32;
	humidity = ((((data[3] * 256.0) + data[4]) * 100) / 65535.0);


	voltage = (analogRead(voltPin) / 1024) * 3.3;
	voltage = voltage / voltFactor;
} // getTemp




void execute()
{
	time1 = millis();              // record transmit time

// temp, humidity, and batt voltage
	Cayenne.virtualWrite(5, fTemp, "Fahrenheit", "f");
	Cayenne.virtualWrite(6, humidity, "Percent", "p");
	Cayenne.virtualWrite(8, fTemp, "analog_sensor", "null");
	Cayenne.virtualWrite(9, humidity, "analog_sensor", "null");

	Cayenne.virtualWrite(7, voltage, "analog_sensor", "null");
	Cayenne.virtualWrite(10, voltage, "analog_sensor", "null");

// system info
	Cayenne.virtualWrite(23, disco, "counter", "null");

	int time2 = (millis() / 1000) / 60;
	Cayenne.virtualWrite(24, time2, "counter", "null");

	onlineTime = ((millis() - prevTime) / 1000) / 60;
	Cayenne.virtualWrite(25, onlineTime, "counter", "null");


	if (sleepNow == 1)                 // if sleep is active, chip sleeps after data transmit
	{
		ESP.deepSleep(1200000 * 1000); // sleeps for 20 min
	}

} // execute


CAYENNE_CONNECTED()
{
	online = true;
	prevTime = millis();

	if (buttonEnabled == 1)      // checks if sleep cycle active
	{
		Cayenne.virtualWrite(0, 1, "digital_sensor", "d");          // sends value of sleep to dashboard
		sleepNow = 1;
	}
}

CAYENNE_DISCONNECTED()
{
	online = false;
	disco++;      // record disconnect
}




CAYENNE_IN(0)  // sleep button
{
	sleepNow = getValue.asInt();

	if (sleepNow == 1)     // save sleep cycle status to eeprom to read after reboot
	{
		EEPROM.write(eepromAddress, 1);
		EEPROM.commit();
	}
	else
	{
		EEPROM.write(eepromAddress, 0);
		EEPROM.commit();
	}

}

CAYENNE_IN(1) // trigger chip restart
{
	restartChip = getValue.asInt();
	delay(1500);

	if (restartChip == 1)
	{
		Cayenne.virtualWrite(1, 0, "digital_sensor", "d");         // writes reboot button back low before restart
		delay(1500);

		ESP.restart();
	}

}

1 Like

Hello,
Nice project! Can you give me the specification of the battery. I am also working on a similar project. I plan to add also a Solar Panel :wink:

The battery is a Lithium Ion 3.7v 2500mah that I got off amazon. It was sold by Adafruit but the battery brand is PKCELL. The link is below for more info. I get about a week of runtime between charges when it wakes every 10min. I just changed it to wake every 20min instead so I’ll see how much longer it goes.

1 Like