Reduce on time to extend battery life

Hi All
Im revisiting a project I had a while ago and updating it
Im new to coding so not very good, ive managed to get a working project by cobbling bits of code together found in various places written by much clever people.(its not pretty Please be gentle :grimacing:)

project:
Im using a esp32 firebeetle to read some sensors dht11, ds18b20, hx711,battery voltage.
The esp32 connects to local wifi then to blynk io and thingpeak uploads latest sensor readings and battery state then enters deepsleep for a set time.

Im trying to get the battery to last as long as possible, I know i can deepsleep for longer and take less readings, but i wanted some help with reducing the time the esp32 is awake getting the reading. uploading them currently around 9 seconds, and possibly turn off the sensor pins when in deep sleep to further save battery(or does the deepsleep do this already)?

Any help or pointers would be really appreciated
Ive attached the code (I hope ive done this correctly) and a screen shot of the serial monitor output


#include <WiFi.h>
#include <WiFiClient.h>
#include <BlynkSimpleEsp32.h>
#include <OneWire.h>
#include <DallasTemperature.h>
#include <Wire.h>  // Only needed for Arduino 1.6.5 and earlier
#include "HX711.h"
#include "DHT.h"

// ThingSpeak Settings
char thingSpeakAddress[] = "api.thingspeak.com";
String    writeAPIKey = "xxxxxxxxxxxxxxx";   // Get the key for your channel to approve writing
int timer;

#define uS_TO_S_FACTOR 1000000  /* Conversion factor for micro seconds to seconds */
#define TIME_TO_SLEEP 30      /* Time ESP32 will go to sleep (in seconds) */
#define BLYNK_PRINT Serial
#define DHTPIN 5         // What digital pin we're connected to select yours accordingly

//Scale settings
#define calibration_factor 104007 //This value is obtained using the SparkFun_HX711_Calibration sketch
#define zero_factor 115356 //This large value is obtained using the SparkFun_HX711_Calibration sketch
#define LOADCELL_DOUT_PIN  26
#define LOADCELL_SCK_PIN  25

//BLynk settings
//#define BLYNK_TEMPLATE_ID "xxxxxxxxxxxxxxxxxxxx"
//#define BLYNK_TEMPLATE_NAME "temp and humidity"
//#define BLYNK_AUTH_TOKEN "xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx"

// DHT temp Sensor Uncomment whatever type you're using!
#define DHTTYPE DHT11     // DHT 11

HX711 scale;
//float weight =0;
//float calibration_factor = - 23400;  //You must change this factor depends on your scale,sensors and etc.


// Data wire is plugged into port 4 on the Arduino or ESP32
#define ONE_WIRE_BUS 2
#define TEMPERATURE_PRECISION 100

// Setup a oneWire instance to communicate with any OneWire devices (not just Maxim/Dallas temperature ICs)
OneWire oneWire(ONE_WIRE_BUS);

// Pass our oneWire reference to Dallas Temperature.
DallasTemperature sensors(&oneWire);

DHT dht(DHTPIN, DHTTYPE);

RTC_DATA_ATTR int bootCount = 0;

// You should get Auth Token in the Blynk App.
// Go to the Project Settings (nut icon).
const char auth[] =            "xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx";
const char blynk_server [] =   "blynk.cloud"; // new variable to hold the name of the Blynk server
const int blynk_port =         8080;              // new variable to hold the port used by the Blynk server

// Your WiFi credentials.
// Set password to "" for open networks.
char ssid[] = "xxxxxxxxxxxx";
char pass[] = "xxxxxxxxxxxx";

int wifi_connect_count = 0;          // New variable to keep track of how manty times we've tried to connect to the Wi-Fi
int wifi_connect_max_retries = 50;   // New variable to specify how many attempts we will have at connecting to the Wi-Fi

float sleep_time_minutes =     1;   // New variable - how long (in minutes) we sleep for. As this is a float variable then it can be 0.5 for a 30 second test

// Voltage batterie
#define ANALOG_PIN_0 36
int analog_value = 0;
int bat_percentage;
float volt=0.00;
float volt1=0.00;
float calibration = 0.33;

