Cant get photon to sleep and wakeup

Hi,
I am trying for some time now to make a weather station with a photon and weathershield.
See my projectpage here: https://www.hanscees.com/photon/charts-data-sparkfun.html (be patient for the diagrams, they are very slow).

I can get the photon to read data and post to data.sparkfun fine.
However, I am trying to safe energy by going to sleep mode. Alas, it does not wake up again, or only someyimes. I have tried several things and followed several guides, but no success.

Can someone please help and tell me where my code is wrong? I am not a programmer, more of a hacker so my C coding is copy-paste from others (I mostly speak bash and python).

#include "SparkFun_Photon_Weather_Shield_Library.h"
#include "SparkFunPhant.h"

int WDIR = A0;
int RAIN = D2;
int WSPEED = D3;

//Global Variables
//-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=
long lastSecond; //The millis counter to see when a second rolls by
byte seconds; //When it hits 60, increase the current minute
byte seconds_2m; //Keeps track of the "wind speed/dir avg" over last 2 minutes array of data
byte minutes; //Keeps track of where we are in various arrays of data
byte minutes_10m; //Keeps track of where we are in wind gust/dir over last 10 minutes array of data

//We need to keep track of the following variables:
//Wind speed/dir each update (no storage)
//Wind gust/dir over the day (no storage)
//Wind speed/dir, avg over 2 minutes (store 1 per second)
//Wind gust/dir over last 10 minutes (store 1 per minute)
//Rain over the past hour (store 1 per minute)
//Total rain over date (store one per day)

byte windspdavg[120]; //120 bytes to keep track of 2 minute average
int winddiravg[120]; //120 ints to keep track of 2 minute average
float windgust_10m[10]; //10 floats to keep track of 10 minute max
int windgustdirection_10m[10]; //10 ints to keep track of 10 minute max
volatile float rainHour[60]; //60 floating numbers to keep track of 60 minutes of rain

//These are all the weather values that wunderground expects:
int winddir = 0; // [0-360 instantaneous wind direction]
float windspeedmph = 0; // [mph instantaneous wind speed]
float windspeedkmh = 0; // [windspeed mh added by hanscees ]
float windgustmph = 0; // [mph current wind gust, using software specific time period]
float windgustkmh = 0; // [kmh current wind gust, using software specific time period]
int windgustdir = 0; // [0-360 using software specific time period]
float windspdmph_avg2m = 0; // [mph 2 minute average wind speed mph]
float windspdkmh_avg2m = 0; // [kmh 2 minute average wind speed mph]
int winddir_avg2m = 0; // [0-360 2 minute average wind direction]
float windgustmph_10m = 0; // [mph past 10 minutes wind gust mph ]
float windgustkmh_10m = 0; // [kmh past 10 minutes wind gust mph ]
int windgustdir_10m = 0; // [0-360 past 10 minutes wind gust direction]
float rainin = 0; // [rain inches over the past hour)] -- the accumulated rainfall in the past 60 min
long lastWindCheck = 0;
volatile float dailyrainin = 0; // [rain inches so far today in local time]

float humidity = 0;
float tempf = 0;
float tempc = 0;
float pascals = 0;
//float altf = 0;//uncomment this if using altitude mode instead
float baroTemp = 0;

int count = 0;//This triggers a post and print on the first time through the loop
int startuph = 0; // if startup after power down do stuff

unsigned long firstAvailable = 0;
#define toggleLED() (digitalWrite(D7, !digitalRead(D7)))

// volatiles are subject to modification by IRQs
volatile long lastWindIRQ = 0;
volatile byte windClicks = 0;
volatile unsigned long raintime, rainlast, raininterval, rain;

//Create Instance of HTU21D or SI7021 temp and humidity sensor and MPL3115A2 barrometric sensor
Weather sensor;

////////////PHANT STUFF//////////////////////////////////////////////////////////////////
const char server[] = "data.sparkfun.com";
const char publicKey[] = "yA0EjKV3owhKNx1NlN3w";
const char privateKey[] = "qwertyuiopasdfghjkl";
Phant phant(server, publicKey, privateKey);
/////////////////////////////////////////////////////////////////////////////////////////

