Cyan Flash of Death Killer

Haha, I finally built my first project.

I am such a newbie and cant figure out the REST thing yet, so my skills remain at the traditional Arduino level. I am sorry if this has already been done before, but I am pretty proud of it! :smile:

Ok, so while playing with the Spark, I found, as others have found, the Cyan Flash of Death CFOD. I couldn’t keep it running for a day, which means any project I build will cease to run until the CFOD is fixed.

When you get a CFOD, it temporarily stops the running program, and to recover you have to push the reset button to bring the cloud back and restart a program.

So using an ATTiny85 ($3) programmed using my Arduino Uno using steps off of the net, I created the CFOD Killer! It listens to see if the program is running, if not it pushes the reset button for you. :smile: Thats it!

Intermittent wifi or internet disconnects wont trigger the reset, only if the code ceases to run during reconnect.

What do you think?

Thanks,
Sparky

2 Likes

nice work. Could you share the attiny code and any special setup in your Spark code?

And please share a circuit diagram of the connections.

I am curious as to how the ATtiny knows the core is not running during reconnect.

Thank you

Yea please share the code.

How does the ATTiny 85 know the loop has stopped running exactly?

My loop will freeze up with a flashing Green light, and it will freeze up sometimes while the Cyan is breathing like everything is fine. So if the ATTiny 85 is just listening for a short burst pattern output from the Spark Core and then triggers a output that triggers the reset pin on the Spark Core then I can see that solving all the lock up issues I’m seeing over the last week.

Good move forward regardless.

Absolutely!!! I need to keep testing of course, but when trying to duplicate outages as soon as the code stops the reset occurs flawlessly so far. Lets see how it does with a week running.

So here is how it works: the Spark runs code in a loop, I placed a small code that tells it to toggle a pin on and off every 5 seconds (you can adjust this). The reason I did this rather than just keep a pin on as an indicator is I found when the code freezes, it keeps the current state, therefore never distinguishes that the code froze. This fixes that by requiring constant change.

The attiny is listening in on that pin, and records the last change. If it has been 10 seconds since the last change (you can adjust this too), it will trigger the reset pin.

The attiny is powered by the core itself.

I programmed the attiny using an arduino uno via: http://highlowtech.org/?p=1695

Here is how it is hooked up:
Spark: A7 to pin 3 of attiny as trigger pin or sensor pin
Spark Gnd to pin 4 of chip
Spark 3v3 to pin 8 of chip
Reset to pin 5 of chip

I tried to comment everything, hope it helps! I am sure there is a better way to write this code but I am a newbie.

Spark Code

    int trigger = A7; // this is the pin talking to the attiny
int led = 7; // this is the led pin for a visual indicator that things are running, it is optional

void setup() { // setup
    pinMode(trigger, OUTPUT); // set signal pin to output
    pinMode (led, OUTPUT); // set led pin to output
}

void loop() { // loop
checker(); // This tells the code to send the checker signal in the loop

///////////////////////////
// place nrmal code here //
///////////////////////////

}

void checker() // trigger code
{
delay(5000); // wait 5 seconds between signals
digitalWrite(led,HIGH); // indicator on
digitalWrite(trigger,HIGH); // Send signal
delay (1000); // wait
digitalWrite(trigger,LOW); // turn off signal
digitalWrite(led,LOW); // turn off indicator
}

Here is the ATTINY Code

    /*

Spark Cyan Flash of Death Killer - by Scott Lichtenstein (StartGroup) 
Open Sourcec - Please feel free to do whatever you want with this! :)

 */

const int resetButton = 0; // pin that will flip the reset switch
int sensorValue = 0;  // variable to store the value coming from the Spark pin
int sensorPin = 3;    // pin from Spark Core
int sensorState;   // holds current state of pin from Spark Core 
int lastTriggerState = LOW;   // the last successful read of the Spark Core pin
long lastTriggerTime = 0;  // the last time the state was changed

