Close

Basic Power Management

A project log for SunLeaf

A solar powered wireless picopower sensor module with cloud Datalogging and control geared towards plant and environmental monitoring

shane kirkbrideshane kirkbride 08/16/2016 at 14:360 Comments

Introduction

One of the goals behind SunLeaf is to enable it run without external charge for at least 2 years. This means that power is a huge factor in making this successful. We think this is possible because both chips: the STM and the ESP both have low power modes. This is not the only consideration. We also need to consider the power source. The battery we will use is here: <insert link> and the solar panel is here <insert link>. The solar panel is small, however we will rely on an adaptive the sleep mode controller to regulate the power and the best times to take a measurement. Now that we have identified the major components we can start the beginning of a power budget to show this capability.

Power budget

STM32F446RET6ESP8266 ESP-02Support hardwareTotalsunits
ModeMode
Run6Run17050226mA
Sleep3Modem sleep15018mA
Stop3Light Sleep0.903.9mA
Stand-by0.00028Deep Sleep0.00100.00128mA
Full Power0.7458W
Sleep Power0.0099033W



Power management in software

The STM32F446RE can be put into a sleep mode and then woken up using an internal interrupt in the programming:

Ticker post_data;
.
.
.
//lots of code here...
.
.
int main(){
.
.
//lots of code here...
.
.
post_data.attach(&post, 60.0); // the address of the function to be attached (post) and the interval (2 seconds)...this will wake up the STM
 
while(true){      
      if(posted)
      {
        debugSerial.printf("sleeping...\n\r");
        posted = false;
        esp.Sleep();  //put the esp to sleep
        ESPisAsleep = true;
        led2 = 0; //turn off all other power and sensors
        
        sleep();       //then sleep
      }else{
        LCD_D7 = 1;
        led2 = !led2;     
        wait(0.5); // give everything a half-second to wake up
      }
  } 

}

So basically we always keep the STM32F446RE in sleep mode unless there is an interrupt. The frequency of the interrupt is given in the second argument. This value can be adapted to optimally send environmental data while preserving the battery life. Details on this will be given in another log on complex power management. You can also see that we send the esp.Sleep() command to the ESP. esp.Sleep() did not originally come with the STM-Client so we had to add it. Here's how we did this. I'll review what was done on the STM32 then I'll review the ESP-Link Code changes. First we added to the STMClient.cpp file the following code at the bottom:

 //look in cmd.c for this. Puts ESP to sleep until a fall edge triggers on RST for it to reset.
 
void STMClient::Sleep(void){
  Request(CMD_SLEEP, 0, 0);
  Request();
}
This code calls the 'Request' function. Within STMClient.h there is a typedef. It MUST MATCH THE ONE IN THE ESP-LINK CODE: line for line.
// Enumeration of commands supported by esp-link, this needs to match the definition in
// esp-link!
typedef enum {
  CMD_NULL = 0,     // null, mainly to prevent 0 from doing something bad
  CMD_SYNC,         // synchronize, starts the protocol
  CMD_RESP_V,       // response with a value
  CMD_RESP_CB,      // response with a callback
  CMD_WIFI_STATUS,  // get the wifi status
  CMD_SLEEP,        // Go to sleep
  CMD_CB_ADD,       // add a custom callback
  CMD_CB_EVENTS,    // ???
  CMD_GET_TIME,     // get current time in seconds since the unix epoch
  //CMD_GET_INFO,

  CMD_MQTT_SETUP = 10,
  CMD_MQTT_PUBLISH,
  CMD_MQTT_SUBSCRIBE,
  CMD_MQTT_LWT,
  CMD_MQTT_EVENTS,

  CMD_REST_SETUP = 20,
  CMD_REST_REQUEST,
  CMD_REST_SETHEADER,
  CMD_REST_EVENTS
} CmdName;
This makes the CMD_SLEEP call '5'. This is useful for debug within the ESP-LINK code. What this basically does is it tells the esp to go find command '5' and execute it.Those are the required changes on the STM. You can see how easy it is to add a custom change. In the future there will likely be a few more types of sleep modes and other ESP-STM interface commands.

The ESP-LINK required a few more additions as well. All of these additions occur in the /cmd/ directory of the ESP-LINK Code.

First we had to add the CMD_SLEEP handler in handlers.c:

// Command dispatch table for serial -> ESP commands
const CmdList commands[] = {
  {CMD_NULL,            "NULL",           cmdNull},        // no-op
  {CMD_SYNC,            "SYNC",           cmdSync},        // synchronize
  {CMD_WIFI_STATUS,     "WIFI_STATUS",    cmdWifiStatus},
  {CMD_SLEEP,           "SLEEP",          cmdSleep}, //SLEEP
  {CMD_CB_ADD,          "ADD_CB",         cmdAddCallback},
#ifdef MQTT
  {CMD_MQTT_SETUP,      "MQTT_SETUP",     MQTTCMD_Setup},
  {CMD_MQTT_PUBLISH,    "MQTT_PUB",       MQTTCMD_Publish},
  {CMD_MQTT_SUBSCRIBE , "MQTT_SUB",       MQTTCMD_Subscribe},
  {CMD_MQTT_LWT,        "MQTT_LWT",       MQTTCMD_Lwt},
#endif
#ifdef REST
  {CMD_REST_SETUP,      "REST_SETUP",     REST_Setup},
  {CMD_REST_REQUEST,    "REST_REQ",       REST_Request},
  {CMD_REST_SETHEADER,  "REST_SETHDR",    REST_SetHeader},
#endif
};
And we need to add the support code later in the file:
//puts the ESP to sleep
static void ICACHE_FLASH_ATTR 
cmdSleep(CmdPacket *cmd) {
//  uint32_t sleepTime = 30000000;
  cmdResponseStart(CMD_RESP_V,espSleep(42),42); //should put this to sleep for 30s attach gpio16 to RST
  cmdResponseEnd();	
  return;
}

This basically tells the ESP to go find the espSleep() command and execute it. But we had to build a commands.c file for the espSleep() function to live in.This file is where all STM-ESP commands can live as well. Here is the entire file for now.

#include "esp8266.h"
#include "commands.h"
#include "cmd.h"

#ifdef CMD_DBG
#define DBG(format, ...) do { os_printf(format, ## __VA_ARGS__); } while(0)
#else
#define DBG(format, ...) do { } while(0)
#endif

int espSleep(uint16_t sleepTime){
  system_deep_sleep(0); 
  return 42; // rule 42, you know...this will probably never get returned because the system starts over after this...
}
commands.h is where the interfaces live and is not very interesting. We use the Espressif API Call
  system_deep_sleep(0);
to put the ESP into the lowest power mode possible. I could see other power modes implemented here in the future as well as other GPIO and DAC controls as well.

That concluded the necessary software changes for sleep modes but it also shows how to implement other commands using ESP-LINk.

Required hardware connections

There are two types of commands to be sent to the ESP from the STM. The first is sleep and the second is "wake up!". The ESP can be put into deep sleep in software as shown above. But it needs the RST pin pulled high to wake up. We do this by connecting a GPIO pin and setting it to "high" during the interrupt as shown below in the schematic.

See it in action

Below is a video of the system posting data to thingspeak.com and then going to sleep. You can see the LEDs turn off when it is asleep and they are on and flickering when it is posting data....enjoy.


Discussions