[SOLVED] Blynk app goes offline constantly, where did I go wrong?

Everything works fine but every 10 seconds or so i get the error “particle photon is offline”, can someone point out my issue? It was fine until I added the last bit about the bluetooth but where should i move it to? Thanks for any help, John

//#pragma SPARK_NO_PREPROCESSOR
#include "blynk/blynk.h"
#include "blynk/BlynkSimpleParticle.h"
#include "SparkCorePolledTimer/SparkCorePolledTimer.h"
#include "spark-dallas-temperature/spark-dallas-temperature.h"
#include "OneWire/OneWire.h"
#include "MCP23008-I2C/MCP23008-I2C.h"  //I2C STUFF
#define ONE_WIRE_BUS D2                 // Data wire is plugged into pin D2 on the particle
#define TEMPERATURE_PRECISION 12        // DS18B20 Thermometer Stuff

char auth[] = "stuff";  //BLYNK CE4

WidgetLED led1(V31);    //BLYNK LED WIDGET on
WidgetLED led2(V30);    //BLYNK LED WIDGET off

const int pinTrig = D6;                 //bt signal in
const     uint32_t msBlinking = 2000;   //bt LED needs to be lit more than
volatile  uint32_t msLastTrig;          //bt trigger 
bool connected;                         //bt code returns 0 or 1

bool locked;                            //door lock returns 0 or 1
bool motion;                            //motion sensed returns 0 or 1


OneWire oneWire(ONE_WIRE_BUS);          // DS18B20 Thermometer Stuff
DallasTemperature sensors(&oneWire);    // DS18B20 Thermometer Stuff
Adafruit_MCP23008 mcp;                  // I2C STUFF
SparkCorePolledTimer updateTimer(5000); //Create a timer object and set it's timeout in milliseconds
void OnTimer(void);                     //Prototype for timer callback method

float main, mainRaw, aux, auxRaw, acc, accRaw, light, lightRaw;
//float bt, btRaw;

//define temp address
DeviceAddress Thermometer1 = { 0x28, 0xFF, 0x44, 0x50, 0x16, 0x15, 0x3, 0xC };      //outside temp
DeviceAddress Thermometer2 = { 0x28, 0xFF, 0xD5, 0x4D, 0x16, 0x15, 0x3, 0xD3 };     //inside temp
DeviceAddress Thermometer3 = { 0x28, 0xFF, 0x2D, 0x37, 0x16, 0x15, 0x3, 0xF8 };     //fridge temp
DeviceAddress Thermometer4 = { 0x28, 0xFF, 0x6A, 0x24, 0x16, 0x15, 0x3, 0xF0 };     //spare temp

// define temp bit resolution ie: int, float, double
double InTempC = -1;    //this line could probably get deleted, also 0 instead of -1
double Temp1 = -1;
double Temp2 = -1; 
double Temp3 = -1;
double Temp4 = -1;
void update18B20Temp(DeviceAddress deviceAddress, double &tempC);
//end temp stuff



//bt trigger stuff
void trig()
{
  msLastTrig = millis();
}




 //setupsetupsetupsetupsetupsetupsetupsetupsetupsetupsetupsetupsetupsetupsetupsetupsetupsetupsetupsetupsetupsetupsetupsetupsetup 