void setup() {
  delay(10000);  // wait 10 seconds for the core to connect.
  pinMode(resetButton, OUTPUT); // call the resetbutton pin as an output
  pinMode(sensorPin, INPUT);  // call the sernsorPin as an input
  digitalWrite(resetButton, HIGH);   // Keep reset pin at high until further notice
}

void loop() { // here starts my loop

  setState(); // checks the sensor and sets value to 1 or 0 depending on its value
  
  if (sensorState != lastTriggerState) { // checks if pin is the same or different from last time.
  lastTriggerTime = millis(); // sets new time for change
  lastTriggerState = sensorState;  // changes new state
  } 

  if ((millis() - lastTriggerTime)>10000){ // if it has been more than 10 seconds since the state has changed, do a reset
     reset(); // activate reset function
  }
}
void reset(){ // here is the reset function
  digitalWrite(resetButton,LOW); // Push Reset button 
  delay(1000); // Wait
  digitalWrite(resetButton,HIGH); // Let go of Reset button
  delay(30000); // wait 30 deconds for reconnect prior to checking again
}

void setState(){ // here is the set state function, number varibles are just to identify change in state.
  sensorValue = analogRead(sensorPin); // check for spark pin
  if (sensorValue < 500)  // if analog value is less than 500, set to variable 0
{
  sensorState = 0; // variable 0
}
if (sensorValue > 500) // if analog state is more than 500, set to varible 1
{
  sensorState = 1; // varible 1
}
}

*Please keep me updated it if helps you! :smile: I am so excited to be able to contribute! *

AWESOME!!! I just witnessed it happen! While I was last posting, the light flashed green for a few seconds, it didn’t even wait for the Cyan and just reset!!! I am not sure how long it was flashing cause I just looked up, but based on my code it couldnt have been more than 10 seconds! HAHAH!A So excited!

Cool!

I’ll have a Adafruit Trinket which is a ATTiny 85 that will allow me to run the test here. I try it with all the error messages I have been experiencing and report back.

Sounds promising though!

Very nice @Sparky! You dropped this at the same time I was messing around with creating something with 555 Timers I would much prefer the ATTiny25/45/85 solution though.

I have a Core code suggestion… to avoid blocking the loop just to toggle the pin:

int trigger = A7; // this is the pin talking to the attiny
int led = D7; // this is the led pin for a visual indicator that things are running, it is optional
uint32_t lastKick = 0; // last time we kicked the watch dog
bool s = false; // output state of the watch dog

void setup()
{
  lastKick = millis(); // We just powered up
  pinMode(trigger, OUTPUT); // set signal pin to output
  pinMode (led, OUTPUT); // set led pin to output
}

void loop() {
  kickTheDog(); // kick the watchdog

  ////////////////////////////
  // place normal code here //
  ////////////////////////////

} // End main loop (currently runs every 5-6 ms)

void kickTheDog() { // kick the dog every 5 seconds
  if( (millis()-lastKick) > 5000 ) {
    lastKick = millis();
    s = !s; // toggle the outputs
    digitalWrite(led,s); // watchdog indicator
    digitalWrite(trigger,s); // watchdog signal
  }
} 

Now this just goes HIGH for 5 seconds, and then LOW for 5 seconds. Different than your timing, but you shouldn’t have to change your ATTiny code.

1 Like

Awesome suggestion! I know there has to be a better way than how I wrote it. I love your comments. lol

Also, I just tried reprogramming my Spark for an adjustment, and found the CFOD Killer resets it before it finishes. So in the ATTiny code I told it to wait 5 minutes from now on instead of 10 seconds. This is way I do not have to unplug the CFPD Killer. I am not running any projects right now so 5 minutes doesn’t matter to me.

1 Like

@Sparky & @BDub

Problem Solved! This is working fine and I guess as BDub said this is an example of a watchdog backup system. I’m learning here!

I quickly forced all 3 situations that has caused the Spark Core lock up over the past week and this ATTiny 85 successfully resolved all of them quickly.

The ATTiny code will reset the spark core every 60 seconds if it does not see a pulsed output coming from the Spark Cores A7 Pin.

Awesome! Now we have a Spark Core that will hold a reliable connection to the internet!

