Code runs, Core flashes blue then back to breathing

Hi everyone, first timer here, been a programmer for 20+ years and always wanted to use a microcontroller but wasn’t sure where to start. Saw the spark and jumped right in. Love it, when I get it working :slight_smile: I’m hooked!

I keep having this issue and thought maybe my code was blocking. I’ve put delays of 2000 -5000 in but still get the same results and then it make it impossible to talk to the core via the APIs. I have striped everything off but the one DHT22 and get the same results. Thought it might be related to the other issues that were going on but the status page says everything is good.

The test I’m using right now is an example from the library for the DHT22 called idDHT22, note I have used the PietteTech_DHT library also. The program runs, I see output but then it will randomly flash blue then back to breathing.

Any help, pointers are appreciated.
Thanks,
John

I had good luck with the ADAFRUIT_DHT library on the web IDE.

@BulldogLowell, thanks I’ll give that a try and see if I have better luck with that lib.

Do these problems also occur with the PietteTech library? As far as I’m aware, that’s currently the most stable one for the DHT22. If you could post your code, we could take a look at it, so we can exclude any other potential issues.

Here is my first code set. My c coding skills are a bit rusty…I wasn’t sure if something else I added was causing the problems so I loaded up the example code for idDHT22 and PietteTech_DHT, added some spark variable and ran the code. Both would start working then I would see the blue flashing light then back to breathing. Same thing this code was doing. I have IFTTT set to watch for the publish event in startup to email me when this event occurs, well my inbox is flooded with emails lol

// This #include statement was automatically added by the Spark IDE.
#include "elapsedMillis/elapsedMillis.h"
//#include "clickButton/clickButton.h"
#include "Adafruit_SSD1306/Adafruit_SSD1306.h"
#include "PietteTech_DHT/PietteTech_DHT.h"
//#include "math.h"

// system defines
#define DHTTYPE  DHT22              // Sensor type DHT11/21/22/AM2301/AM2302
#define DHTPIN   D3         	    // Digital pin for communications
#define DHT_SAMPLE_INTERVAL   3000  // Sample every 3 seconds
#define RELAY1   A6
#define TMPPIN   A7
#define OLED_RESET D2
#define PUSHBUTTONPIN D6
#define _VERSION 0.1

float temperatureC, temperatureF = 0.0;
float relayTempC, relayTempF = 0.0;
float holdTempC = 0;
float awayTempC = 22; // save to EEPROM
float lowC, highC = 0;
float lowF, highF = 0;
float humidity = 0;

Adafruit_SSD1306 display(OLED_RESET);

int pushButtonStatus = 0; 
int screenMode = 1;
//ClickButton button1(PUSHBUTTONPIN, LOW, CLICKBTN_PULLUP);

elapsedMillis tempReadTimer;
elapsedMillis displayTimer;

void dht_wrapper(); // must be declared before the lib initialization

// Lib instantiate
PietteTech_DHT DHT(DHTPIN, DHTTYPE, dht_wrapper);

// globals
unsigned int DHTnextSampleTime;	
bool bDHTstarted;		    

bool isHeatOn = false;
int heatState = -1;
bool displayModeCelsius = true;

void setup()
{
    Serial.begin(9600);
    //while (!Serial.available()) {
    //    Serial.println("Press any key to start.");
    //    delay (1000);
    //}
    
    // Register a Spark variable here
    Spark.variable("CurrentTempC", &temperatureC, DOUBLE);
    Spark.variable("CurrentTempF", &temperatureF, DOUBLE);
    Spark.variable("Humidity", &humidity, DOUBLE);
    Spark.variable("HoldTempC", &holdTempC, INT);
    Spark.variable("IsHeaterOn", &isHeatOn, BOOLEAN);
    
    // max name len 12
    Spark.function("SetHeatMode", setHeatMode);
    Spark.function("SetHoldTemp", setHoldTemp);
    Spark.function("C_F_Display", tempDisplayMode);
    
    DHTnextSampleTime = 0;  // Start the first sample immediately
    
    pinMode(PUSHBUTTONPIN, INPUT_PULLUP);
    pinMode(RELAY1, OUTPUT);
    pinMode(D7, OUTPUT);
    digitalWrite(RELAY1, LOW);
    digitalWrite(D7, LOW);
    
    holdTempC = EEPROM.read(1);
    if(holdTempC == 255) holdTempC = 0;
    
    // Setup button timers (all in milliseconds / ms)
    // (These are default if not set, but changeable for convenience)
    //button1.debounceTime   = 20;   // Debounce timer in ms
    //button1.multiclickTime = 250;  // Time limit for multi clicks
    //button1.longClickTime  = 1000; // time until "held-down clicks" register
    
    display.begin(SSD1306_SWITCHCAPVCC, 0x3C);
    display.display(); // show splashscreen
    delay(2000);
    display.clearDisplay();   // clears the screen and buffer
    
    //21 chars with txt size 1
    display.setTextSize(1);
    display.setTextColor(WHITE);
    display.setCursor(0,0);
    display.print("Loading...");
    display.setCursor(0,7);
    display.print("LIB version: ");
    display.println(_VERSION);
    display.setTextSize(2);
    display.println("Initializing");
    display.println("System");
    display.display();

    ReadDhtTemp1();

    delay(2000);
    display.clearDisplay();
    
    Spark.publish("online", currentTimeJsonString(), 60, PRIVATE);
}