//Interrupt routines (these are called by the hardware interrupts, not by the main code)
//-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=
void rainIRQ()
// Count rain gauge bucket tips as they occur
// Activated by the magnet and reed switch in the rain gauge, attached to input D2
{
  raintime = millis(); // grab current time
  raininterval = raintime - rainlast; // calculate interval between this and last event

    if (raininterval > 10) // ignore switch-bounce glitches less than 10mS after initial edge
  {
    dailyrainin += 0.011; //Each dump is 0.011" of water
    rainHour[minutes] += 0.011; //Increase this minute's amount of rain

    rainlast = raintime; // set up for next event
  }
}

void wspeedIRQ()
// Activated by the magnet in the anemometer (2 ticks per rotation), attached to input D3
{
  if (millis() - lastWindIRQ > 10) // Ignore switch-bounce glitches less than 10ms (142MPH max reading) after the reed switch closes
  {
    lastWindIRQ = millis(); //Grab the current time
    windClicks++; //There is 1.492MPH for each click per second.
  }
}

//---------------------------------------------------------------
void setup()
{
    // initialization
    sensor.begin();
    // sync time as here https://community.particle.io/t/time-synchronization-cant-set-rtc-time-upon-reboot-solved/8803/8
    // Spark.connect();
        while(Time.year() <= 1970) // 1969 in my case
            {
                Spark.syncTime();
                Spark.process();
                delay(100);
            }
        // Spark.disconnect();
        Time.zone(+2);




    pinMode(WSPEED, INPUT_PULLUP); // input from wind meters windspeed sensor
    pinMode(RAIN, INPUT_PULLUP); // input from wind meters rain gauge sensor

    Serial.begin(9600);   // open serial over USB
    //Begin posting data immediately instead of waiting for a key press.

    //Initialize the I2C sensors and ping them
    sensor.begin();

    /*You can only receive acurate barrometric readings or acurate altitiude
    readings at a given time, not both at the same time. The following two lines
    tell the sensor what mode to use. You could easily write a function that
    takes a reading in one made and then switches to the other mode to grab that
    reading, resulting in data that contains both acurate altitude and barrometric
    readings. For this example, we will only be using the barometer mode. Be sure
    to only uncomment one line at a time. */
    sensor.setModeBarometer();//Set to Barometer Mode
    //baro.setModeAltimeter();//Set to altimeter Mode

    //These are additional MPL3115A2 functions the MUST be called for the sensor to work.
    sensor.setOversampleRate(7); // Set Oversample rate
    //Call with a rate from 0 to 7. See page 33 for table of ratios.
    //Sets the over sample rate. Datasheet calls for 128 but you can set it
    //from 1 to 128 samples. The higher the oversample rate the greater
    //the time between data samples.

    sensor.enableEventFlags(); //Necessary register calls to enble temp, baro ansd alt

    seconds = 0;
    lastSecond = millis();

    // attach external interrupt pins to IRQ functions
    attachInterrupt(RAIN, rainIRQ, FALLING);
    attachInterrupt(WSPEED, wspeedIRQ, FALLING);

    // turn on interrupts
    interrupts();

    getWeather();//get initial values out of the way
    delay(1000);
    getWeather();//print before entering the loop and waiting for count
    printInfo();
   postToPhant();
   //wait 3 minutes so we can flash if neccesary, after that shut down wifi
   delay(180000);
   WiFi.off();
}
//---------------------------------------------------------------
void loop()
{
  //Keep track of which minute it is
  if(millis() - lastSecond >= 1000)
  {

    lastSecond += 1000;

    //Take a speed and direction reading every second for 2 minute average
    if(++seconds_2m > 119) seconds_2m = 0;

    //Calc the wind speed and direction every second for 120 second to get 2 minute average
    float currentSpeed = get_wind_speed();
    //float currentSpeed = random(5); //For testing
    int currentDirection = get_wind_direction();
    windspdavg[seconds_2m] = (int)currentSpeed;
    winddiravg[seconds_2m] = currentDirection;
    //if(seconds_2m % 10 == 0) displayArrays(); //For testing

    //Check to see if this is a gust for the minute
    if(currentSpeed > windgust_10m[minutes_10m])
    {
      windgust_10m[minutes_10m] = currentSpeed;
      windgustdirection_10m[minutes_10m] = currentDirection;
    }

    //Check to see if this is a gust for the day
    if(currentSpeed > windgustmph)
    {
      windgustmph = currentSpeed;
      windgustdir = currentDirection;
    }

    if(++seconds > 59)
    {
      seconds = 0;

      if(++minutes > 59) minutes = 0;
      if(++minutes_10m > 9) minutes_10m = 0;
      if(++minutes > 59)
      {

      rainHour[minutes] = 0; //Zero out this minute's rainfall amount
      windgust_10m[minutes_10m] = 0; //Zero out this minute's gust
    }

    //Rather than use a delay, keeping track of a counter allows the photon to
    // still take readings and do work in between printing out data.
    count++;
    //alter this number to change the amount of time between each reading
    if(count == 500)
    {
      //Get readings from all sensors
       getWeather();
       printInfo();
       //connect to wifi, not to cloud
       if (!WiFi.ready()) {
            WiFi.connect();
            while (WiFi.connecting())
            {
                toggleLED();
                delay(100);
             firstAvailable = 0;
              //  Spark.process();
            }
          }

       postToPhant();
       delay(1000); //might take a while?
       count = 0;
       //drop wifi again
       WiFi.off();
       //sleep x minutes after posting and shut down wifi
       // sleep doesnt work reliable
       // System.sleep(450);
       }
    }
  }
  // see https://github.com/sparkfun/Photon_Weather_Shield/issues/10
  int currentTime = Time.now();
  if ((Time.hour(currentTime) == 0) && (Time.minute(currentTime) == 0) && (Time.second(currentTime) == 0)){
          dailyrainin = 0;
      }
}