void setup()
{
Serial.begin(9600);
Blynk.begin(auth);          // BLYNK initialization
updateTimer.SetCallback(OnTimer);
//Particle.function("lock", lock);
//Particle.function("unlock", unlock);

pinMode(pinTrig, INPUT);                    //bt trigger 
attachInterrupt(pinTrig, trig, FALLING);    //bt trigger

sensors.begin();            // DS18B20 initialization
sensors.setResolution(Thermometer1, TEMPERATURE_PRECISION);
sensors.setResolution(Thermometer2, TEMPERATURE_PRECISION); 
sensors.setResolution(Thermometer3, TEMPERATURE_PRECISION);
sensors.setResolution(Thermometer4, TEMPERATURE_PRECISION);

pinMode(A0, INPUT);         //main battery voltage
pinMode(A1, INPUT);         //aux battery voltage
pinMode(A2, INPUT);         //acc voltage use to tell if vehicle is running
//pinMode(A3, INPUT);       //spare
//pinMode(A4, INPUT);       //spare
pinMode(A5, INPUT);         //ambient light sensor
//pinMode(A6, INPUT);       //spare
//pinMode(A7, INPUT);       //spare


//pinMode(D0, INPUT);       //used by I2C Relays DO NOT ENABLE
//pinMode(D1, INPUT);       //used by I2C Relays DO NOT ENABLE
//pinMode(D2, INPUT);       //used by TEMP Sensors DO NOT ENABLE
pinMode(D3, INPUT_PULLUP);  //inner motion trigger
pinMode(D4, INPUT_PULLUP);  //outer motion trigger
//pinMode(D5, INPUT);       //spare
//pinMode(D6, INPUT);       //used by BT photoresistor DO NOT ENABLE
pinMode(D7, OUTPUT);        //bt shows visual of connection boolean, not neccessary

//pinmode(lock, OUTPUT);
//pinmode(unlock, OUTPUT);



// I2C STUFF
mcp.begin();      // use default address 0
  mcp.pinMode(0, OUTPUT); 
  mcp.pinMode(1, OUTPUT);
  mcp.pinMode(2, OUTPUT);
  mcp.pinMode(3, OUTPUT);
  mcp.pinMode(4, OUTPUT);
  mcp.pinMode(5, OUTPUT);
  mcp.pinMode(6, OUTPUT);
  mcp.pinMode(7, OUTPUT);
// END I2C STUFF
}// END VOID SETUP

// BLYNY WRITE NEEDS TO BE ABOVE LOOP BUT NOT IN SETUP LIKE THIS
// I2C STUFF
BLYNK_WRITE(0) {                        //bluetooth power
    if (param.asInt()) {
        mcp.digitalWrite(0, HIGH);
        delay(2000);
    } else {
       mcp.digitalWrite(0, LOW);}}
       
BLYNK_WRITE(1) {                        //start/stop
    if (param.asInt()) {
        mcp.digitalWrite(1, HIGH);
        delay(3000);         
    } else {
       mcp.digitalWrite(1, LOW);}}
       
BLYNK_WRITE(2) {                        //spare - used for calibrating motion sensor
    if (param.asInt()) {
        mcp.digitalWrite(2, HIGH);
    } else {
       mcp.digitalWrite(2, LOW);}}
       
BLYNK_WRITE(3) {                        //windows vent  
    if (param.asInt()) {
        mcp.digitalWrite(3, HIGH);
    } else {
       mcp.digitalWrite(3, LOW);}}
       
BLYNK_WRITE(4) {                        //windows down
    if (param.asInt()) {
        mcp.digitalWrite(4, HIGH);
    } else {
       mcp.digitalWrite(4, LOW);}}
       
BLYNK_WRITE(5) {                        //windows up
    if (param.asInt()) {
        mcp.digitalWrite(5, HIGH);
    } else {
       mcp.digitalWrite(5, LOW);}}
       
BLYNK_WRITE(6) {                        //unlock    
    if (param.asInt()) {
        mcp.digitalWrite(6, HIGH);
        delay(500);   
        mcp.digitalWrite(6, LOW);
        delay(500);  
        mcp.digitalWrite(6, HIGH);
        delay(500); 
    } else {
       mcp.digitalWrite(6, LOW);}}
        
BLYNK_WRITE(7) {                        //lock
    if (param.asInt()) {
        mcp.digitalWrite(7, HIGH);
        delay(500);   
        mcp.digitalWrite(7, LOW);
        delay(500);  
        mcp.digitalWrite(7, HIGH);
        delay(500); 
    } else {
       mcp.digitalWrite(7, LOW);}}
//I2C STUFF


//looplooplooplooplooplooplooplooplooplooplooplooplooplooplooplooplooplooplooplooplooplooplooploop//looplooplooplooplooplooploopl
void loop()
{
Blynk.run();
updateTimer.Update();
}

void OnTimer(void) { //Handler for the timer, will be called automatically
        // DS18B20 change to farenheight and calibrate - change to *1.8 + 32
        sensors.requestTemperatures();
        update18B20Temp(Thermometer1, InTempC);
        Temp1 = (InTempC * 9)/5 + 32;
        update18B20Temp(Thermometer2, InTempC);  
        Temp2 = (InTempC * 9)/5 + 31.33;  
        update18B20Temp(Thermometer3, InTempC);  
        Temp3 = (InTempC * 9)/5 + 31.67;  
        update18B20Temp(Thermometer4, InTempC);  
        Temp4 = (InTempC * 9)/5 + 32; 
        
updateTimer.Update();    // new stuff i dont think we need this one
}

