Author Topic: Low power oak and watchdog timer advice needed  (Read 4483 times)

Brucutus

  • Newbie
  • *
  • Posts: 5
Low power oak and watchdog timer advice needed
« on: January 24, 2017, 10:54:00 pm »
I'm looking into using one of my oaks to run off a solar charged Li-ion battery perpetually and only wake up specific time several times a day. I need to get it into a low power mode and using some strategy to wake it up using something like a watchdog timer. 
Sample code I found:
#include <avr/sleep.h>
#include <avr/power.h>
#include <avr/wdt.h>

ISR(WDT_vect)
{
  if(f_wdt == 0)
  {
    f_wdt=1;
  }

...
 fails finding the #includes.  I assume this means no support is built in?  Is there a workaround or would I do better with a Arduino Nano or Teensy + ESP8266, Arduino MKR1000, Particle or any other board?
If I don't use an Oak or Particle, would there still be away to access the Particle cloud?
Bruce

PeterF

  • Hero Member
  • *****
  • Posts: 881
Re: Low power oak and watchdog timer advice needed
« Reply #1 on: January 25, 2017, 01:24:17 am »
Sounds doable. The code you've come across is AVR specific - ie. Arduino Uno/Nano specific, so won't work with the ESP8266 chip in the Oak. However, it has it's own sleep implementation (deepSleep), which you can instruct on how long it should sleep for, at which point the Oak will reboot and start afresh.

Basically, you connect the Wake pin of your Oak to the Reset (RST) pin, as this is how the Oak will reset itself at the end of the deepsleep period.

Then, in your code, when you're ready to power down the Oak for it's nap, do something like a

Code: [Select]
ESP.deepSleep(sleepSeconds*1000000, WAKE_RF_DEFAULT);
where sleepSeconds is the number of seconds to sleep. It draws so little power in deep sleep mode your battery will pretty much last forever if it is in sleep mode most of the time. You'll then need to either use a check at the start of your code to disable sleep mode, or use the Oaks config mode (P1 to GND for a few seconds when powering on) to do OTA programming.

You can also cut the [LED EN] power led pad on the Oak so that doesn't use power necessarily.

Brucutus

  • Newbie
  • *
  • Posts: 5
Re: Low power oak and watchdog timer advice needed
« Reply #2 on: January 26, 2017, 01:07:51 am »
Thanks a bunch.  I'm having it go low power and wake as expected, but from what I read, I'm not seeing setup() called after each wakeup.  My loop() seems to get called instead (although I did get into the setup sleep loop once).  I'm also not seeing my debug strings sent to the digistump dashboard.  Could these things be related?  Or could there be some floating pin?

#include "stdlib.h"
#include <ESP8266WiFi.h>

#define LED_PIN 1
#define WAKE_PIN 5
#define sleepSeconds 10

int mins = 0;

void setup()
{
  pinMode(LED_PIN,OUTPUT);
  delay(100); //Allow for serial print to complete.
 
  digitalWrite(LED_PIN, HIGH);   // turn the LED on (HIGH is the voltage level)
  delay(150);               // wait for a second
  digitalWrite(LED_PIN, LOW);    // turn the LED off by making the voltage LOW
  delay(100);               // wait for a second

  // Check to see if sleep mode selected
  if (digitalRead(WAKE_PIN) == HIGH) {
     Particle.publish("debug", "Entering Deep Sleep");
     delay(1000);
     ESP.deepSleep(sleepSeconds*1000000, WAKE_RF_DEFAULT); // Sleep
  }
  else {
     Particle.publish("debug", "Entering Non Sleep Mode");
     delay(1000);
  }
} //END setup()


void loop() {
 short i;
 
  // 20 seconds of blinks
  for(i=0; i<80; i++)
  {
    digitalWrite(LED_PIN, HIGH);   // turn the LED on (HIGH is the voltage level)
    delay(150);               // wait for a second
    digitalWrite(LED_PIN, LOW);    // turn the LED off by making the voltage LOW
    delay(100);               // wait for a second
  }
  Particle.publish("debug", "Entering loop Sleep Mode");
  delay(1000);
  ESP.deepSleep(sleepSeconds*1000000, WAKE_RF_DEFAULT); // Sleep
}

PeterF

  • Hero Member
  • *****
  • Posts: 881
Re: Low power oak and watchdog timer advice needed
« Reply #3 on: January 26, 2017, 01:37:35 am »
I'll have to think about it a bit more (brain freeze)... but my initial thought is:

1) it can't skip setup... so how is it?

