Seemingly simple code seems to brick Photons (blinking red)

So, I have now apparently bricked THREE Photons. I know, I should have stopped after one! Anyway, I’ve written what I think is fairly straightforward code (that Verifies fine) and flashed it to three different Photons. Each one seems to flash, then crash. (Blinking red, SOS, then one blink indicating HARD FAULT.)

Two questions:

  1. What’s wrong with this code?
  2. How do I recover these Photons?
/***************************************************************************************************
 * 
 * TINKER VARIABLES
 * 
 **************************************************************************************************/
int tinkerDigitalRead(String pin);
int tinkerDigitalWrite(String command);
int tinkerAnalogRead(String pin);
int tinkerAnalogWrite(String command);

/***************************************************************************************************
 * 
 * MY VARIABLES
 * 
 **************************************************************************************************/

//int button1 = D0; 

// For power detection
int pinGarageButton = D0;
int pinGotPower = D1;
int pinLed = D2;
int pinGarageDoor = D3;
int pinTempSensor = A7;
int gotPower = 0;
int lightOn = 0;
int longPumpRun = 0;
unsigned long ms;
unsigned long msPowerDuration;
unsigned long msDuration;

// For temp reading
int reading = 0;
int garageClosed = 0;
float voltage = 0.0;
float tempC = 0.0;
float tempF = 0.0;
char strC[10];
char strF[10];

int pressGarageButton(String command);


/***************************************************************************************************
 * 
 * SETUP
 * 
 **************************************************************************************************/
void setup()
{

    // Set pin Modes for all pins
    //pinMode(button1, OUTPUT);
    pinMode( pinGotPower, INPUT_PULLDOWN );
    pinMode( pinGarageButton, OUTPUT );
    pinMode( pinLed, OUTPUT );
    pinMode( pinGarageDoor, INPUT_PULLDOWN );
    pinMode(pinTempSensor, INPUT);

    // Register Tinker functions
	Particle.function("digitalread", tinkerDigitalRead);
	Particle.function("digitalwrite", tinkerDigitalWrite);
	Particle.function("analogread", tinkerAnalogRead);
	Particle.function("analogwrite", tinkerAnalogWrite);

    // Register my functions    
    Particle.function("toggleGarage",pressGarageButton);
    Particle.function("garageButton", pressGarageButton);

    // Request path and body can be set at runtime or at setup.
    //request.hostname = "herstein.dyndns.org";
    //request.port = 80;
    //request.path = "/home/index.php?c=event&t=gotpower";
    
    // Register my variables    
    Particle.variable("reading", &reading, INT);
    Particle.variable("tempC", strC, STRING);
    Particle.variable("tempF", strF, STRING);
    Particle.variable("garageClosed", &garageClosed, INT);
}


// GARAGE CODE HERE
/*
int pressGarageButton(String command)
{
  digitalWrite(button1, HIGH);
  delay(250);
  digitalWrite(button1, LOW);
  return 0;
}
*/

/**
 * To get temp: https://api.spark.io/v1/devices/53ff6e065067544859341287/tempF?access_token=41e5a3fa026212878490cb128db08ad70f6dd36f
 * To press garage button: https://api.spark.io/v1/devices/53ff6e065067544859341287/garagebutton?access_token=41e5a3fa026212878490cb128db08ad70f6dd36f
 * 
 */
 

//HttpClient http;
//
// Headers currently need to be set at init, useful for API keys etc.
//http_header_t headers[] = {
//    //  { "Content-Type", "application/json" },
//    //  { "Accept" , "application/json" },
//    { "Accept" , "*/*"},
//    { NULL, NULL } // NOTE: Always terminate headers will NULL
//};
//
//http_request_t request;
//http_response_t response;



/***************************************************************************************************
 * 
 * LOOP
 * 
 **************************************************************************************************/