// This wrapper is in charge of calling
// mus be defined like this for the lib work
void dht_wrapper() {
    DHT.isrCallback();
}

void loop()
{
    
/*    button1.Update();
    //pushButtonStatus = digitalRead(PUSHBUTTONPIN);
    if (button1.clicks != 0) pushButtonStatus = button1.clicks;
    if (button1.clicks != 0)
    {
        if (button1.clicks > 0)
        {
            screenMode += button1.clicks;
        }
        if (screenMode == 5)
            screenMode = 1;
    }
*/    
    
    // Check if we need to start the next sample
    if (tempReadTimer > DHTnextSampleTime) 
    {
        Serial.println("-- Start Temp Read --");
        ReadDhtTemp1();
        //ReadRelayTemp();
        //printTempReadings();
        tempReadTimer = 0;
        if(DHTnextSampleTime == 0) DHTnextSampleTime = DHT_SAMPLE_INTERVAL;
        
        UpdateDisplay();
        Serial.println("-- End Temp Read --");
    }

    // Add ability to override for a set time?
    if((int)temperatureC < holdTempC & heatState == -1 & !isHeatOn)
    {
        heatState = 1; //On
    }
    
    if((int)temperatureC >= holdTempC & heatState == -1 & isHeatOn)
    {
        heatState = 0; //Off
    }
    
    switch (heatState)
    {
        case 0: // Off
            if(isHeatOn)
            {
                Serial.println("-- Start Turn Heat Off --");
                isHeatOn = false;
                digitalWrite(RELAY1, LOW);
                digitalWrite(D7, LOW);
                
                //Spark.publish(String eventName, String data, int ttl, PRIVATE)
                Spark.publish("heater-off-txt", "Current Temp: xx, Low Temp: xx, High Temp: xx", 60, PRIVATE);
                Spark.publish("heater-off-json", currentTimeJsonString(), 60, PRIVATE);
                UpdateDisplay();
                Serial.println("-- End Turn Heat Off --");
            }
            heatState = -1; // processed
            break;
            
        case 1: // On
            if(!isHeatOn)
            {
                Serial.println("-- Start Turn Heat On --");
                isHeatOn = true;
                digitalWrite(RELAY1, HIGH);
                digitalWrite(D7, HIGH);
                
                //Spark.publish(String eventName, String data, int ttl, PRIVATE)
                Spark.publish("heater-on-txt", "Current Temp: xx, Low Temp: xx, High Temp: xx", 60, PRIVATE);
                Spark.publish("heater-on-json", currentTimeJsonString(), 60, PRIVATE);
                UpdateDisplay();
                Serial.println("-- End Turn Heat On --");
            }
            heatState = -1; // processed            
            break;
        
        case 2: // Away
            Serial.println("-- Start Set Heat to Away --");
            if(isHeatOn)
            {
                isHeatOn = false;
                digitalWrite(RELAY1, LOW);
                digitalWrite(D7, LOW);
            }
            heatState = -1; // processed
            Serial.println("-- End Set Heat to Away --");
            break;
    }
    
    delay(2000);
}

void ReadDhtTemp1()
{
    Serial.println("-- ReadDhtTemp1 --");
	if (!bDHTstarted) {		// start the sample
	    Serial.println("-- start the sample --");
	    DHT.acquire();
	    bDHTstarted = true;
	}

	if (!DHT.acquiring()) {		// has sample completed?
	    Serial.println("-- get DHT status --");
	    int result = DHT.getStatus();
        printDhtSensor1Results(result);
        UpdateTempVars();
	    bDHTstarted = false;  // reset the sample flag so we can take another
	}
}

