Thanks @zach, it may now be fixed but I’m not sure why and I would really appreciate someone casting a programmers eye over it as I am a beginner at this.
It has been running for 16 hrs now without any apparent symptoms. The loop() code is below.
The ‘if’ test starting about 20 lines form the end, headed ‘// signal strength LED’, is used to drive an LED (blink ON time proportional to RSSI strength) and I also use it to detect freezes by testing to see whether the blink time is much longer than expected. For more than 9 out of 10 freezes the RSSI value has been recorded as 2dB and I always suspected that had something to do with the problem.
2 days ago I added the ability to disconnect from wi-fi for 59mins every hour, just listening for commands for 1min. The thought was that it was the cc3000 that was causing the freezes (I had patched the cc3000 a week before). The ‘conn’, ‘stayConnected’ and ‘starting’ booleans manage the connection and I use a spark.function to toggle full time connection. This seemed to reduce the fault rate significantly, but they were still occurring.
The changes I made 16 hrs ago that may have fixed it were:
- corrected an error at the start of the signal strength LED loop: if (td >= 0) was previously if (td >= strTime).
- I had previously used a class called elapsedMillis (from the Arduino website) to simplify the 12 or so timers in the app. These are now handled ‘locally’ with millis()-xxxx tests. This change was a wild stab to see whether this was the cause and I don’t know why or if this fixed it.
void loop() {
cSecs = Time.now() - UNIXMONTH;
cMins = cSecs / 60 - DAYSMONTH * 24 * 60 + 600; // add 600 to get local time from UTC
if(starting)
{
if(millis() > 10 * 60 * 1000) starting = LOW; // stay connected for 10 mins after resetting
}
else
{
if(!conn && stayConnected) { // activate the stayConnected flag
Spark.connect();
conn=HIGH;
}
if(!stayConnected){
if (conn && (cMins % 60) <= 58){
delay(100);
sprintf(publishString,"close bugMins:%i bugCount:%i cMins:%i Strength:%idB",bugMins,EEPROM.read(98),cMins,Network.RSSI());
Spark.publish("connection",publishString);
Spark.disconnect();
conn=LOW;
}
}
if(!conn && (cMins % 60) > 58){
Spark.connect();
delay(1000);
sprintf(publishString,"open bugMins:%i bugCount:%i cMins:%i Strength:%idB",bugMins,EEPROM.read(98),cMins,Network.RSSI());
Spark.publish("connection",publishString);
conn=HIGH;
}
}
/*
if (publishTime-millis()>pubTime){
sprintf(publishString,"%i - %i %idB",bugMins,cMins,Network.RSSI());
Spark.publish("connection",publishString);
publishTime=millis();
}
*/
if(debug){
delay(500);
Serial.print("version: ");
Serial.print(version);
Serial.print("mins: ");
Serial.print(cMins);
Serial.print("-");
Serial.println(oMins);
Serial.print("masks: ");
Serial.print(mask0);
Serial.print("-");
Serial.println(mask1);
Serial.println(Network.RSSI());
Serial.println(Network.SSID());
}
// check time for new patterns
if(cMins >= pattern[pIndex][0] + oMins){
mask0 = pattern[pIndex][1];
mask1 = pattern[pIndex][2];
pIndex++;
if (pIndex >= pMax) {
pIndex = 0;
oMins = oMins + 1440;
}
readMask();
tMins = pattern[pIndex][0] + oMins;
}
// control fans
for (int i = 0; i < 9; i++) {
cMillis=millis();
if (outState[i] && (cMillis-tmElStr[i]) > ontime[i]) // fan is on and timer exceeded
{
outState[i] = LOW; // toggle the state from HIGH to LOW
digitalWrite(out[i], LOW);
tmElStr[i] = cMillis; // reset the counter to 0 so the counting starts over...
}
if (!outState[i] && (cMillis-tmElStr[i]) > offtime[i])
{
outState[i] = HIGH; // toggle the state from LOW to HIGH
if(m[i] == 1) digitalWrite(out[i], HIGH);
else digitalWrite(out[i], LOW);
tmElStr[i] = cMillis; // reset the counter to 0 so the counting starts over...
}
}
// random blinking LED
cMillis=millis();
if (!LEDState && (cMillis-tmElStrLED) > LEDTime)
{
LEDState = !LEDState; // toggle the state
digitalWrite(LEDOut, LEDState);
tmElStrLED = cMillis;
LEDTime = 50 + rand() % 200; // LED ON period
}
if (LEDState && (cMillis-tmElStrLED) > LEDTime)
{
LEDState = !LEDState; // toggle the state
digitalWrite(LEDOut, LEDState);
tmElStrLED = cMillis;
LEDTime = 50 + rand() % 1000; // LED OFF period
if(LEDTime < 400) LEDTime = 100;
}
// signal strength LED
cMillis=millis();
td = cMillis - tmElStrstr - strTime;
if (td >= 0)
{
if(conn) {
sigstr = (int)Network.RSSI(); // what's the signal strength
strcpy(SSID,Network.SSID()); // wi-fi network name
}
else {
sigstr = -80;
}
if(td > 20000) // 20 secs more than expected -> some sort of slow down bug??? record it.
{
delay(20);
int bugCount = EEPROM.read(98);
delay(20);
if(bugCount >= 250) bugCount = 0;
delay(20);
EEPROM.write(98,bugCount + 1);
bugMins = cMins;
delay(20);
bugsig = sigstr;
bugtime = td;
}
if(!strState)
{
strTime = map(sigstr,-80,-50,150,4000);
strTime = constrain(strTime,150,4000);
strState = HIGH;
digitalWrite(strOut, HIGH);
}
else
{
strTime = 300;
strState = LOW;
digitalWrite(strOut, LOW);
}
tmElStrstr = cMillis;
}
}
There are various other support functions that are not called frequently, eg UNIXMONTH, DAYSMONTH, pattern[][], etc. are stored in EEPROM and received OTA using a spark.function and read from memory upon reset or on command. The spark.publish component is in development and only works when connected.
Debugging capability is limited and is normally via queries to various variables using a spark.function as it is not easy to wire up via USB when in-situ.
The core is being used in a kinetic artwork driven by data scraped from a public website. The example here is running with a UNO which requires me to reprogram it daily by USB. The goal is to program it from home OTA with the core. Data scraping and communication uses Processing, but I just saw this post which gives me hope the whole thing can be done real-time on the core - subject to my programming skills
Thanks for your help,
Andrew