The code is here : https://www.hanscees.com/photon/Sparkfun-Weather-Phant-hc-2017-03-1.txt

So my wifi stategy is:

  1. collect data, & post data to phant server in startup
  2. shut down wifi and goto the loop part
  3. wait 500 loops and collect new data
  4. connect to wifi
  5. post new data to phant server
  6. shut down wifi again
  7. and loop forever

There currently are issues with this "non-sleep" sleep mode (and I don't really see the point of it anyway - when code is still runnung, let the code control the radio :wink: )
https://github.com/spark/firmware/issues/1233

But for this

What is the problem you can't fix? Without any info what we should look out for we probably won't find what you expect us to :sunglasses:

Hi,
I want the wifi to turn on if I want to send something to the internet. In this bit of code, thereby saving energy. Why doesnt it turn on?:

 printInfo();
   //connect to wifi, not to cloud
   if (!WiFi.ready()) {
        WiFi.connect();
        while (WiFi.connecting())
        {
            toggleLED();
            delay(100);
         firstAvailable = 0;
          //  Spark.process();
        }
      }

   postToPhant();
   delay(1000); //might take a while?
   count = 0;
   //drop wifi again
   WiFi.off();

This code works fine for me. What result does this code give you? Is toggleLED() being called? What color pattern are you seeing on the system LED? Do you know that the code is reaching the if (!WiFi.ready()) line?

2 Likes

Also even after WiFi.connecting() becomes false this will not immediately mean that WiFi.ready() will be true.
Iā€™d still add waitFor(WiFi.ready, 5000) safeguard.

2 Likes

Hi,

thanks for your help. When I started troubleshooting properly as Ric suggested it appears the code indeed works fine: I was looking in the wrong direction!
It appears the data.sparkfun website is just deadslow or non-responsive, so the post just fails often. Took me a week to find out :frowning:
So the wifi wakes up just fine!

2 Likes