A while ago I researched the battery-powered options for ESP8266. Found some interesting articles and managed to program an ESP8266 with a temp sensor that updates every 5 mins to Thingspeak. It runs on a 3.7V Li-ion 200mAh for ca 20 days.
I will not go into detail, but one of the 'tricks' involved is putting the deepsleep in the RF disabled mode, so that when it returns from deepsleep the RF is initially not enabled.
ESP.deepSleep( SLEEPTIME, WAKE_RF_DISABLED );
Further I use static IP and the rtcMemory to store the MAC address and WIFI channel as to invoke a quick WIFI connection. (And this is a huge time saver!)
WiFi.config( ip,dns, gateway, subnet );
WiFi.begin( WLAN_SSID, WLAN_PASSWD, rtcData.channel, rtcData.ap_mac, true );
Here's a sample code I used and adapted for my needs:
https://gitlab.com/diy_bloke/verydeepsl ... pSleep.ino
Sofar so good. My setup reads a temp-sensor every 5 minutes (along with battery Voltage and the time the ESP is awake) and sends it to Thingspeak. It is only 'on' for some 1.3 secs every measurement.
However, there is more to gain. What if I store -say- 12 measurements (conveniently 1 hour of data) in the rtcMemory and upload it only once an hour? The 'on' time per measurement would drastically go down (I measured ca 250msec) and the powerhungry RF radio would be on for only 1.3 secs once an hour.
So I stayed up one night and programmed a new setup. Using a NodeMCU for convenience. And it seems to work.
However, and here is the issue, -sorry for the long introduction- the quick connection 'trick' is not working anymore. It needs to get the ,already known, info again and that takes about 10 secs to complete.
I tried several things, put in delays after some RF commands, tried WIFI_off and other goto sleep commands but nothing worked sofar.
And the strange thing is that when I switch on the WIFI every measurement it will quick connect. Once I cycle throught the code without switching on the WIFI it won't quick connect anymore.
So I went back to a bare-bone setup. Again this 'bug' appears! So when coming from deepsleep and start the WIFI every time, a quick connection is made. But when I come from deepsleep and cycle one or more times without switching on the WIFI it looses the ability to quick connect.
Maybe someone can shed a light on this issue....
(Code may have some redundant lines, I copied them from my main program)
Where I put the arrow <----------------------in the code try putting 0 and then e.g 2. The nr of times it will cycle through deepsleep before turning on WIFI.
//What happens if radio is switched on every xx times?
// No reading of sensors, only radio on/off
long SLEEPTIME=30e6; // 30secs
#include <ESP8266WiFi.h>
#include "secrets.h"
float tempSensor1, V_adjust=0.97, VBat;
unsigned long myChannelNumber = SECRET_CH_ID;
const char * myWriteAPIKey = SECRET_WRITE_APIKEY;
char* WLAN_SSID = SECRET_SSID; // your network SSID (name)
char* WLAN_PASSWD = SECRET_PASS; // your network password
int httpCode=0;
unsigned long previousTime = millis();
const unsigned long interval = 1000;
int OTA_Timeout = 60;
WiFiClient clientWiFi;
// Temperature wire is plugged into port D5 on the ESP8266 (GPIO 14)
// We make a structure to store connection information
// The ESP8266 RTC memory is arranged into blocks of 4 bytes. The access methods read and write 4 bytes at a time,
// so the RTC data structure should be padded to a 4-byte multiple.
struct {
uint32_t crc32; // 4 bytes
uint8_t channel; // 1 byte, 5 in total
uint8_t ap_mac[6];// 6 bytes, 11 in total
uint8_t index_count; // 1 byte, 12 in total
} rtcData;
//We will use static ip
IPAddress ip( 192, 168, 1, 12 );// pick your own suitable static IP address
IPAddress gateway( 192, 168, 1, 254 ); // may be different for your network
IPAddress subnet( 255, 255, 255, 0 ); // may be different for your network (but this one is pretty standard)
IPAddress dns(192,168,1,254);
void setup() {
pinMode(LED_BUILTIN, OUTPUT);
digitalWrite(LED_BUILTIN, HIGH); //That means LED off..
Serial.begin(115200);
// we disable WiFi, coming from DeepSleep, as we do not need it right away
WiFi.mode( WIFI_OFF ); //required? we start with rf disabled ???
WiFi.forceSleepBegin();
delay( 1 );
// Try to read WiFi settings from RTC memory
bool rtcValid = false;
if( ESP.rtcUserMemoryRead( 0, (uint32_t*)&rtcData, sizeof( rtcData ) ) ) {
// Calculate the CRC of what we just read from RTC memory, but skip the first 4 bytes as that's the checksum itself.
uint32_t crc = calculateCRC32( ((uint8_t*)&rtcData) + 4, sizeof( rtcData ) - 4 );
if( crc == rtcData.crc32 ) {
rtcValid = true;
}
else {
rtcData.index_count = 0;
}
}
//-----------------
// Now is the time to do stuff like reading sensors while the radio is still off
// Start the sensors but to give it time the actual reading is done later
//-----------------
Serial.println();
Serial.println();
Serial.printf("millis: %i, msecs\n\r", millis());
//Read the voltage
int vdd = analogRead(A0);
Serial.printf("Vdd = %d -> %.2fV\n\r",vdd, vdd*5.02/1024*V_adjust);
//Switch Radio back On
Serial.printf("millis: %i, msecs\n\r", millis());
Serial.printf("index count: %i\n\r", rtcData.index_count);
if (rtcData.index_count >= 2) { // set to 0 for every cycle, set to eg 4 for every 4 cycles. <----------------------
Serial.println(" Starting Radio");
WiFi.forceSleepWake();
delay(1);
// Disable the WiFi persistence. The ESP8266 will not load and save WiFi settings unnecessarily in the flash memory.
WiFi.persistent( false );
// Bring up the WiFi connection
WiFi.mode( WIFI_STA );
WiFi.config( ip,dns, gateway, subnet );
//-----------Now we replace the normally used "WiFi.begin();" with a procedure using connection data stored by us
if( rtcValid ) {
// The RTC data was good, make a quick connection
Serial.println("RTC OK, Quick connection!");
WiFi.begin( WLAN_SSID, WLAN_PASSWD, rtcData.channel, rtcData.ap_mac, true );
}
else {
// The RTC data was not valid, so make a regular connection
Serial.println("RTC BAD, Regular connection!");
WiFi.begin( WLAN_SSID, WLAN_PASSWD );
}
//------now wait for connection
int retries = 0;
int wifiStatus = WiFi.status();
while( wifiStatus != WL_CONNECTED ) {
retries++;
if( retries == 100 ) {
Serial.println("Retries WIFI = 100");
// Quick connect is not working, reset WiFi and try regular connection
WiFi.disconnect();
delay(10);
WiFi.forceSleepBegin();
delay(10);
WiFi.forceSleepWake();
delay(10);
WiFi.begin( WLAN_SSID, WLAN_PASSWD );
}
if( retries == 600 ) {
Serial.println("Retries WIFI = 600");
// Giving up after 30 seconds and going back to sleep
WiFi.disconnect( true );
delay(1);
WiFi.mode( WIFI_OFF );
Serial.printf("millis: %i, msecs\n\r", millis());
ESP.deepSleep( SLEEPTIME, WAKE_RF_DISABLED );
}
delay(50);
wifiStatus = WiFi.status();
}
//---------
Serial.println(" WiFi connected");
Serial.print("IP address: ");
Serial.println(WiFi.localIP());
// Write current connection info back to RTC
rtcData.channel = WiFi.channel();
memcpy( rtcData.ap_mac, WiFi.BSSID(), 6 ); // Copy 6 bytes of BSSID (AP's MAC address)
rtcData.index_count = 0; // reset count
rtcData.crc32 = calculateCRC32( ((uint8_t*)&rtcData) + 4, sizeof( rtcData ) - 4 );
ESP.rtcUserMemoryWrite( 0, (uint32_t*)&rtcData, sizeof( rtcData ) );
//-------Now it's time to use your connection, e.g. by sending data
// Do nothing just test deepsleep cycles....
WiFi.disconnect( true );
delay( 1 );
}
rtcData.index_count++;
rtcData.crc32 = calculateCRC32( ((uint8_t*)&rtcData) + 4, sizeof( rtcData ) - 4 );
ESP.rtcUserMemoryWrite( 0, (uint32_t*)&rtcData, sizeof( rtcData ) );
// WAKE_RF_DISABLED to keep the WiFi radio disabled when we wake up
Serial.printf("millis: %i, msecs\n\r", millis());
Serial.println(" Going to Deepsleep zzzzz");
ESP.deepSleep( SLEEPTIME, WAKE_RF_DISABLED );
}
void loop() {
}
// the CRC routine
uint32_t calculateCRC32( const uint8_t *data, size_t length ) {
uint32_t crc = 0xffffffff;
while( length-- ) {
uint8_t c = *data++;
for( uint32_t i = 0x80; i > 0; i >>= 1 ) {
bool bit = crc & 0x80000000;
if( c & i ) {
bit = !bit;
}
crc <<= 1;
if( bit ) {
crc ^= 0x04c11db7;
}
}
}
return crc;
}