void loop()
{
    if(digitalRead( pinGotPower ))
    {
        if(!gotPower) //power was off
        {
            ms = millis(); // record the current time            
            gotPower = 1; //set gotPower flag on
            digitalWrite(pinLed, HIGH); // turn on the LED

            //JSH: Need to replace next two lines with PUBLISH
            //request.path = "/home/index.php?c=event&t=sparkpoweron";
            //http.get(request, response, headers);
        }
        else
        {
            // power was already on
            msDuration = millis() - ms;
            if(!longPumpRun && msDuration>60000)
            {
               longPumpRun = 1;
//               Spark.publish("Pump_Running", String(msPowerDuration/1000)); 
               Particle.publish("Pump_Running"); 
            }
        }
    }
    else
    {
        if(gotPower) //power was on
        {
            gotPower = 0;
            digitalWrite(pinLed, LOW);
            
            //determine how long power was on
            msPowerDuration = millis() - ms;
            //String strDuration = String(msPowerDuration);
            
            // log the power on
            // The library also supports sending a body with your request:
            //request.body = "{\"duration\":\".strDuration."\"}";
            // Get request
            //JSH: Need to replace next two lines with PUBLISH
            //request.path = "/home/index.php?c=event&t=sparkpoweroff&d="+String(msPowerDuration);
            //http.get(request, response, headers);
            
//            Spark.publish("Pump_Ran", String(msPowerDuration/1000));
            //Particle.publish("Pump_Ran",String(msPowerDuration));
            Particle.publish("Pump_Ran", String(msPowerDuration), PRIVATE);
            longPumpRun = 0;
        }
    }

    // Keep reading the temperature so when we make an API
    // call to read its value, we have the latest one
    reading = analogRead(pinTempSensor);
    voltage = (reading * 3.3) / 4095;
    tempC   = (voltage - 0.5) * 100;
    tempF   = (tempC * 9/5) + 32;
    sprintf(strC,"%.2f",tempC);
    sprintf(strF,"%.2f",tempF);

    garageClosed = digitalRead(pinGarageDoor);
    
    delay(1000);               // Wait for 1 second
}


/***************************************************************************************************
 * 
 * Simulate Garage Opener button press
 * 
 **************************************************************************************************/
int pressGarageButton(String command)
{
    digitalWrite(pinGarageButton, HIGH);
    delay(100);               // Wait for 0.1 second
    digitalWrite(pinGarageButton, LOW);

/*
    if(lightOn)
    {
        digitalWrite(pinLed, LOW); // turn off the LED
        lightOn = 0;
    }
    else
    {
        digitalWrite(pinLed, HIGH); // turn on the LED
        lightOn = 1;
    }
*/

    return 1;
}


/***************************************************************************************************
 * 
 * TINKER CODE BELOW -- DON'T TOUCH
 * 
 **************************************************************************************************/

int tinkerDigitalRead(String pin) {
	int pinNumber = pin.charAt(1) - '0';
	if (pinNumber< 0 || pinNumber >7) return -1;
	if(pin.startsWith("D")) {
		pinMode(pinNumber, INPUT_PULLDOWN);
		return digitalRead(pinNumber);}
	else if (pin.startsWith("A")){
		pinMode(pinNumber+10, INPUT_PULLDOWN);
		return digitalRead(pinNumber+10);}
	return -2;}

int tinkerDigitalWrite(String command){
	bool value = 0;
	int pinNumber = command.charAt(1) - '0';
	if (pinNumber< 0 || pinNumber >7) return -1;
	if(command.substring(3,7) == "HIGH") value = 1;
	else if(command.substring(3,6) == "LOW") value = 0;
	else return -2;
	if(command.startsWith("D")){
		pinMode(pinNumber, OUTPUT);
		digitalWrite(pinNumber, value);
		return 1;}
	else if(command.startsWith("A")){
		pinMode(pinNumber+10, OUTPUT);
		digitalWrite(pinNumber+10, value);
		return 1;}
	else return -3;}

int tinkerAnalogRead(String pin){
	int pinNumber = pin.charAt(1) - '0';
	if (pinNumber< 0 || pinNumber >7) return -1;
	if(pin.startsWith("D")){
		pinMode(pinNumber, INPUT);
		return analogRead(pinNumber);}
	else if (pin.startsWith("A")){
		pinMode(pinNumber+10, INPUT);
		return analogRead(pinNumber+10);}
	return -2;}