void update18B20Temp(DeviceAddress deviceAddress, double &tempC)
{
  tempC = sensors.getTempC(deviceAddress);

// read temperature and discard reading between 150 and -30, write to blynk - add averaging
if ( Temp1 < 150 && Temp1 > -30) {      //inside temp
    Blynk.virtualWrite(21, Temp1); 
}
if ( Temp2 < 150 && Temp2 > -30) {      //outside temp
    Blynk.virtualWrite(22, Temp2); 
}
if ( Temp3 < 150 && Temp3 > -30) {      //fridge temp
    Blynk.virtualWrite(23, Temp3);
}
if ( Temp4 < 150 && Temp4 > -30) {      //spare temp
    Blynk.virtualWrite(24, Temp4);
}

// read analog ports and rename for mapping and virtual pin assignment - add averaging
mainRaw = analogRead(A0);   //main battery voltage
auxRaw = analogRead(A1);    //aux battery voltage
accRaw = analogRead(A2);    //acc battery voltage
lightRaw = analogRead(A5);  //ambient light sensor
//btRaw = analogRead(A4);

// map analog input scale output
main = map(mainRaw, 0, 4096, 0, 1865);
aux = map(auxRaw, 0, 4096, 0, 1865);
acc = map(accRaw, 0, 4096, 0, 1865);
light = map(lightRaw, 0, 4050, 1100, 1500);
//bt = map(btRaw, 300, 3500, 0, 100);

// correct decimal place for blynk display
main = (main / 100);
aux = (aux / 100);
acc = (acc / 100);
light = (light / 100);

Blynk.virtualWrite(10, main);
Blynk.virtualWrite(11, aux);
Blynk.virtualWrite(12, acc);
//Blynk.virtualWrite(13, pulsecount);
Blynk.virtualWrite(14, connected);
Blynk.virtualWrite(15, light);

connected = (digitalRead(pinTrig) && (millis() - msLastTrig > msBlinking)); //bt connected boolean 
digitalWrite(D7, connected);    //bt shows visual of connection boolean, not neccessary




//if ((D2 == HIGH) && (A2 < .05))  {
//        mcp.digitalWrite(0, HIGH);
//        delay(2000);
//    } else {
//       mcp.digitalWrite(0, LOW);}
//or
//    Blynk.virtualWrite(20, HIGH); }
//    else  {
//    Blynk.virtualWrite(20, LOW);  }
//or
//BLYNK_WRITE(0)



if ( connected == 1) //Bluetooth LED is solid
{
WidgetLED led1(31); //means you need to have LED on app configured on virtual pin 31.
led1.on();
}
else {led1.off();}

if ( connected == 0) //Bluetooth LED is blinking or off
{
WidgetLED led2(30); //means you need to have LED on app configured on virtual pin 30.
led2.on();
}
else {led2.off();}


}

I’m not sure this is a reason but you shouldn’t use delays within BLYNK_WRITE. It should be executed as fast as possible. Please try to remove those delays.

Thanks, I will take those out and see what happens. I am simulating long key presses and double key presses with the waits, I’ll find another way to do that.

@Dmitriy you are the man, that was the problem. I’m not having any dropouts anymore, Thank you! Please let me know when i can send you guys some money, It is my most used app.

2 Likes

Glad you fixed it.

=))). Thank you, no need for that. We will introduce in-apps soon so you’ll be able to buy what you need if you need it.

Im having trouble with BLYNK going offline again, it seems the longer i wait to take readings (update timer) the less it goes offline but still goes out a couple times an hour. It seems to be a problem with the mcp pinmode and BlynkWrite function because if i comment that portion out everything runs fine even at high update rates. Is there a problem with using BlynkWrite over I2C? you can see where i comment out the portion using #if 0 and #endif, this solves the dropouts but cripples my relay controller. Any help would be appreciated, thank you!


