Electron lost all communication - flashing dark blue

Eventually I was able to reset the Electron, it is working with the webIDE and I was able to flash the tutorial “flash an LED” successfully.

I hesitate to plug it back into the “Asset Tracker” shield or flash the project I was working on before I know what the root cause is.

I was hoping someone would be kind enough to review the attached wiring diagram and the code below and help me figure out what I did wrong?

When I finished Sunday night everything was working great, Last night I made some (I thought minor) changes to my code and flashed it to the device. After that I could no longer communicate with the Electron and had the dark blue flashing LED. I hadn’t made any wiring changes, but am not sure the wiring isn’t the problem.

//=================================================================================================  REQUIRED LIBRARIES
#include <AssetTracker.h>
#include <WS2812FX.h>

SYSTEM_THREAD(ENABLED);     // Allows the Electron to powerup and run with no connection available
SYSTEM_MODE(AUTOMATIC);     // Allows the Electron to search for and make a connection

//=================================================================================================  INITIALIZATION PARAMETERS
#define PIXEL_PIN D3
#define PIXEL_COUNT 24
#define PIXEL_TYPE WS2812B
WS2812FX ws2812fx = WS2812FX(PIXEL_COUNT, PIXEL_PIN, PIXEL_TYPE);

#define LED_TIMER_MS 10000
int MAINT_PIN = D1;
int COVER_PIN = D2;
int BEEP_PIN = B3;

Servo myservo;                      // create servo object to control a servo a maximum of eight servo objects can be created
FuelGauge fuel;                     // A FuelGauge named 'fuel' for checking on the battery state
AssetTracker t = AssetTracker();    // Creating an AssetTracker named 't' for us to reference

//=================================================================================================  FUNCTIONAL PARAMETERS AND VARIABLES
//============================= TIMER TRACKING
int lastStatusUpdate = 0;
int lastMaintUpdate = 0;
int lastHazardUpdate = 0;
int activationTime = 0;
int servoHoldRetract = 0;

int StatusMsgFreq = 5 * 24 * 60 * 60 * 1000;      //  days*hr*min*sec*ms   -- sends a battery status update every (x) days
int MaintDWELL = 1 * 60 * 1000;            //  min*sec*ms      -- allows (x) minutes before going into hazard mode
int MaintMsgFreq = 5 * 60 * 1000;            //  min*sec*ms      -- sends a maintenance message every (x) minutes
int HazardMsgFreq = 1 * 60 * 1000;            //  min*sec*ms      -- sends a hazard message every (x) minutes

//============================= STATE TRACKING
bool beepOn = false;
bool enabled = false;
bool isDeployed = false;
bool maintState = false;
bool hazardState = false;
bool ledOn = false;

//============================= GENERAL VARIABLES
uint16_t LED_brightness = 1;
unsigned long last_change = 0;
unsigned long now = 0;
unsigned long startupTime = 0;
int beepdelay = 0;
int pos = 0;                                // variable to store the servo position

//=================================================================================================  INITIALIZES THE DEVICE WHEN POWER COMES ON
void setup() {
	startupTime = millis();
	ws2812fx.init();
	ws2812fx.setBrightness(LED_brightness);
	ws2812fx.setSpeed(1000);
	ws2812fx.setColor(0x007BFF);
	ws2812fx.setMode(FX_MODE_CIRCUS_COMBUSTUS);
	// ws2812fx.start();


	Particle.function("batt", batteryStatus);
	// Particle.function("null", setNull);
	Particle.function("setSpeed", setSpeed);
	Particle.function("setBright", setBrightness);
	Particle.function("reset", resetAll);
	Particle.function("enable", enableDisable);


	myservo.attach(D0);   // attach the servo on the D0 pin to the servo object
	myservo.write(5);    // test the servo by moving it to 25°
	pinMode(BEEP_PIN, OUTPUT);
	pinMode(COVER_PIN, INPUT_PULLDOWN);
	pinMode(MAINT_PIN, INPUT_PULLDOWN);
	beepOn = false;
}