void UpdateTempVars()
{
    //Serial.println("analogRead\ttemperatureC\ttemperatureF");
    //sprintf(message,"%d\t\t %.0f\t\t %.0f : %.0f", reading, temperatureC, temperatureF, (temperatureC*1.8+32));
    //Serial.println(message);  
    temperatureC = (double)DHT.getCelsius();
    temperatureF = (double)DHT.getFahrenheit();
    humidity = (double)DHT.getHumidity();
    
    if(temperatureC < lowC)
        lowC = temperatureC;
      
    if(temperatureC > highC)
        highC = temperatureC;
        
    if(temperatureF < lowF)
        lowF = temperatureF;
      
    if(temperatureF > highF)
        highF = temperatureF;
    
}

void printDhtSensor1Results(int result)
{
        Serial.println("---------------------------------------");
	    Serial.print("Read DHT sensor1: ");
	    switch (result) {
		case DHTLIB_OK:
		    Serial.println("OK");
		    break;
		case DHTLIB_ERROR_CHECKSUM:
		    Serial.println("Error\n\r\tChecksum error");
		    break;
		case DHTLIB_ERROR_ISR_TIMEOUT:
		    Serial.println("Error\n\r\tISR time out error");
		    break;
		case DHTLIB_ERROR_RESPONSE_TIMEOUT:
		    Serial.println("Error\n\r\tResponse time out error");
		    break;
		case DHTLIB_ERROR_DATA_TIMEOUT:
		    Serial.println("Error\n\r\tData time out error");
		    break;
		case DHTLIB_ERROR_ACQUIRING:
		    Serial.println("Error\n\r\tAcquiring");
		    break;
		case DHTLIB_ERROR_DELTA:
		    Serial.println("Error\n\r\tDelta time to small");
		    break;
		case DHTLIB_ERROR_NOTSTARTED:
		    Serial.println("Error\n\r\tNot started");
		    break;
		default:
		    Serial.println("Unknown error");
		    break;
	    }
	    
	    Serial.print("Screen: ");
        Serial.println(screenMode);
    
	    Serial.print("Humidity (%): ");
	    Serial.println(DHT.getHumidity(), 2);

	    Serial.print("Temperature (oC): ");
	    Serial.println(DHT.getCelsius(), 2);

	    Serial.print("Temperature (oF): ");
	    Serial.println(DHT.getFahrenheit(), 2);

	    Serial.print("Temperature (K): ");
	    Serial.println(DHT.getKelvin(), 2);

	    Serial.print("Dew Point (oC): ");
	    Serial.println(DHT.getDewPoint());

	    Serial.print("Dew Point Slow (oC): ");
	    Serial.println(DHT.getDewPointSlow());
	    Serial.println("---------------------------------------");
}

void UpdateDisplay()
{
    //Serial.println("-- Start Update Display --");
    display.setTextSize(2);
    display.setTextColor(WHITE);
    display.clearDisplay();

    display.setCursor(0,0);
    display.print("Heat: ");
    if(isHeatOn)
    {
        display.setTextColor(BLACK, WHITE); // 'inverted' text
        display.println("On");
    }
    else
    {
        display.setTextColor(BLACK, WHITE); // 'inverted' text
        display.println("Off");
    }
    display.setTextColor(WHITE);

    display.print("Set:");
    if(displayModeCelsius)
    {
        display.print(holdTempC, 1);
        display.println((char)222); // "c");
        display.setTextSize(4);
        display.print(temperatureC, 1); //DHT.getCelsius()
        //display.println("°");
        display.println("c");
    }
    else
    {
        display.print(CtoF(holdTempC), 1);
        display.println("f");
        display.setTextSize(4);
        display.print(temperatureF, 1); //DHT.getCelsius()
        //display.println("°");
        display.println("f");
    }
    
    display.display();
    //Serial.println("-- End Update Display --");
}

void ReadRelayTemp()
{
    //Serial.println("-- Start Reading Temp --");
    
    float tempSamples[8];
    
    //int reading = analogRead(TMPPIN);
    //Serial.print("Temp:");
    //float val = ( 5.0 * analogRead(TMPPIN) * 100.0) / 1024.0;
    //Serial.println( roundf(val*10.0f)/10.0f );
 
    for(int i = 0; i <= 7; i++){ // gets 8 samples of temperature
        tempSamples[i] = (((analogRead(TMPPIN) * 3.3)/4095) - 0.5) * 100;
        relayTempC += tempSamples[i];
        delay(200);
    }
    relayTempC = relayTempC / 8.0;
    //relayTempC = roundf(temperatureC*10.0f)/10.0f;

    // The returned value from the Core is going to be in the range from 0 to 4095
    // Calculate the voltage from the sensor reading
    //double voltage = (reading * 3.3) / 4095.0;

    // Calculate the temperature and update our static variable
    //tempC = (((analogvalue * 3.3)/4095) - 0.5) * 100;
    //relayTempC = (voltage - 0.5) * 100.0;
    relayTempF = CtoF(temperatureC); // (relayTempC * 9.0 / 5.0) + 32.0;
    
    //Serial.println("-- End Reading Temp --");
}