int tinkerAnalogWrite(String command){
	int pinNumber = command.charAt(1) - '0';
	if (pinNumber< 0 || pinNumber >7) return -1;
	String value = command.substring(3);
	if(command.startsWith("D")){
		pinMode(pinNumber, OUTPUT);
		analogWrite(pinNumber, value.toInt());
		return 1;}
	else if(command.startsWith("A")){
		pinMode(pinNumber+10, OUTPUT);
		analogWrite(pinNumber+10, value.toInt());
		return 1;}
	else return -2;
}

Are you able to place the Photon in Safe mode?

No. When I do the button sequence it just goes back to blinking red.

I can get it into dfu mode (blinking yellow), but I’m having a separate issue getting dfu-util running.

1 Like

Can you post a video of you doing the Safe Mode button action? (Just for us to be sure ;-))
Since it’s not your code (I have tested that ;-)), it might be your circuitry.
Where have you got your pinGotPower and pinGarageDoor tied to? What voltage does the switch close to?

Remove the Photons from any external circuitry - only USB power and try again.

Some side notes:
When intending to do an analogRead() on pinTempSensor, don’t set the pinMode()!
I’d go for tempF = (tempC * 9.0/5.0) + 32; instead of tempF = (tempC * 9/5) + 32; to make sure you get a float division, in case the division is performed before the multiplication.

1 Like

I think I have same issue and not able to place the Photon in Safe Mode.
Let me post a video of Safe Mode button action.

It would be great if you could tell me how to recover my Photon.

If you can get it into DFU mode, give “particle update” and “particle flash --usb tinker” a try in the CLI.

Also, that’s a Sparkfun Redboard containing a P1 module, it’s not a Photon :wink:

2 Likes

Thank you very much, as you say it’s not a Photon but P1 module :flushed:

I’m struggling but I cannot get it into DFU mode. Device begins to blink yellow, however, it’s regarded as not “DFU mode”, but “safe mode”.

[
{
“id”: “[my device id]”,
“name”: “[my device name]”,
“last_app”: null,
“last_ip_address”: “[my IP address]”,
“last_heard”: “2016-10-06T06:55:38.041Z”,
“product_id”: 8,
“connected”: false,
“platform_id”: 8,
“cellular”: false,
“status”: “safe-mode”
}
]

…$ particle flash --usb tinker
Error loading command /usr/local/lib/node_modules/particle-cli/commands/SerialCommand.js Error: Module version mismatch. Expected 46, got 14.

!!! I was unable to detect any devices in DFU mode...

> Your device will blink yellow when in DFU mode.
> If your device is not blinking yellow, please:

1) Press and hold both the RESET/RST and MODE/SETUP buttons simultaneously.

2) Release only the RESET/RST button while continuing to hold the MODE/SETUP button.

3) Release the MODE/SETUP button once the device begins to blink yellow.

Error writing firmware...No DFU device found

…$ particle update
Error loading command /usr/local/lib/node_modules/particle-cli/commands/SerialCommand.js Error: Module version mismatch. Expected 46, got 14.

!!! I was unable to detect any devices in DFU mode...

> Your device will blink yellow when in DFU mode.
> If your device is not blinking yellow, please:

1) Press and hold both the RESET/RST and MODE/SETUP buttons simultaneously.

2) Release only the RESET/RST button while continuing to hold the MODE/SETUP button.

3) Release the MODE/SETUP button once the device begins to blink yellow.

…$dfu-util -l
dfu-util 0.9

Copyright 2005-2009 Weston Schmidt, Harald Welte and OpenMoko Inc.
Copyright 2010-2016 Tormod Volden and Stefan Schmidt
This program is Free Software and has ABSOLUTELY NO WARRANTY
Please report bugs to http://sourceforge.net/p/dfu-util/tickets/

Cannot open DFU device 2b04:d008