//=================================================================================================  MAIN LOOP; RUNS CONTINUSOUSLY WHEN POWER IS ON
void loop()
{

	if (digitalRead(COVER_PIN) == HIGH && enabled)
	{
		if (activationTime == 0) { activationTime = millis(); }
		ws2812fx.setBrightness(LED_brightness);
		maintenanceMode();
	}
	else
	{
		myservo.write(5);
		ws2812fx.stop();
		ledOn = false;
		t.gpsOff();
		isDeployed = false;
		maintState = false;
		hazardState = false;
		statusMode();
		lastStatusUpdate = 0;
		lastMaintUpdate = 0;
		lastHazardUpdate = 0;
		activationTime = 0;
		servoHoldRetract = 0;
	}
}

//=================================================================================================  ACTIVATION MODE HANDLING
// The cover has been released
// Send a one-time activation message
// Allow time for maintenance overide
// If overide is not activated switch to hazard mode
void maintenanceMode()
{
	if (digitalRead(MAINT_PIN) == HIGH) // maintenance overide enabled
	{
		ws2812fx.stop();
		isDeployed = false;
		myservo.write(5);
		if (millis() - lastMaintUpdate > MaintMsgFreq)
		{
			sendMaintMessage();
			lastMaintUpdate = millis();
		}
		piezo(3000, 30);
	}
	else
	{
		if (lastHazardUpdate == 0)
		{
			lastHazardUpdate = millis();
		}
		if (millis() - lastHazardUpdate > MaintDWELL)
		{
			hazardMode();
		}
	}
}

void statusMode()       // The cover is depressed, send regular status updates at the preset frequency
{
	if (millis() - lastStatusUpdate > StatusMsgFreq)
	{
		lastStatusUpdate = millis();
	}
}

void hazardMode()       // The cover has been released and the maintenance overide has not been enabled  
{
	ws2812fx.service();

	if (!isDeployed)
	{
		myservo.write(25);
		isDeployed = true;
		servoHoldRetract = millis();
		t.gpsOn();
		t.updateGPS();
		if (!ledOn)
		{
			ws2812fx.start();
			ledOn = true;
		}
	}
	else
	{
		if (isDeployed && millis() - servoHoldRetract > 15000)
		{
			myservo.write(5);
		}
		piezo(700, 150);
	}
	if (millis() - lastHazardUpdate > HazardMsgFreq)
	{
		// GPS requires a "fix" on the satellites to give good data, so we should only publish data if there's a fix
		if (t.gpsFix())
		{
			sendHazardMessage();
			lastHazardUpdate = millis();// Remember when we published
			t.gpsOff(); // when publishing is complete turn the GPS off to save power
		}
	}
}

//=================================================================================================  COMMUNICATIONS HANDLING
void sendStatusMessage()
{
	Particle.publish("STATUS", "v:" + String::format("%.2f", fuel.getVCell()) + ",c:" + String::format("%.2f", fuel.getSoC()), 60, PRIVATE);
}
void sendMaintMessage()
{
	Particle.publish("MAINT", "v:" + String::format("%.2f", fuel.getVCell()) + ",c:" + String::format("%.2f", fuel.getSoC()), 60, PRIVATE);
}
void sendHazardMessage()
{
	Particle.publish("HAZARD", "Lat-Long: " + t.readLatLon() + "   Batt v:" + String::format("%.2f", fuel.getVCell()) + "   Batt c:" + String::format("%.2f", fuel.getSoC()), 60, PRIVATE);
}

void piezo(int gap, int width)
{
	if (beepdelay>gap)
	{
		digitalWrite(BEEP_PIN, HIGH);
		delay(width);
		beepdelay = 0;
	}
	else
	{
		digitalWrite(BEEP_PIN, LOW);
		beepdelay++;
	}
}

//=================================================================================================  REMOTE COMMAND HANDLING
// Lets you remotely check the battery status by calling the function "batt" 
// Triggers a publish with the info (so subscribe or watch the dashboard)
// and also returns a '1' if there's >10% battery left and a '0' if below
int batteryStatus(String command)
{
	// Publish the battery voltage and percentage of battery remaining
	// if you want to be really efficient, just report one of these
	// the String::format("%f.2") part gives us a string to publish,
	// but with only 2 decimal points to save space
	Particle.publish("B",
		"v:" + String::format("%.2f", fuel.getVCell()) +
		",c:" + String::format("%.2f", fuel.getSoC()),
		60, PRIVATE
	);
	// if there's more than 10% of the battery left, then return 1
	if (fuel.getSoC()>10) { return 1; }
	// if you're running out of battery, return 0
	else { return 0; }
}