float CtoF(float c)
{
    return ((c * 9.0 / 5.0) + 32.0);
} 

int setHeatMode(String command)
{
    if(command.equalsIgnoreCase("on")) 
        return heatState = 1;
    else if(command.equalsIgnoreCase("off")) 
        return heatState = 0;
    else if(command.equalsIgnoreCase("away")) 
        return heatState = 2;
    else 
        return -1;
}

int setHoldTemp(String command)
{
    if(command.toFloat())
    {
        if(command.toFloat() != holdTempC)
        {
            holdTempC = command.toFloat();
            EEPROM.write(1, holdTempC);
        }
    }
    else
        return -1;
}


int tempDisplayMode(String command)
{
    displayModeCelsius = !displayModeCelsius;
    return 1;
}

String currentTimeJsonString()
{
    char publishString[64];
    // now is in milliseconds
    unsigned long now = millis();
    unsigned nowSec = now/1000UL;
    unsigned sec = nowSec%60;
    unsigned min = (nowSec%3600)/60;
    unsigned hours = (nowSec%86400)/3600;        
    sprintf(publishString,"{\"Hours\": %u, \"Minutes\": %u, \"Seconds\": %u}",hours,min,sec); 
    return publishString;
}

Update: I’m at a loss as to why my core keeps doing this. Very basic code is causing the same issue.

// Define the pins we're going to call pinMode on
int led = D0;  // You'll need to wire an LED to this one to see it blink.
int led2 = D7; // This one is the built-in tiny one to the right of the USB jack

float temperatureC, temperatureF, holdTempC = 0.0;
float lowC, highC = 0;
float lowF, highF = 0;
float humidity = 0;

// This routine runs only once upon reset
void setup() {
  // Initialize D0 + D7 pin as output
  // It's important you do this here, inside the setup() function rather than outside it or in the loop function.
  pinMode(led, OUTPUT);
  pinMode(led2, OUTPUT);
  
  
    Spark.variable("CurrentTempC", &temperatureC, DOUBLE);
    Spark.variable("CurrentTempF", &temperatureF, DOUBLE);
    Spark.variable("HoldTempC", &holdTempC, DOUBLE);
    Spark.variable("Humidity", &humidity, DOUBLE);
}

// This routine gets called repeatedly, like once every 5-15 milliseconds.
// Spark firmware interleaves background CPU activity associated with WiFi + Cloud activity with your code. 
// Make sure none of your code delays or blocks for too long (like more than 5 seconds), or weird things can happen.
void loop() {
  digitalWrite(led, HIGH);   // Turn ON the LED pins
  digitalWrite(led2, LOW);
  delay(1000);
  digitalWrite(led, LOW);
  digitalWrite(led2, HIGH);
  delay(1000);               // Wait for 1 second in off mode
}

Just a wild guess from own experiance.

Sometimes a I had this problem, when I had my Core attached to my tablets USB port which seems to provide less than perfect power.

Have you got the same behaviour with a wall wart?

@ScruffR, just tested with 3 different wall warts/cables and got the same results.

Question: Is there a limit on how often the API’s can be called to read the variables on a core? Could that be causing the problem? Grasping at straws here…

Thanks for the help.

AFAIK the blue flashing also indicates a loss of WiFi connection.

http://docs.spark.io/troubleshooting/#troubleshoot-by-color-flashing-blue

You could have radio interference or log distance to your rooter or shielding/interfering components near your antenna or if you’ve got a uFL Core your antenna might not be connected propperly or …

I didn’t suspect that as the issue because the core connects to WiFi when it starts and runs just fine, for a bit. Then it acts like the WiFi is lost, reconnects and all is fine, breathing light, runs for a bit, acts like the WiFi is lost, reconnects and all is fine, breathing light. Repeat, repeat… But once it has done this once or twice making calls to the APIs time out.

Current location had full bars on phone for WiFi, but to just be sure the WiFi wasn’t fading/dropping I moved the core closer and it still did the same thing. Interesting thing, if I comment out 2 of the Spark.variables I don’t have a problem. Maybe the internal conversion from float to double is causing an issue? Maybe I have a defective core?

