Running Arduino Pro Mini 3.3V and ESP8266-01 on Battery

  Arduino, ESP8266

Finish each day before you begin the next, and interpose a solid wall of sleep between the two

Contents

Power Management

Without power management, the battery would last only a few hours, but we want it to keep our circuit alive for months. In most applications of the Arduino Pro Mini, it would not be necessary to constantly make computations or acquire data from sensors. If you want to build a weather station, would it be crucial to measure the temperature every single second? Probably not. About every 10 minutes seems more reasonable. Letting the circuit run idle during this period would be a tremendous waste of energy. Nowadays, many MCUs like Arduino, ESP8266, and even the Pololu voltage regulator, come with built in power conservation features. Let’s begin with the Arduino Pro Mini. Make sure you make some sense of the following Arduino Pro Mini sketch:

Arduino Pro Mini deep sleep code example:
#include <avr/sleep.h>;
#include <avr/wdt.h>;

volatile int sleepcounter = 0;

void setup() {
  Serial.begin(9600);
  watchdogOn();
  ADCSRA = ADCSRA &amp; B01111111;
  ACSR = B10000000;
  DIDR0 = DIDR0 | B00111111;
}

void loop() {
  pinMode(LED_BUILTIN, OUTPUT);
  // Blink LED as proof
  digitalWrite(LED_BUILTIN, HIGH);
  delay(100);
  digitalWrite(LED_BUILTIN, LOW);
  delay(100);

  // Connect pin D5 to CH_PD of ESP-01 and pull high for 'enable'
  pinMode(5, OUTPUT);
  digitalWrite(5, HIGH);
  // Wait for the ESP-01 to power up and connect to WiFi network
  delay(6000);
  //
  // ... and here you do your thang
  //
  delay(1000);
  digitalWrite(5, LOW);
  // Save some power
  pinMode(PD5, INPUT);
  pinMode(LED_BUILTIN, INPUT);

  pwrDown(4); // ATmega328 powers down for 4 x 8 seconds;
}

int spi_save;
void pwrDown(int sec) {
  // Disable SPI
  spi_save = SPCR;
  SPCR = 0;

  set_sleep_mode(SLEEP_MODE_PWR_DOWN); // Select most powerfull PWR_DOWN :)
    for(int i = 0; i &lt; sec; i++) {
    sleep_enable();
    sleep_mode(); // Enter Sandman
    sleep_disable(); // After watchdog timer woke up MCU, program continues here
  }
  // Restore SPI
  SPCR = spi_save;
}

void watchdogOn() {
  MCUSR = MCUSR &amp; B11110111;
  WDTCSR = WDTCSR | B00011000;
  WDTCSR = B00100001; // Watchdog prescaler, 8 seconds
  WDTCSR = WDTCSR | B01000000; // Watchdog interrupt
  MCUSR = MCUSR &amp; B11110111;
}

ISR(WDT_vect) {
  sleepcounter ++; // Count sleep cycles
}

You set some of the bits named WDP0 through to WDP3 as per the following table, to get different wake-up times. The smallest is 16 mS and the longest is 8 S.  In the above code, we arranged longer sleep times by having a “counting” loop and sleep/wake/sleep/wake for x times.

Note that the watchdog timer is independent of the clock speed of the processor, so an 8-second watchdog timer is still that, regardless of what speed you are clocking the processor at.

ESP8266-01 code example:

Since we disable (power down) the ESP-01 module by pulling its CH_PD input pin low, we don’t need any sleep mode code running on the ESP-01.
Nevertheless, the sleep mode support within the ESP-01 is more intuitive, as it just needs a number of seconds for getting to sleep, with no iteration loop to count for. That could make the ESP_01 an even better candidate for waking up the Arduino Pro Mini. Well, in this article we send the Pro Mini to sleep, and enable/disable the ESP-01 by using its CH_PD pin.
There is a chance that we lost focus on what we ortiginally wanted to accomplish when putting the Pro Mini and ESP-01 into the same circuit. Ok, here is why. The ESP-01 doesn’t have much digital input pins, and it totally lacks any analog pin. Many sensors are either analog, or they require an SPI or I2C interface. The ESP-01 doesn’t have any of that. So when it comes to handling different kind of sensors, the Pro Mini is a much better choice. In order to send the sensor data to a server or IoT cloud service, the Pro Mini must communicate with the ESP-01 in order to tell him what to send and where. Here is the code for the ESP-01 which receives the data from the Pro Min over serial pin (RX/TX) and sends it to a server.

#include <ESP8266WiFi.h>
#include <ESP8266HTTPClient.h>

const char* ssid = "SSID";
const char* password = "Pa$$w0rd";

// sleep for this many seconds
const int sleepSeconds = 20;

const byte numChars = 32;
char receivedChars[numChars];   // an array to store the received data
boolean newData = false;

void setup () { 
  Serial.begin(9600);
  // if analog input pin 0 is unconnected, random analog
  // noise will cause the call to randomSeed() to generate
  // different seed numbers each time the sketch runs.
  // randomSeed() will then shuffle the random function.
  randomSeed(analogRead(0));
  WiFi.mode(WIFI_STA);
  WiFi.begin(ssid, password);
  
  connect();  
}
 
void sendData(String s) { 
  if (WiFi.status() == WL_CONNECTED) {    //Check WiFi connection status 
    HTTPClient http;                      //Declare an object of class HTTPClient

    String url = "http://192.168.1.105:8080/arduin_recv/ArduinoRecvServlet?sensor1=";
    url.concat(s);
    
    http.begin(url);                       //Specify request destination
    int httpCode = http.GET();             //Send the request 
    if (httpCode > 0) {                    //Check the returning code 
      String payload = http.getString();   //Get the request response payload
      Serial.println(payload);             //Print the response payload 
    } 
    http.end();   //Close connection 
  }
}

void connect() {
  int i;
  for(i = 0; i < 8; i++) {
    if(WiFi.status() != WL_CONNECTED) {
      delay(1000);
    } else {
      break;
    }
  }
}

void loop() {
    static byte ndx = 0;
    char endMarker = '\n';
    char rc;
    
    while (Serial.available() > 0 && newData == false) {
        rc = Serial.read();

        if (rc != endMarker) {
            if(rc == ' ') {
              receivedChars[ndx++] = '%';
              receivedChars[ndx++] = '2';
              receivedChars[ndx] = '0';
            } else {
              receivedChars[ndx] = rc;
            }
            ndx++;
            if (ndx >= numChars) {
                ndx = numChars - 1;
            }
        }
        else {
            receivedChars[ndx] = '\0'; // terminate the string
            ndx = 0;
            newData = true;
        }
    }
    
    if(newData) {
      sendData(String(receivedChars));
      ndx = 0;
    }
    newData = false;
}

LEAVE A COMMENT