void getBatterie()
{
   analog_value = analogRead(ANALOG_PIN_0);
   //Serial.println(analog_value);
   volt = analog_value;
   //volt1= volt / 4096 * 5 * (811.333/680.000);  // voltage divider using R1 470k and R2 680k resistor
   //volt1= volt / 4096 * 5 * (212.118/220.000); // voltage divider using 100k and 220k resistor
   volt1= (((volt * 3.3) / 4096) * 2 + calibration); // voltage divider using 100k and 100k resistor
   Serial.print("Voltage = ");  
   Serial.println(volt1);

     bat_percentage = mapfloat(volt1, 2.8, 4.2, 0, 100); //2.8V as Battery Cut off Voltage & 4.2V as Maximum Voltage
 
  if (bat_percentage >= 100)
  {
    bat_percentage = 100;
  }
  if (bat_percentage <= 0)
  {
    bat_percentage = 1;
  }
 
  Serial.print("Analog Value = ");
  Serial.print(analog_value);
  Serial.print("\t Output Voltage = ");
  Serial.print(volt1);
  Serial.print("\t Battery Percentage = ");
  Serial.println(bat_percentage);
  delay(1000);
  
}
float mapfloat(float x, float in_min, float in_max, float out_min, float out_max)
{
  return (x - in_min) * (out_max - out_min) / (in_max - in_min) + out_min;
}

void getdht()
{
  float h = dht.readHumidity();
  float t = dht.readTemperature(); // or dht.readTemperature(true) for Fahrenheit
  
  if (isnan(h) || isnan(t)) {
    Serial.println("Failed to read from DHT sensor!");
    return;
  }
  Serial.println(" DHT Humidity: " + String(h)+ "%");
  //Serial.print(h);
  Serial.println(" DHT Temperature: " + String(t));
  //Serial.print(t);
}
void Deep_Sleep_Now() // New function - moded code out of void loop so that the sleep function can be called if we fail to connect to Wi-Fi or Blynk
{
  esp_sleep_enable_timer_wakeup((uint64_t)(TIME_TO_SLEEP) * uS_TO_S_FACTOR);
  Serial.println("Setup ESP32 to sleep for every " + String(TIME_TO_SLEEP) +
  " Seconds");
  Serial.println("Going to sleep now");
  Serial.flush();
  esp_deep_sleep_start();
 
  delay(200);
}

void sendSensor()
{
 // Request temperature to all devices on the data line
  sensors.requestTemperatures(); 
  
  Serial.println("Celsius temperature: " + String(sensors.getTempCByIndex (0))); 
  //We can connect more than one IC on the same data wire. 0 refers to the first IC on the wire
  //Serial.print(sensors.getTempCByIndex(0)); 
  int tempC=sensors.getTempCByIndex(0);
  
  delay(200);
}

void getWeight()
{
 scale.begin(LOADCELL_DOUT_PIN, LOADCELL_SCK_PIN);
 scale.set_scale(calibration_factor); //This value is obtained by using the SparkFun_HX711_Calibration sketch
 scale.set_offset(zero_factor); //Zero out the scale using a previously known zero_factor
  //Serial.println("Readings:");
Serial.print("Weight: ");
  Serial.print(scale.get_units(10)); //scale.get_units() returns a float
  Serial.print(" Kilos"); //You can change to kg but you'll need to change the calibration_factor
  Serial.println();
  
}
void WiFi_Connect() // New functon to handle the connectuon to the Wi-Fi network
{
  Serial.println(F("Connecting to Wi-Fi"));
  //WiFi.config(device_ip, dns, gateway, subnet); // Not needed if you just want to have a DHCP assigned IP address. If you diont use this then delete the device_ip, dns, gateway & subnet declarations
   
  if (WiFi.status() != WL_CONNECTED)
  {
      WiFi.begin(ssid, pass); // connect to the network
  }
  while (WiFi.status() != WL_CONNECTED  && wifi_connect_count < wifi_connect_max_retries) // Loop until we've connected, or reached the maximum number of attemps allowed
  {
    delay(500);
    wifi_connect_count++;  
    Serial.print(F("Wi-Fi connection - attempt number "));
    Serial.println(wifi_connect_count);
  }
 
  if (WiFi.status() == WL_CONNECTED)
  {
    WiFi.mode(WIFI_STA);
    Serial.println(F("Wi-Fi CONNECTED"));
    Serial.println();
  }
} // End of void WiFi_Connect