I’m seeing the core being reset every few mins now. I think it might have something to do with the Trinket running at 5v and the Spark Core being a 3.3v board. If thats not it then this is not working for me for some reason, its just resetting the spark core about every min when before the spark core would stay connected for hours and hours before locking up.

What I did first is use an LED to test my code and hookup. After a bit of fiddling, I got it for sure to only reset when down. The way I would test this is unplug the signal wire and watch the led blink telling me that it was hitting the reset button, when I plug the signal wire back in it stops. I would play around with it, adjust the state function and look for different variables. Or maybe try a resister as a pullup or pulldown.

Make sure to watch your blue indicator light on the core to make sure the core is running and not something with your wifi. If the indicator light is sending the pules, as described in the code above, you will know the problem lies in the way you have it hooked up or with the CFOD Killer device. If the blue indicator light on the core is not constant with its pules, then the probably might be within your connection.

Also, it might be important to make sure that you are using a common ground. I am powering my ATTiny by the core itself so it shares a ground.

Both the Spark Core and the ATTiny 85 are being powered from the same USB port via a USB battery pack, so I think that would be considered as a shared ground but I’m not 100% sure.

Maybe the 3v output from the Core is not enough for the 5v Trinket ATTiny 85 to run correctly? I’ll have to play around with it some more tomorrow.

I see that somebody else has figured out that the Watchdog timer built into the Spark Core has not been implemented yet and they have code that should activate it. Hopefully they get that worked out and working so we can get back to only needing the Spark Core.

I’m learning lots regardless.

Even with the same battery, I would try to at least jump the grounds. Just an idea.

The more I look at your picture the more I think you should share a ground.

First I would try unplugging usb on the CFODK, jumping the 3.3* to bat+ and jump Ground to BAT -.

If that doesnt work try jumping just one ground to the other with the USB powering it.

Then play with this part of the code and lower or raise to get your test LED on the CFODK to blink only when no pulse.