int enableDisable(String command)
{
	uint16_t cmd = atoi(command);
	if (cmd < 0 || cmd > 1)
	{
		return -1;
	}
	enabled = cmd;
	return 0;
}

int resetAll(String command)
{
	myservo.write(5);
	delay(100);
	ws2812fx.stop();
	ledOn = false;
	t.gpsOff();
	isDeployed = false;
	activationTime = 0;
	lastMaintUpdate = 0;
	lastHazardUpdate = 0;
	maintState = false;
	hazardState = false;
	statusMode();
	startupTime = millis();
}

int setSpeed(String speed_str)              // Override - Changes the rotation speed of the LED pattern; resets on power down/up
{
	uint16_t speed = atoi(speed_str);
	if (speed < 0 || speed > 65535) return -1;
	ws2812fx.setSpeed(speed);
	return 0;
}

int setBrightness(String brightness_str)    // To save battery power during debugging you can remotely set this value to 5 or less (default is 255); resets on power down/up
{
	LED_brightness = atoi(brightness_str);
	if (LED_brightness < 0 || LED_brightness > 255) return -1;
	ws2812fx.setBrightness(LED_brightness);
	return 0;
}

A loose SIM card can also cause blinking dark blue.

Blinking dark blue, listening mode, typically occurs if there is a problem with the SIM card or a loose connection to the Electron.

Unplug the USB power and battery from the Electron. If it’s installed in a breadboard, carefully remove it. Be sure to lift it from both sides; if you pull up from one side only you can bend the pins on the other side.

Flip the Electron over and remove the SIM card. Gently push down on the metal band to make sure it’s tight. In rare cases you may want to use a pin to lift up the tiny metal prongs on the Electron, but this is not typically necessary.

Put the SIM card back in. The metal contacts on the card face the Electron, and the cut corner goes on the inside. Make sure it’s pushed all the way in.

Putting a layer or two of clear tape on the non-contact side of the SIM card can also make it thicker and assure a snug fit.

Thanks rikkas7,

Yes as I said I tried all of that, none of it worked.

There was no evidence that the SIM was the problem, it slid in firmly, the spring pins were all up where they belonged, and there were scratches on the SIM contact pads where the springs had rubbed them. Also, the board had worked for 2 weeks with no problem, up to when I put it up Sunday night. I was able to get it restored eventually by restoring the default firmware with the CLR and usb cable.

I was embarrassed to explain before I had a second Asset Tracker that was still in the wrapper, so this morning I registered it and it worked fine, as soon as I connected it to the shield and flashed my code, the exact same thing happened to it. For me that points to mistakes in wiring and/or code.

So I’m sure you can understand why I really need someone to review my code and wiring diagram before I make another attempt.

I’m hoping you can take some time to check my code and wiring diagram. Both are relatively simple, I’m just new to this kind of device and programming. I’m sure I’ve made a simple dumb mistake and am too close to it to see where I messed up.

As always thank you for responding,

UPDATE

I’ve ruled out the wiring by pre-loading a simple demo to the Electron and re-installing the shield. The demo worked fine and I flashed a couple other “Hello World” type projects via the webIDE.

Everything is working properly even with both the Electron LiPo and the auxiliary battery pack connected.

I then started trying to piece together my code a little at a time. So far I’ve got the LED ring displaying the correct sequence.

I have my suspicitions on where the problem is, and am saving that bit of code till last.

BTW… I’ve been able to resurrect the second board
But the “Reset factory defaults” documentation is either incorrect, not clear, or incomplete, I will identify the changes that need to be made and post a new thread when I have time.

I’ve got everything up and running as it was, the only suspect piece of code were these statements which are still commented out because that’s what I suspected was causing the problem:

//SYSTEM_THREAD(ENABLED);     // Allows the Electron to powerup and run with no connection available
//SYSTEM_MODE(AUTOMATIC);     // Allows the Electron to search for and make a connection

The reason for the 2 lines is I need to be sure the system will start-up and run even though there is no connectivity.

As I was suspecting this was the issue, it occured to me that maybe the order of the command matters, so when I do un-comment them, I’m thinking I should flip the order, AUTOMATIC mode first then ENABLE the system thread.

Does anyone have any experience or insight on this?

Thanks
Don