void setup()
{
  Serial.begin(115200);
  Serial.println(__FILE__);
  
  // New section of code - stop using Blynk.begin, which is a blocking function, and instead do the following:
  //
  // 1) Attempt to connect to Wi-Fi a few times (how many times we try is specified by the 'wifi_connect_max_retries' variable)
  // 2) If we successfully connected to Wi-Fi then attempt to connect to Blynk in a non-blocking way. If we aren't connected to Wi-Fi then go to sleep
  // 3) If we connected to Blynk then run the rest of the code as normal. If we aren't connected to Blynk then go to sleep
 
  WiFi_Connect(); // Attempt to connect to Wi-Fi

  if (WiFi.status() == WL_CONNECTED)               // If we managed to connect to Wi-Fi then try to connect to Blynk, else go to sleep
  {
    Blynk.config(auth, "blynk.cloud", 80);  // Initialise the Blynk connection settings
    Blynk.connect();                               // Attempt to connect to Blynk
  }
  else
  {
    Serial.println ("Wi-Fi connection failed - going to sleep");
    //sleep_time_minutes = sleep_time_minutes * 2; // If you enable this line of code the it will make the device go to sleep for twice as long before trying again. Changing to 0.5 would make it try again sooner than normal
    Deep_Sleep_Now();
  }
 
  if (Blynk.connected())                          // If we manages to connect to Blynk then carry-on as normal, else go to sleep
  {  
    Serial.println ("Connected to Blynk");
  }
  else
  {  
    //sleep_time_minutes = sleep_time_minutes * 2; // If you enable this line of code the it will make the device go to sleep for twice as long before trying again. Changing to 0.5 would make it try again sooner than normal
    Serial.println("Blynk connection failed - going to sleep");
    Deep_Sleep_Now();
  }
  
  ++bootCount;
  Serial.println("Boot number: " + String(bootCount));
  delay(500);

 sensors.begin();
  dht.begin();
  getdht();
  getWeight();
  sendSensor();
  getBatterie();
}

void loop()
{
  float Weight = (scale.get_units(10));
  float h = dht.readHumidity();
  float t = dht.readTemperature();
  float tempC = (sensors.getTempCByIndex (0));
  float Battperc = (bat_percentage);
  
  Blynk.virtualWrite(V3, bootCount);
  Blynk.virtualWrite(V7, volt1);
  Blynk.virtualWrite(V1,h);
  Blynk.virtualWrite(V0,t);
  //Blynk.virtualWrite(V6, p);
  Blynk.virtualWrite(V2, tempC);
  Blynk.virtualWrite(V8, Battperc);
  Blynk.virtualWrite(V4, Weight);
  Blynk.virtualWrite(V4, (scale.get_units(10)));
  //Blynk.virtualWrite(V10, h2);
  Blynk.virtualWrite(V6, TIME_TO_SLEEP);
  float wake_time = (float)millis()/float(1000); // Find out how long since the ESP rebooted
  Blynk.virtualWrite(V5, wake_time);  // Wake time
  Serial.print("Wake Time = ");
  Serial.print(wake_time);
  Serial.println(" seconds");
  Blynk.run(); // Needed to ensure that the Wake Time value is always uploaded to Blynk before going to sleep
  delay(500);
  

  float current_temperature = dht.readTemperature(); //DHT.readTemperature();
  float current_humidity    = dht.readHumidity(); //DHT.readHumidity();
  float current_ds18_temperature    = (sensors.getTempCByIndex (0));// Read DS18b20 sensor
  float current_Weight    = (scale.get_units(10));// read scale average of 10 readings
  float current_Battery    = (volt1);// battery voltage
  float current_bootCount   = (bootCount);// number of times device has rebooted after deep sleep
  float current_Battery_perc    = (bat_percentage);// battery percentage
  /*
  Serial.println(String(current_temperature,1)+"'c"); 
  Serial.println(String(current_humidity,0)+"%"); 
  Serial.println(String(current_ds18_temperature,1)+"'c"); 
  Serial.println(String(current_Weight,2) + " Kg");
  Serial.println(String(current_Battery,2)+"v");
  Serial.println(String(current_bootCount,1)+"");
  */
  UpdateThingSpeak(current_temperature, current_humidity, current_ds18_temperature, current_Weight, current_Battery, current_bootCount, current_Battery_perc);
  //Serial.println("Finished:" + String(millis() - timer));

}