void setState(){ // here is the set state function, number varibles are just to identify change in state.
  sensorValue = analogRead(sensorPin); // check for spark pin
  if (sensorValue < 500)  // if analog value is less than 500, set to variable 0
{
  sensorState = 0; // variable 0
}
if (sensorValue > 500) // if analog state is more than 500, set to varible 1
{
  sensorState = 1; // varible 1
}

I would be curious to see how many times mine needs to reset using my CFOD Killer. Does anyone know how to make a simple Xively code to publish the last time of reset?

Thanks

You can easily see the reset pattern in the Xivley graph. Mine showed almost every 60 seconds eventually. Lets see how yours works out. Just setup a Xivley account, the free version, and get your feed number and key and enter it at the top of the code I’m pasting below. Its using @BDub 's updated code:

#define FEED_ID "12345" //note: fake id here.. 
#define XIVELY_API_KEY "123456789" //note: fake key here

TCPClient client;

int trigger = A7; // this is the pin talking to the attiny
int reading = 0; // this is analog pin we are taking sensor readings at
int ledD = D7; // this is our onboard LED Pin
unsigned long LastUpTime = 0;
uint32_t lastKick = 0; // last time we kicked the watch dog
bool s = false; // output state of the watch dog
char whichApp[64] = "READ TEMPERATURE with XIVELY";

// This routine runs only once upon reset
void setup()
{
   //Register our Spark function here
  Spark.variable("whichapp", &whichApp, STRING);
  Spark.variable("reading", &reading, INT);
  Spark.function("degres", tempCalculation);
  Spark.function("volt", analogReading);
  pinMode(A0, INPUT);
  pinMode(ledD, OUTPUT);
  ledStatus(2,100); //Blink
  lastKick = millis(); // We just powered up
  pinMode(trigger, OUTPUT); // set signal pin to output
  lastKick = millis(); // We just powered up
 
}

void loop()
{
kickTheDog(); // kick the watchdog
    
  reading = analogRead(A0);
  int temp_calc = (reading*3.3/4095)*100 - 50;

   if (millis()-LastUpTime>2000)
   {
      xivelyTemp(temp_calc);
      LastUpTime = millis();
   }
}

void xivelyTemp(int temperature) {

   //Serial.println("Connecting to server...");
    if (client.connect("api.xively.com", 8081)) 
    {

        // Connection succesful, update datastreams
        client.print("{");
        client.print("  \"method\" : \"put\",");
        client.print(" \"resource\" : \"/feeds/");
        client.print(FEED_ID);
        client.print("\",");
        client.print("  \"params\" : {},");
        client.print("  \"headers\" : {\"X-ApiKey\":\"");
        client.print(XIVELY_API_KEY);
        client.print("\"},");
        client.print("  \"body\" :");
        client.print("    {");
        client.print("      \"version\" : \"1.0.0\",");
        client.print("      \"datastreams\" : [");
        client.print("        {");
        client.print("          \"id\" : \"Sensor_Data_Watchdog_ON\",");
        client.print("          \"current_value\" : \"");
        client.print(temperature);
        client.print("\"");
        client.print("        }");
        client.print("      ]");
        client.print("    },");
        client.print("  \"token\" : \"0x123abc\"");
        client.print("}");
        client.println();

        ledStatus(2, 500);        
    } 
    else 
    {
        // Connection failed
        //Serial.println("connection failed");
        ledStatus(4, 500);
    }


    if (client.available()) 
    {
        // Read response
        //char c = client.read();
        //Serial.print(c);
    }

    if (!client.connected()) 
    {
        //Serial.println();
        //Serial.println("disconnecting.");
        client.stop();
    }

    client.flush();
    client.stop();
}

void kickTheDog() { // kick the dog every 5 seconds
  if( (millis()-lastKick) > 5000 ) {
    lastKick = millis();
    s = !s; // toggle the outputs
    digitalWrite(trigger,s); // watchdog signal
  }
}

    
void ledStatus(int x, int t)
{
    for (int j = 0; j <= x-1; j++)
    {
        digitalWrite(ledD, HIGH);
        delay(t);
        digitalWrite(ledD, LOW);
        delay(t); 
   }
}

int tempCalculation(String command) {
    int tempCalc = (reading*3.3/4095)*100 - 50;
    return tempCalc;
}

int analogReading(String command) {
    return reading;
} 

FYI My core is now running more than 24 hours straight! :smile:

@RWB, how is yours going with the modification?

Also I am trying the Xively now, not sure if I did it right, do I need to setup channels? Also the API Key, all I could find was an API link, so I used that. :confused:

I can’t get it to work right with the ATTiny 85 / Trinket or the Arduino Micro controller. It just cycles the board on and off every 60 seconds. It works sometimes but most of the time it does not so I’m not sure whats going on. I tried lots of stuff and don’t really have more time to day to devote to it.

Very Frustrating to say the least LOL

I see they are making progress with the built in ARM watch dog timer, but we will have to see how that goes this week.

If your Trinket is a 5V version, you might want to set your sensorValue threshold lower… say < 338 decimal, declare it LOW. A 3.3V signal should be at least double that, 680 … so 500 might be a little close ? (shrug). Do you have the grounds connected together and not through the USB cable… very important. Since you are using analog input on the trinket… there’s not reason not to add a small 0.01uF cap from analog #3 to gnd. The Spark core output should handle driving that high/low no problem… if you are worried about peak currents, put a 220 ohm resistor in between the spark digital output and the trinket analog input.

Just a quick note, I just got this implemented on a cheap 14-pin DIP MSP430(G2452). It monitors a pin and if it’s not toggled high/low at least every 20 seconds it’ll toggle the Core’s reset pin. These chips run at 3V3 and require no extra components. Simply put it in the breadboard with your Core, give it 3.3V, GND and hook it to the Core’s Reset pin and one I/O line and you’re good to go.

I’m willing to program and mail one to anyone who needs it for $2 + postage ($0.50 in the lower 48 states).

The shipping version will let you program the timeout via serial and if I make any firmware changes in the future the chip can be flashed over the air by hooking it up to the Core via I2C.

Just send me a PM if you’re interested!

3 Likes