2) re-read 1 several times, and then continue (that's where I'm stuck at atm... sheer denial ;)

3) yes, possibly floating pin... so perhaps define WAKE_PIN as pinMode(WAKE_PIN,INPUT_PULLUP); and check for the pin being LOW instead of HIGH?

maybe some more checks are needed... perhaps the wifi isn't fully up before it goes to sleep? Try something like a

Code: [Select]
while (!Oak.connected())
{
    digitalWrite(LED_PIN,!digitalRead(LED_PIN));
    delay(250);
}

before the check for sleep mode in setup... it should blink the LED_PIN on and off every 250ms if the WiFi is still booting up... if I wrote it properly, that is! :-O

I also like to manage the WiFi a bit more manually (instead of on pure auto), so we can walk through that if you're interested and it is still being stubborn.

exeng

  • Sr. Member
  • ****
  • Posts: 454
Re: Low power oak and watchdog timer advice needed
« Reply #4 on: January 26, 2017, 08:32:30 am »
Brutucus,

If you are judging whether or not you are entering stepup() upon wake up by your particle publish, I think Pete is correct in thinking that WiFi has not connected to Particle yet. Or what we might call a race condition. If you are judging it based upon your LED output, your delay comments say one second, your code turns on the LED for 150ms. Easy to miss if you are not watching it carefully. You may want to increase the on time and add a delay to give WiFi time to connect before your Particle.publish.

UPDATE: So I was looking at an example of using sleep mode that I created for DS18B20 wiki a long time ago... I thought the use of a sleep indicator pin looked familiar. Two things I noticed; 1. There is no significant delay in setup specifically to wait for WiFi to come up upon wake other than the code intended to do some work in setup, and 2. The original idea behind using the sleep indicator pin was to provide two modes of operation. If the pin was high we would do our work in setup and sleep (rinse and repeat). If the pin was low we would do work in setup(), not sleep, then continue on to loop(), continue to do work and never sleep. I guess the same could be accomplished by simply checking for the sleep indicator in loop() and not in setup() with a little restructuring of the code. Again, the original intent was to provide a sleep / non sleep (user selected) option for a sketch. Hope this doesn't confuse things.
« Last Edit: January 26, 2017, 08:53:23 am by exeng »

Brucutus

  • Newbie
  • *
  • Posts: 5
Re: Low power oak and watchdog timer advice needed
« Reply #5 on: February 05, 2017, 11:37:45 am »
I'm not really interested in determining the condition of sleep or not -  I just need the system to wake up after some interval and run a motor if the time is right.  Right now I can't figure out how to save the state of the motor when sleeping (sometime it needs to run CW or CCW).  After every wakeup the state variable resets.  I've tried declaring it a volatile, but that still doesn't work. 
I thought of saving the state to the particle cloud, but the 'use case' doesn't seem to support a save/load type operation.  Or maybe I'm missing some low level Particle functions?

exeng

  • Sr. Member
  • ****
  • Posts: 454
Re: Low power oak and watchdog timer advice needed
« Reply #6 on: February 05, 2017, 02:05:56 pm »
What about using the Oak's EEPROM? Or, if you prefer to use the cloud to store and retrieve state, perhaps a ThinkSpeak channel. I would try EEPROM first. I think there is an EEPROM example sketch for the Oak.

PeterF

  • Hero Member
  • *****
  • Posts: 881
Re: Low power oak and watchdog timer advice needed
« Reply #7 on: February 05, 2017, 03:32:33 pm »
Yeah, there is no point trying to save it in a variable, as what the Oak actually does when instructed to sleep is power down, and after the specified time has elapsed, the WAKE pin triggers a reset (hence why you need to bind WAKE to RST when using deep sleep) in order to wake up the Oak. So as exeng said, either store it locally in EEPROM (which on the Oak is really just a sector of the flash memory) (there are three included examples - one to write, another to read, and another to clear -  and I beleive the only real difference is in how you use EEPROM.begin) or maybe use thingspeak or ubidots to store it online. You haven't missed anything, there is nothing in the Particle data set that I have seen thus far which is aligned towards any sort of data storage - it is really just a connector.