void UpdateThingSpeak(float current_temperature, float current_humidity, float current_ds18_temperature, float current_Weight, float current_Battery, float current_bootCount, float current_Battery_perc) {
  WiFiClient client;
  //GET http://api.thingspeak.com/update?api_key=32CCT6D9GBIDV0NW&field1=22&field2=23&field3=1028
  String url = "GET /update?api_key=" + writeAPIKey + "&field1=" + String(current_temperature,1) +
                                                      "&field2=" + String(current_humidity,1)    +
                                                      "&field3=" + String(current_ds18_temperature,1)    +
                                                      "&field4=" + String(current_Weight,1)    +
                                                      "&field5=" + String(current_Battery,2)    +
                                                      "&field6=" + String(current_bootCount,1)    +
                                                      "&field7=" + String(current_Battery_perc,1)    +
                                                      " HTTP/1.1";
  if (client.connect(thingSpeakAddress, 80))
  {
    client.println(url);
    client.println("Host: api.thingspeak.com");
    client.println("Connection: close\n");
    Serial.println("Upload of data complete");
    if (client.connected()) Serial.println("Connecting to ThingSpeak...");
    else                    Serial.println("Connection to ThingSpeak failed");
  }
  else
  {
    Serial.println("Connection to ThingSpeak Failed");
  }
  delay(500);    // Essential to enable upload to complete
  client.stop();  // close the connection

  Deep_Sleep_Now();
}

Okay, so this is basically the code that @christophebl and I put together for his Beehive Connected project.

TBH, you’re not going to get things to work that much quicker. You’ll find that specifying a static IP address may help speed-up your WiFi connection time, and tweaking the delay between WiFi connection attempts (sometimes slightly longer is better) may help.
Routers often cache the device connection for a while, then purge this table of connections after a while (30 seconds maybe). This means that longer sleep times without a static IP can result in longer WiFi connection times because of the way that the DHCP renegotiation process works once the connection table has been purged.

I have seen some circuits where a transistor is used to cut the parasitic power of the sensors in deep sleep, but it depends on the wake-up and stabilisation time of your sensors. TBH the DHT range of sensors are total rubbish and I wouldn’t touch them with a bargepole.

Ultimately though, your temperature and humidity aren’t going to change much in 30 seconds, and a 2:1 sleep/wake ratio isn’t going to give you decent battery life, so you really need to extend your sleep time.

One possible way of speeding-up the process is to use the Blynk HTTP REST API rather than establishing a connection via Blynk.begin, but if your coding skills aren’t great then that might be too much work.

Pete.

Hi Pete,
yes that’s right, I’ve butchered it somewhat from the original code. Ill try and add a static IP see if it makes a difference, i used a transistor on the last one to cut the power to the sensors i was wondering if it could be done with the gpio pins setting them to low before deep sleep. Im struggling to get the onboard led to go off in sleep and come back on when it wakes at the moment so that may be above me. :thinking:

The DHT sensors are just what i have at the moment, the last one i used a bme280. what sensors would you recommend?

The onboard LED is active LOW, so that won’t work.

I quite like the SHT range of sensors.

Pete.

1 Like

Check this out

Adafruit have an excellent tutorial on YouTube how to setup and use this.

billd

1 Like
1 Like

Thanks Bill ill have a look at that,

I changed it to a static ip address as you suggested Pete and reduced some of the delays in the code, it did reduce the time down to around 6.5 seconds.
I noticed on the serial monitor theres about 3 seconds between the weight and the wake time,this seems a long time, is this just the time it takes the sensor to read or could this be reduced in the code?

thanks for the help

I’m not sure. I’ve never actually used this code with any hardware attached

Ok thanks