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;
}
}