// Define the pins we're going to call pinMode on
int led = D0;  // You'll need to wire an LED to this one to see it blink.
int led2 = D7; // This one is the built-in tiny one to the right of the USB jack

float temperatureC, temperatureF, holdTempC = 0.0;
float lowC, highC = 0;
float lowF, highF = 0;
float humidity = 0;

// This routine runs only once upon reset
void setup() {
  // Initialize D0 + D7 pin as output
  // It's important you do this here, inside the setup() function rather than outside it or in the loop function.
  pinMode(led, OUTPUT);
  pinMode(led2, OUTPUT);
  
  
    Spark.variable("CurrentTempC", &temperatureC, DOUBLE);
    Spark.variable("CurrentTempF", &temperatureF, DOUBLE);
    Spark.variable("HoldTempC", &holdTempC, DOUBLE);
    Spark.variable("Humidity", &humidity, DOUBLE);
}

// This routine gets called repeatedly, like once every 5-15 milliseconds.
// Spark firmware interleaves background CPU activity associated with WiFi + Cloud activity with your code. 
// Make sure none of your code delays or blocks for too long (like more than 5 seconds), or weird things can happen.
void loop() {
  digitalWrite(led, HIGH);   // Turn ON the LED pins
  digitalWrite(led2, LOW);
  delay(1000);
  digitalWrite(led, LOW);
  digitalWrite(led2, HIGH);
  delay(1000);               // Wait for 1 second in off mode
}

Of course, I completely missed this.

It would be safer to use a double variable for your DOUBLE Spark.variable.

Since something like this is what happens when you define a Spark.variable.

  float someFloat;
  void* ptrToSparkVar.
  
  // store pointer to someFloat e.g. in setup()
  ptrToSparkVar = (void*)&someFloat;
  
  // return the float as double - part of "background" cloud code between loop()
  return (double)*ptrToSparkVar;

So actually the return statement doesn’t have a clue that the provided pointer actually references a float location and so doesn’t really know about the need to do a float -> double conversion.

Well that makes sense, I should have changed the type.

So, I made the change and flashed my core with the new code and I still get the same results. Discouraging.

// Define the pins we're going to call pinMode on
int led = D0;  // You'll need to wire an LED to this one to see it blink.
int led2 = D7; // This one is the built-in tiny one to the right of the USB jack

double temperatureC, temperatureF, holdTempC = 0.0;
double humidity = 0;

// This routine runs only once upon reset
void setup() {
  // Initialize D0 + D7 pin as output
  // It's important you do this here, inside the setup() function rather than outside it or in the loop function.
  pinMode(led, OUTPUT);
  pinMode(led2, OUTPUT);
  
  
    Spark.variable("CurrentTempC", &temperatureC, DOUBLE);
    Spark.variable("CurrentTempF", &temperatureF, DOUBLE);
    Spark.variable("HoldTempC", &holdTempC, DOUBLE);
    Spark.variable("Humidity", &humidity, DOUBLE);
}

// This routine gets called repeatedly, like once every 5-15 milliseconds.
// Spark firmware interleaves background CPU activity associated with WiFi + Cloud activity with your code. 
// Make sure none of your code delays or blocks for too long (like more than 5 seconds), or weird things can happen.
void loop() {
  digitalWrite(led, HIGH);   // Turn ON the LED pins
  digitalWrite(led2, LOW);
  delay(1000);
  digitalWrite(led, LOW);
  digitalWrite(led2, HIGH);
  delay(1000);               // Wait for 1 second in off mode
}

Hi @xcode

I loaded this code on to a core and ran it–it has been working fine for me for several minutes. How long does it take to fail for you?

Can you try it with a standard WiFi router instead of your phone? I think something in your setup around the core is not right. Do you have this problem with any other programs you have tried?

Hi @bko

The core is actually connected to my home WiFi. This current example will error out in about 2 min. But if I comment out the Spark.variablelines everything is just fine.

I ran it for around 10 minutes without trouble before I moved on.

How are you accessing the Spark variables when it fails? Do you have CoAP port 5683 open for outbound connections? Any router firewall? Can you flash over-the-air successfully? Any other trouble with Spark publish or function?

I’m using postman to call the APIs for the variables and functions. I don’t have any issues flashing over-the-air and functions and publish events were working just fine before the problem with the WiFi resetting. After which everything times out.

I re-flashed my original code after commenting out the Spark.variables and that ran all day without issues. I then uncommented the Spark.variables. It’s been running fine for a hour now. Can’t explain it. Haven’t changed anything with the network or firewall.

Thanks for the help.