#include "blynk/blynk.h"
#include "blynk/BlynkSimpleParticle.h"
#include "SparkCorePolledTimer/SparkCorePolledTimer.h"
#include "spark-dallas-temperature/spark-dallas-temperature.h"
#include "OneWire/OneWire.h"
#include "MCP23008-I2C/MCP23008-I2C.h"  //I2C STUFF
#include "Adafruit_DHT/Adafruit_DHT.h"
#define ONE_WIRE_BUS D2                 // Data wire is plugged into pin D2 on the particle
#define TEMPERATURE_PRECISION 12        // DS18B20 Thermometer Stuff
#define DHT1PIN C0         // what pin we're connected to
#define DHT2PIN C1        // what pin we're connected to
#define DHT1TYPE DHT22		// DHT 22 (AM2302)
#define DHT2TYPE DHT22		// DHT 22 (AM2302)

STARTUP(cellular_credentials_set("broadband", "", "", NULL));

Adafruit_MCP23008 mcp;                  // I2C STUFF

SparkCorePolledTimer updateTimer(1000); //Create a timer object and call it updateTimer - set it's timeout in milliseconds 180K = 5 minutes 
                                        //lower than 5000 and it lockes up after awhile and stack overflow code is thrown
                                        //10000 makes mcp relay response higher but less data transmitted
void OnTimer(void);                     //Prototype for timer callback 

float h1, t1, h2, t2;
DHT dht1(DHT1PIN, DHT1TYPE);
DHT dht2(DHT2PIN, DHT2TYPE);
float main, mainRaw, aux, auxRaw, acc, accRaw, light, lightRaw;

void setup()
{
Serial.begin(9600);
Blynk.begin("token", IPAddress(45,55,130,102), 8442);    //blynk token with electron address
updateTimer.SetCallback(OnTimer);

Particle.keepAlive(20);     //number of seconds between keep alive pings. Each ping uses 121 bytes of data
dht1.begin();
dht2.begin();
 
pinMode(A0, INPUT);         //main battery voltage
pinMode(A1, INPUT);         //aux battery voltage
pinMode(A2, INPUT);         //acc voltage use to tell if vehicle is running
//pinMode(A3, INPUT);       //spare
//pinMode(A4, INPUT);       //spare
pinMode(A5, INPUT);         //ambient light sensor
//pinMode(A6, INPUT);       //spare
//pinMode(A7, INPUT);       //spare

pinMode(C0, INPUT_PULLUP);         //DHT 1 
pinMode(C1, INPUT_PULLUP);         //DHT 2
//pinMode(C2, INPUT)          //used by BT photoresistor DO NOT ENABLE

//pinMode(D0, INPUT);       //used by I2C Relays DO NOT ENABLE maybe C0 on photon?
//pinMode(D1, INPUT);       //used by I2C Relays DO NOT ENABLE
//pinMode(D2, INPUT_PULLUP);       //used by TEMP Sensors DO NOT ENABLE
pinMode(D3, INPUT_PULLUP);  //inner motion trigger pulled high
pinMode(D4, INPUT_PULLUP);  //outer motion trigger pulled high
//pinMode(D5, OUTPUT);       //spare / inner motion
//pinMode(D6, INPUT);       //old code used by BT photoresistor DO NOT ENABLE
//pinMode(D7, OUTPUT);        //shows visual of connection boolean, outer motion
//pinmode(lock, OUTPUT);
//pinmode(unlock, OUTPUT);
}
#if 0

// I2C STUFF
mcp.begin();      // use default address 0
  mcp.pinMode(0, OUTPUT); 
  mcp.pinMode(1, OUTPUT);
  mcp.pinMode(2, OUTPUT);
  mcp.pinMode(3, OUTPUT);
  mcp.pinMode(4, OUTPUT);
  mcp.pinMode(5, OUTPUT);
  mcp.pinMode(6, OUTPUT);
  mcp.pinMode(7, OUTPUT);
// END I2C STUFF
}// END VOID SETUP

BLYNK_WRITE(0) {                        //bluetooth power
    if (param.asInt()) {
        mcp.digitalWrite(0, HIGH);
    } else {
       mcp.digitalWrite(0, LOW);}}
       
BLYNK_WRITE(1) {                        //start/stop
    if (param.asInt()) {
        mcp.digitalWrite(1, HIGH);
    } else {
       mcp.digitalWrite(1, LOW);}}
       
BLYNK_WRITE(2) {                        //spare - used for calibrating motion sensor
    if (param.asInt()) {
        mcp.digitalWrite(2, HIGH);
    } else {
       mcp.digitalWrite(2, LOW);}}
       
BLYNK_WRITE(3) {                        //windows vent  
    if (param.asInt()) {
        mcp.digitalWrite(3, HIGH);
    } else {
       mcp.digitalWrite(3, LOW);}}
       
