Thank you that is an good alternative. But i am trying not to add any further hardware.
Hello particle community
I need a little bit help. I am using the System.sleep(uint16_t wakeUpPin, uint16_t edgeTriggerMode, long seconds) in order to cycle my photon in and out of stop mode. Now i understand that the photonâs processing will stop for the specified âlong secondsâ, if an external signal does not disturb it before hand, and then wake and continue running code from the point it stopped. Do timers still run in the back ground even when the photon is âstoppedâ (during the period of long seconds)? The reason i am asking is because, for example, i would like to increment a counter periodically every 3 seconds, which is the frequency that i have set the counterâs function to run at using blynkâs timer function timer1.setInterval(3000L, CounterFunction). Now this is the general idea that i have applied to specific application. My specific application requires that i saved data to an SD card, with a time stamp. Since the medium of communication between the photon is bluetooth (with builtin photon wifi switched off), i request the current date and time through the use of my projectâs Blynk interface app. So basically my hardware receives unix time from blynk over bluetooth communication and than, using particleâs pre-built time and date converter functions, i am able to produce a time stamp of the current time and date. However, since my app will not constantly be connected to the hardware (it will only definitely be connected to the hardware for the initial setup) i am required to find a way to increment the time stamp and maintain the time]ings when the hardware is disconnected from the app (e.g. if i move away from the hardware so that bluetooth comms in not possible). Now i used a counter and some elementary code to detect when the hardware app and hardware are disconnected and when this happens the time stamp manually incremented by 3 in order to maintain the time stamp. I have tested this and found a perfect correlation between the timestamp produced by this method and matched it to the timestamp produced through unix conversion. I was able to verify this by allowing my project to run for a few hours and then connecting to the app, allowing the app to immediately take over the value of the timestamp and saw that the difference between the artificially incremented time stamps as well and those that followed it lined up and measured 3 seconds apart. The problem however arises when i introduce the stop mode. Logically, witha 1 second stop mode i should simply add the additional second to my increments and the timestamp correlation should be upheld. However this is not the case, my timestamp is always a few minutes ahead of real time. I cannot understand why, other then to assume that maybe the timer controlling the execution of the counter every 3 seconds is not be stopped? Here is the code i am using:
void setup() {
Serial.begin(9600);
Serial1.begin(115200); //Initialise serial communication on the TX and RX pins
Blynk.begin(Serial1,auth); //Connect the Blynk application to the photon via bluetooth
pinMode(WindspeedPin,INPUT_PULLUP); //Specifies the Digital pin as an input
pinMode(DetectPin1, INPUT_PULLDOWN); //Set analog pin A7 as input with internal pull down resistor
pinMode(DetectPin2, INPUT_PULLUP); //Set analog pin A6 as input with internal pull up resistor
pinMode(RainSensorPin,INPUT_PULLDOWN); //Set analog pin D5 as input with internal pull down resistor
pinMode(RainDetectorPin,INPUT_PULLDOWN); //Set analog pin D6 as input with internal pull down resistor
Blynk.notify("Weather Station: Online");
Serial.println("Weather Station: Online");
delay(1000);
timer1.setInterval(3000L, AllFunctions); //Set timer1 to periodically send data to Blynk every 3 seconds
}
void loop() {
Blynk.run(); //Maintain connection to Blynk
timer1.run(); //Keep timer1 running
}
void AllFunctions(){
Windsensor();
GetVEML7700SensorData();
RainSensor();
GetBME280SensorData(); //Moved it to give it enough time to intialise
BlynkComms(); //Called last to allow sensors to make measurements before they are transmitted to the mobile app
DisplayOnSerialMonitor(); //Displays variables on the serial monitor
SaveToSDCard(); //Checks to see if the data logging to SD card is activated
TimeStampCounter=3; // Time increments by 3 when power save is not invoked
if(PowerSave1==1 & PowerSave2==1){ //Power saving mode activated when both the rain sensor and the windsensor are disconnected from the station
Blynk.syncVirtual(V14);
System.sleep(DetectPin1,RISING,1);
TimeStampCounter=3.739; // Instead of 4 i am trying to workout by trail and error what value i should use
}
Counter=0;
}
}
// The data logging to SD card code
void SaveToSDCard(){
if (digitalRead(DetectPin2)==HIGH){ //Checks if the SD card is connected
requestTime(); //Request unix time from Blynk
if(CheckSDCard==1){// Check if the SD is present
printToCard.println("\nNew batch of weather data,Date,Time,Temperature(C),Humidity(%),Pressure(hPa),Windspeed(km/h),Wind direction,Light intensity(klx),Rain fall(mm/hr)"); //This will run once only when the SD is first activated
Serial.println("\nNew batch of weather data");
if(!printToCard.getLastBeginResult()){ //To verify is data is being stored onto the SD card
Blynk.notify("SD card initializing, please wait...");
Serial.println("SD card initializing, please wait...");
CheckSDCard=1;
}
else{
Blynk.notify("Save data to SD card: Enabled");
Serial.println("Save data to SD card: Enabled");
CheckSDCard=0;
}
}
else if(CheckSDCard==0){
Serial.printlnf("The value of t0=%f before", t0);
Serial.printlnf("The value of t=%f before", t);
if(t==t0){
t=t+TimeStampCounter;
t0=t;
Serial.printlnf("Since no connection to blynk the t=t+TimeStampCounter executed. TimeStampCounter=%f", TimeStampCounter);
}
else{
t0=t;
Serial.println("The t0=t executed");
}
Serial.printlnf("The value of t0=%f after", t0);
Serial.printlnf("The value of t=%f after", t);
Seconds=Time.second(t);
Minutes=Time.minute(t);
Hours=Time.hour(t);
Day=Time.day(t);
//WeekdayNumber=Time.weekday(t);
Month=Time.month(t);
Year=Time.year(t);
Serial.printlnf("%i/%i/%i %i:%i:%i", Day, Month, Year, Hours, Minutes, Seconds);
//Serial.printlnf("Date: %i-%i-%i \nTime: %i:%i:%i ", Day, Month, Year, Hours, Minutes, Seconds);
//Serial.print("Weekday: ");
//Serial.print(Weekday);
//Serial.println("");
printToCard.printlnf(" ,%i/%i/%i,%i:%i:%i,%0.2f,%0.2f,%0.2f,%0.2f,%s,%0.2f,%0.2f,%d", Day, Month, Year, Hours, Minutes, Seconds,Temperature, Humidity, Pressure, Speed, Direction, LightIntensity, RainFall);
//Serial.printlnf("%i/%i/%i %i:%i:%i Temperature: %0.2f C, Humidity: %0.2f %, Pressure: %0.2f hPa, Windspeed: %0.2f km/h, Wind direction: %s, Light intensity: %0.2f klx, Rain fall: %0.2f mm, counter2: %d", Day, Month, Year, Hours, Minutes, Seconds,Temperature, Humidity, Pressure, Speed, Direction, LightIntensity, RainFall);
}
the variables i have used: TimeStampCounter, t and t0 have been declared as doubles since the integer value 4 is too large an increment and integer 3 is too small when stop mode is activated. Please advise.
No
However the Photon features a RTC which will keep updating the time and when the device gets woken (by said RTC) you will find that the time returned by the Time object will be pretty close to what it is supposed to be.
Another word of caution, since the RTC has only a 1 second resolution your System.sleep(DetectPin1,RISING,1) will usually not sleep for 1 second exact but only for the rest of the running second in which you are sending the device to sleep.
BTW, this is probably the wrong "AND" operator
This should probably not be the binary AND but the logical
if(PowerSave1==1 && PowerSave2==1){
While in this particular case the result will be the same, for other checks you'd probably get confusing results ![]()
Hello ScruffR. Thank you for your reply.
However the Photon features a RTC which will keep updating the time and when the device gets woken (by said RTC) you will find that the time returned by the
Timeobject will be pretty close to what it is supposed to be.
What do you mean by this? Are you talking about the accuracy in terms of switching the Photon "on" and "off" stop mode ? If not what 'time returned by RTC' do you mean?
... will usually not sleep for 1 second exact but only for the rest of the running second in which you are sending the device to sleep.
What do you mean by this? If my stop mode is set for 1 second of sleep are you saying my device will sleep for less than 1 second? Is there a way to determine how long it will be in stop mode for? I am trying by trail and error: I started reducing the value of 4 to 3.9 3.8 etc to see which value comes close but what i am noticing is that as the battery powering my project depreciates the results of my values achieve different results i.e. when i use 3.737 as the TimeStampCounter and the voltage is 3.9V i get a deviation of 80 seconds after an hour of manual incrementation, however when i test the same TimeStampCounter value and the voltage is 3.7V the deviation becomes less. This problem is only prevalent when i introduce the sleep mode. When the sleep mode is not invoked and i manually increment the time by 3, regardless of the voltage level, there is no observable deviation after an hour. This method is not proving effective when the stop mode is invoked though. Is there a better and more reliable method i can use to improve accuracy of the time obtained when stop mode is invoked?
I could set the RTC time using the unix time obtained from blynk using setTime() but is there a way to then request the time incremented by the RTC and use this incremented unix timestamp to convert to real time?
While in this particular case the result will be the same, for other checks youâd probably get confusing results
Thanks!![]()
The STM32 features a Real Time Clock which will be updating the time as long it is powered - even in deep sleep. And that same RTC is also used for the timing of the wake. When you set the device to wake in 10 seconds the system calculates what real time that would be and sets a wake schedule for that time.
So when the time of the RTC (e.g. set via the cloud or via Time.setTime() is correct before going to sleep it will still be correct after wake (maybe with ~1sec drift over a day).
e.g. when you send your device to sleep for 10 minutes at 7/5/2019 8:00:00pm immediately after (timed) wake check Time.local() you will get 7/5/2019 8:10:00 pm (ignoring the reconnect latency for illustrational purposes - e.g. with SYSTEM_THREAD(ENABLED)).
Yes, that's what I'd suspect for above reason.
With external timing device (e.g. an oscilloscope)
Depends on the kind of precision you are aiming for.
Are you not using the Particle cloud? The time provided by that is at least of the same quality and it's the "native" time base for the Time object which will be automatically set on with each new cloud connect.
Of course
int timeBeforeSleep = Time.now();
System.sleep(DetectPin1, RISING, 100, SLEEP_NETWORK_STANDBY);
int timeAfterSleep = Time.now();
Serial.printlnf("Slept for %d seconds", timeAfterSleep - timeBeforeSleep);
You keep mentioning UNIX timestamp as if it was something special. The Time object uses just that, so we can just call it time ![]()
I also don't see the benefit of using Blynk Timers instead of Particle's Software Timers.
However, with either timer I'd not rely on the 3000ms of the timer callbacks to be precise. If precision was important I'd take a snapshot of the last call (e.g. millis()) and calculate the difference between the current and the last call to account for any timer latency.
The STM32 features a Real Time Clock which will be updating the time as long it is powered - even in deep sleep. And that same RTC is also used for the timing of the wake. When you set the device to wake in 10 seconds the system calculates what real time that would be and sets a wake schedule for that time.
So when the time of the RTC (e.g. set via the cloud or viaTime.setTime()is correct before going to sleep it will still be correct after wake (maybe with ~1sec drift over a day).
e.g. when you send your device to sleep for 10 minutes at 7/5/2019 8:00:00pm immediately after (timed) wake checkTime.local()you will get 7/5/2019 8:10:00 pm (ignoring the reconnect latency for illustrational purposes - e.g. withSYSTEM_THREAD(ENABLED)).
Okay thanks i will play around with this.
A 1 second drift after a day is more than adequate precision for my application.
No i am not using the cloud, as i mentioned in the previous message, my particular project requires bluetooth communication only and i have my switched off my photon's Wi-Fi.
Thank you! this is most helpful.
I am trying to be as specific as possible to avoid any confusing.
Okay thanks, i used a similar method to determine how long my code took to run before the it restarted the cycle.
Thanks alot ScruffR, i think this might solve my problem
Hi there, I see in the Docs for the OS API there is a new way of sleeping from version 1.5.0. Has anyone got any examples of using this method, I cannot get it to work. The documentation is here:
https://docs.particle.io/reference/device-os/firmware/photon/#sleep-sleep-
Iâm assuming the top three lines I enter at the top of my code
SystemSleepConfiguration config;
config.mode(SystemSleepMode::STOP)
.gpio(D2, RISING);
and when I want to sleep I run
SystemSleepResult result = System.sleep(config);
However when I try compiling this I get the following error:
toothbrush_timer.ino:2:1: 'config' does not name a type
Can anyone give me some guidance on how to move forward.
Thanks.
Sure, there are just a few steps:
- Initialize the API - In the programâs header
SystemSleepConfiguration config; // Initialize the Sleep 2.0 API
- Set the configuration for Sleep - In your sketch - setup or loop
config.mode(SystemSleepMode::STOP) // Could use HIBERNATE here but then would only be awoken by interrupt as the RTC is not connected to a GPIO pin
.gpio(userSwitch,CHANGE)
.duration(testDurationSeconds * 1000)
.network(NETWORK_INTERFACE_CELLULAR)
.flag(SystemSleepFlag::WAIT_CLOUD);
- Call the Sleep API:
System.sleep(config);
- Optional - Figure out what woke the device from sleep
SystemSleepResult result = System.sleep(config);
Hope that helps.
Chip
Thatâs brilliant, all working now. Thank you.