When I upload code to my spark device, sometimes the old code is still on the device (problem with upload). And sometime i have to powercycle the device to run the uploaded code. I would like to use the eeprom function to check if the running code has the same version as the one uploaded earlier. Is there any compiler directive to add some timestamp as a constant into code? Then I can run a short deep_sleep command to restart like a power cycle.
Hmm. Sounds like we should really fix the underlying bug and improve reliability of the flash. Is this from programming over USB, or over the air? If it’s over the air, have you installed the deep update?
While I agree with @zach to fix the root of your problems, I think this is also a valuable debugging tool that has been requested in the past. Here’s an example of how to gain access to the date and time at compile time. These are standard GNU predefined Macros. Here I’ve exposed the string as a variable so you can see it, but I am also working on a complete example with the EEPROM. Too bad my laptop is dying and I have no power adapter with me This is all you get for now!
//#pragma SPARK_NO_PREPROCESSOR
//-------------------------------------------
#include "application.h"
//-------------------------------------------
// https://gcc.gnu.org/onlinedocs/cpp/Standard-Predefined-Macros.html
#define COMPILED_TIME __TIME__
#define COMPILED_DATE __DATE__
//-------------------------------------------
char compiledDateTime[22] = COMPILED_DATE;
//-------------------------------------------
void setup() {
strcat(compiledDateTime, " - ");
strcat(compiledDateTime, COMPILED_TIME);
// Expose a variable via GET API for diagnostics
// https://api.spark.io/v1/devices/DEVICE_ID/compiled?access_token=ACCESS_TOKEN_ID
Spark.variable("compiled", &compiledDateTime, STRING);
}
//-------------------------------------------
void loop() {
}
@Zach: Yes i upload over air. I have setup my computer to upload over USB but I did not figured out yet, how to use additional libraries. I use the timber demo to restore.
@peekay: This is a good tipp. I will check this out.
Just to give you some hints about my project: It is a weather station running four sensors for temp, humidity, pressure, light and power. The station stays in the backyard powered only by solar energy with battery backup. Today, I use a jumper on the board to tell SPARK to use power saving mechanism. If the jumper is on, the device uses the deep_sleep mode to save energy. Without jumper the device stays idle runig the SPARK_WLAN_Loop().
When i want to upload code, the device is in idle an waits for update. Sometimes the device start blinking like an update, but at the end the device is not updated. This is why I asked about timestamps to check if the upload is a success.
What I miss is a function which tells me that WLAN is REALLY ready to connnect other devices. The core firmware function does not provide such functionaltity. I have to use a static delay about 5 seconds to successfully send data to another server.
Spark.variable(“compiled”, &compiledDateTime, STRING); does not work for my solution because it is read directly from the device. My device is mostly sleeping so responses fails.
It would be very nice to have a function which the device can read data from the cloud and then can react in any matter. So I can set a variable with my browser and the device can read it after it awakes from sleep. This would allow me to prevent further power safe and I can upload new software.
Power saving is a very important issue in every battery driven application. So there should be a firmware thats aware of it.
Sounds like you could use Spark.publish() and Spark.subscribe() for this… coupled with some other mechanisms to remotely verify that new firmware is indeed running.
You could open a browser page with your App that allows you to Publish a flag (with a longer TTL in seconds than your core is deep sleeping for) to the Spark Cloud that says “Time to reprogram”, and the Core that is constantly deep sleeping for long periods of time will periodically wake up and run Spark.subscribe() on that event. If it exists and is true, then it can stay awake for a period of time. Your web App can also periodically check to see if your Core is online, and as soon as it is… Alert you to reflash your Core. Or, you could make this entire process autonomous with a Node.js script and the local Spark CLI.
BTW, sorry I haven’t had time to work on the EEPROM code further… work and home projects have consumed a lot of my time recently.
Here is my unfinished EEPROM code that compiles, but doesn’t work yet. I haven’t debugged it… but perhaps you can make it work before I get a chance to:
//#pragma SPARK_NO_PREPROCESSOR
//-------------------------------------------
#include "application.h"
//-------------------------------------------
// https://gcc.gnu.org/onlinedocs/cpp/Standard-Predefined-Macros.html
#define COMPILED_TIME __TIME__
#define COMPILED_DATE __DATE__
//-------------------------------------------
void flashLED(uint8_t cycles, uint8_t hertz);
//-------------------------------------------
char compiledDateTime[22] = COMPILED_DATE;
char savedDateTime[22] = "";
//-------------------------------------------
void setup() {
pinMode(D7,OUTPUT);
strcat(compiledDateTime, " - ");
strcat(compiledDateTime, COMPILED_TIME);
// Read savedDateTime from EEPROM
for(uint8_t x=0; x<22; x++) {
uint8_t val = EEPROM.read(x);
strcat(savedDateTime, (const char*)val);
}
// If versions are the same, flash D7 LED fast
if(strncmp(compiledDateTime, savedDateTime, 22) == 0) {
flashLED(20, 5); // 20 times at 5 hertz
}
else {
// flash D7 LED slow and
flashLED(10, 2); // 10 times at 2 hertz
// overwrite savedDateTime with new val
for(uint8_t x=0; x<22; x++) {
EEPROM.write(x, compiledDateTime[x]);
}
}
// Expose variables via GET API for diagnostics
// https://api.spark.io/v1/devices/DEVICE_ID/serial?access_token=ACCESS_TOKEN_ID
// https://api.spark.io/v1/devices/DEVICE_ID/saved?access_token=ACCESS_TOKEN_ID
Spark.variable("compiled", &compiledDateTime, STRING);
Spark.variable("saved", &savedDateTime, STRING);
}
//-------------------------------------------
void loop() {
}
//-------------------------------------------
void flashLED(uint8_t cycles, uint8_t hertz) {
for(uint8_t x=0; x<cycles; x++) {
digitalWrite(D7,HIGH);
delay(500/hertz);
digitalWrite(D7,LOW);
delay(500/hertz);
}
}
For this project, the device sends the data to my Raspberry Pi. I use a simple PHP script to fill all data into a RRD database. To enter PRGM mode I let the script response the char $. If no char is send back, the device will sleep instead if idleing.