BLYNK_WRITE(4) {                        //windows down
    if (param.asInt()) {
        mcp.digitalWrite(4, HIGH);
    } else {
       mcp.digitalWrite(4, LOW);}}
       
BLYNK_WRITE(5) {                        //windows up
    if (param.asInt()) {
        mcp.digitalWrite(5, HIGH);
    } else {
       mcp.digitalWrite(5, LOW);}}
       
BLYNK_WRITE(6) {                        //unlock    
    if (param.asInt()) {
        mcp.digitalWrite(6, HIGH);
    } else {
       mcp.digitalWrite(6, LOW);}}
        
BLYNK_WRITE(7) {                        //lock
    if (param.asInt()) {
        mcp.digitalWrite(7, HIGH);
    } else {
       mcp.digitalWrite(7, LOW);}}

#endif
//I2C STUFF
void loop()
{
Blynk.run();
updateTimer.Update();
}  //xxxxxxxxxxxxxxxxxxxxx

void OnTimer(void) {//Handler for the timer, will be called automaticallyxxxxxxxxxxxx

   h1 = dht1.getHumidity();     //moved from void loop above
   t1 = dht1.getTempFarenheit();//moved
   h2 = dht2.getHumidity();
   t2 = dht2.getTempFarenheit();

    Blynk.virtualWrite(21, t1); 
    Blynk.virtualWrite(22, h1); 
    Blynk.virtualWrite(23, t2); 
    Blynk.virtualWrite(24, h2); 
     
//Write temp and humidity to virtual pins to display degF and % symbols Interger drops decimal places
int t1degf = (int)t1;           //turn float t1 into interger
String temp1 = (String)t1degf;  //turn t1 into string
temp1 += "°F";                  //add deg f to string but wont map anymore on grfh
Blynk.virtualWrite(31, temp1);  // write to another pin due to graphing limitaion

int h1percent = (int)h1;           //turn float t1 into interger
String humid1 = (String)h1percent;  //turn t1 into string
humid1 += "%";                  //add deg f to string but wont map anymore on grfh
Blynk.virtualWrite(32, humid1);  // write to another pin due to graphing limitaion

int t2degf = (int)t2;           //turn float t1 into interger
String temp2 = (String)t2degf;  //turn t1 into string
temp2 += "°F";                  //add deg f to string but wont map anymore on grfh
Blynk.virtualWrite(33, temp2);  // write to another pin due to graphing limitaion

int h2percent = (int)h2;           //turn float t1 into interger
String humid2 = (String)h2percent;  //turn t1 into string
humid2 += "%";                  //add deg f to string but wont map anymore on grfh
Blynk.virtualWrite(34, humid2);  // write to another pin due to graphing limitaion

 
// read analog ports and rename for mapping and virtual pin assignment - add averaging
mainRaw = analogRead(A0);   //main battery voltage
auxRaw = analogRead(A1);    //aux battery voltage
accRaw = analogRead(A2);    //acc battery voltage
lightRaw = analogRead(A5);  //ambient light sensor

//motionOut = digitalRead(D2);   //outer motion sensor
//btRaw = analogRead(A4);

// map analog input scale output
main = map(mainRaw, 0, 4096, 0, 1865);
aux = map(auxRaw, 0, 4096, 0, 1865);
acc = map(accRaw, 0, 4096, 0, 1865);
light = map(lightRaw, 0, 4050, 1100, 1500);
//bt = map(btRaw, 300, 3500, 0, 100);

// correct decimal place for blynk display
main = (main / 100);
aux = (aux / 100);
acc = (acc / 100);
light = (light / 100);

Blynk.virtualWrite(10, main);
Blynk.virtualWrite(11, aux);
Blynk.virtualWrite(12, acc);
//Blynk.virtualWrite(13, motionOut);
//Blynk.virtualWrite(14, connected);
Blynk.virtualWrite(15, light);
//Blynk.virtualWrite(16, D4);
//Blynk.virtualWrite(17, D3);

}

I think I’ve found a solution, it had to do with either firmware or libraries, not the code. I noticed two of my Particle devices (simple temperature loggers with only blynk and timer in loop) were going offline at the same time, seemed odd. I updated the firmware and new blynk libraries and all is well, for now. It doesn’t seem like a lot of people are using the 3G particles and wifi electrons with blynk, hopefully this helps someone else.