Photon goes offline, WiFi signal seems ok though


#1

I have a Photon controlling a few things in my greenhouse outside. I bought a netgear wifi extender and put in the garage so the signal reaches out there, but it goes offline every couple days or so and won’t come on until I reset it. I added some code in the sketch the published the RSSI signal the Photon has, and it’s around 65-70, which seems good (My phone shows good wifi out there, too). I send a little data to the Particle server every 10 seconds. Temp, humidity, LED status in my Blynk app. That’s about it. Any ideas why this is happening? Here’s my code:

//LIBRARIES
#include "Particle.h"
#include <blynk.h>
#include "Adafruit_DHT.h"
//PINS
#define analogMQ7 A4 //CO2 sensor pin
#define DHTPIN 2     // what pin we're connected to
#define heat 6 //relay for heater
#define lamp 5 //relay for heater
#define fan 4   //fresh air fan
#define aux 3   //aux relay

//TEMP SENSOR INIT
#define DHTTYPE DHT22   // DHT 22 (AM2302)
DHT dht(DHTPIN, DHTTYPE);
//Temp sensor connections:
// Connect pin 1 (on the left) of the sensor to +5V
// Connect pin 2 of the sensor to whatever your DHTPIN is
// Connect pin 4 (on the right) of the sensor to GROUND
// Connect a 10K resistor from pin 2 (data) to pin 1 (power) of the sensor

//CO2 sensor connections:
//Connect pin A0 to A4 on the PHOTON
//Connect Gnd to ground
//Connect Vcc to Vin

//Blynk init
char auth[] = "xxxxxxxxxxxxxxxxxxxx";

WidgetLED led_heat(V2);
WidgetLED led_lamp(V3);
WidgetLED led_fan(V4);
WidgetLED led_aux(V7);

// Attach virtual serial terminal to Virtual Pin V0
WidgetTerminal terminal(V0);

//Variables
float h; //humidity
float t; //temperature
unsigned long loopMillis; //loop timer
int tempErr; //count error readings on the temp sensor

struct settings {
    int heater_setpoint;  //lower than this, heater comes on
    int fan_setpoint; //higher than this, exhaust fan comes on
    unsigned long lampDelay; //timer delay for lamp recept
    int enableHeat; //enable or disable the low temp heat control
    int lampReceptState; //manual off (0), on (1), or timed with heat (3)
    int enableFan; //enable or disable the high temp exhaust fan control
    int lowTempWarming; //notify if temp drops 5 degrees below setpoint
    int auxReceptState; //manual ON/OFF state of the 4th recept, controlled by V40
} s;


int rssi = 0;
    
void wifi_status() {    
    rssi = WiFi.RSSI();
    Particle.publish("rssi", String(rssi), 60, PRIVATE);
    Blynk.virtualWrite(V50, rssi);
}



void setup() {
    //Serial.begin(9600);
    delay(1000); // Allow board to settle
    EEPROM.get(1, s); //get the settings from EEPROM
    Blynk.begin(auth); //begin Blynk
    dht.begin();    //begin temp sensor
    pinMode(heat, OUTPUT); //set pin modes
    pinMode(lamp, OUTPUT); //set pin modes
    pinMode(fan, OUTPUT);   //set pin modes
    pinMode(aux, OUTPUT);   //set pin modes
    digitalWrite(heat, LOW); //turn off heater 1
    digitalWrite(lamp, LOW); //turn off heater 2
    digitalWrite(fan, LOW); //turn off the fan
    digitalWrite(aux, LOW); //turn off the aux relay
    //set the external antenna
    WiFi.selectAntenna(ANT_EXTERNAL);

    Particle.variable("RSSI", &rssi, INT);

}

void loop() {
    Blynk.run();
    if (millis() - loopMillis > 10000UL) { //do this every 10 seconds
        loopMillis = millis(); //update the timer
        read_temp(); //read temp and humidity
        update_heater(); //control to heater relay
        update_fan();    //control the fan relay
        update_lampRecept(); //set the 3rd relay state
        update_auxRecept(); //set the 4th relay state
        wifi_status(); //publish RSSI
    }
}

void read_temp() {
    // Read the humidity
    h = dht.getHumidity();
    // Read temperature as Farenheit
    t = dht.getTempFarenheit();

    // Check if any reads failed and exit early (to try again).
    if (isnan(h) || isnan(t)) {
        tempErr++;
        if (tempErr > 10) { //10 errors takes about 50 seconds
            Blynk.notify("We're not getting a correct reading from the temperature sensor! Please call technical support!");
            tempErr = 0; //reset the error counter
        }
        return;
    }
    else {
        tempErr = 0; //reset the error counter
    }
    t = t - 3; //temp reads about 3 degrees high
    Blynk.virtualWrite(V5, t);  //V5 is temperature
    Blynk.virtualWrite(V6, h); //V6 is humidity
    
    //low temp warning
    if (t <= s.heater_setpoint - 5 && s.lowTempWarming) { //it's 5 degrees colder than it should be, heat isn't keeping up!
        Blynk.notify("The heaters can't keep up!  It's more than 5 degrees colders in the greenhouse than the heater setpoint!");
    }
}

void update_heater() {
    static unsigned long startTime; //time the heat turns on
    if (s.enableHeat) { 
        if (t < s.heater_setpoint) { //it's too cold
            if (digitalRead(heat) == 0) { //heat wasn't on
                startTime = millis(); //heat is just starting
            }
            digitalWrite(heat, HIGH); //so turn on the heat
            led_heat.on();
            if (millis() - startTime > s.lampDelay && s.lampReceptState == 3) { 
                //has it been on long enough for heat2 & is the lamp recept option set to timer?
                digitalWrite(lamp, HIGH); //start aux heat
                led_lamp.on();
            }
        }
        
        if (t > s.heater_setpoint) { //temp is above setpoint
            digitalWrite(heat, LOW); //turn off heat 1
            led_heat.off(); //turn off the heat LED
            if (s.lampReceptState == 3) { //lamp controlled by heat timer
                digitalWrite(lamp, LOW); //and heat 2 in case it was on too
                led_lamp.off();
            }
        }
    }
    else { //heat is turned off
        digitalWrite(heat, LOW); //turn off heat 1
        led_heat.off(); //LED off
        if (s.lampReceptState == 3) { //lamp is controlled via heat timer
            digitalWrite(lamp, LOW); //so turn it off since heat is disabled
            led_lamp.off(); //LED off
        }
    }
}

void update_fan() {
    if (s.enableFan) {
        if (t > s.fan_setpoint) { //it's too hot
            digitalWrite(fan, HIGH); //so turn on the fan
            led_fan.on();   //turn on the fan LED
        }
    
        if (t < s.fan_setpoint) { //it's cooled off
            digitalWrite(fan, LOW); //turn off the fan
            led_fan.off();  //turn off the fan LED
        }
    }
    else { //not using fan
        digitalWrite(fan, LOW); //turn off the fan
        led_fan.off();  //turn off the fan LED
    }
}

void update_lampRecept() {
    if (s.lampReceptState == 2) { //Off
        digitalWrite(lamp, LOW); //turn off relay
        led_lamp.off(); //turn off LED
    }
    else if (s.lampReceptState == 1) { //ON
        digitalWrite(lamp, HIGH); //turn on relay
        led_lamp.on(); //turn on LED
    }
}

void update_auxRecept() { 
    if (s.auxReceptState) { //ON from the manual button in the app
        digitalWrite(aux, HIGH); //turn on the relay
        led_aux.on(); //turn on the LED
    }
    else {
        digitalWrite(aux, LOW); //turn off the relay
        led_aux.off(); //turn off the LED
    }
 }
 
BLYNK_CONNECTED() {
    terminal.clear();
    terminal.println(F("Blynk connected"));
    terminal.flush();
    
    Blynk.virtualWrite(V20, s.enableHeat);
    Blynk.virtualWrite(V21, s.heater_setpoint);
    Blynk.virtualWrite(V22, s.heater_setpoint);
    Blynk.virtualWrite(V23, s.lampReceptState);
    Blynk.virtualWrite(V24, s.lowTempWarming);
    Blynk.virtualWrite(V30, s.enableFan);
    Blynk.virtualWrite(V31, s.fan_setpoint);
    Blynk.virtualWrite(V32, s.fan_setpoint);
    //HEAT1 LED
    if (digitalRead(heat) == HIGH) led_heat.on();
    else  led_heat.off();
    //HEAT2 LED
    if (digitalRead(lamp) == HIGH) led_lamp.on();
    else  led_lamp.off();
    //FAN LED
    if (digitalRead(fan) == HIGH) led_fan.on();
    else  led_fan.off();
}

BLYNK_WRITE(18) { //aux heat delay
    //1: no delay   2: 5 min    3: 15 min   4: 30 min   5: 60 min
    int i = param.asInt();
    if (i == 1) s.lampDelay = 0;
    if (i == 2) s.lampDelay = 300000;
    if (i == 3) s.lampDelay = 900000;
    if (i == 4) s.lampDelay = 1800000;
    if (i == 5) s.lampDelay = 3600000;
    EEPROM.put(1, s); //save the settings to EEPROM
}

BLYNK_WRITE(20) {     //turn on/off heater function
    s.enableHeat = param.asInt();
    EEPROM.put(1, s); //save the settings to EEPROM
    if (s.enableHeat == 0) {
        Blynk.notify("You turned off the freeze protection.  The heater(s) will not come on in cold weather.");
    }
}

BLYNK_WRITE(V22) { //Heater temp select SLIDER
    //sets the low temp for the heater to kick on
    s.heater_setpoint = param.asInt();
    EEPROM.put(1, s); //save the settings to EEPROM
    Blynk.virtualWrite(V21, s.heater_setpoint);

}

BLYNK_WRITE(23) {     //turn on/off/Timer for the lamp recept
    s.lampReceptState = param.asInt();
    EEPROM.put(1, s); //save the settings to EEPROM
}

BLYNK_WRITE(24) {     //turn on/off low temp notification
    s.lowTempWarming = param.asInt();
    EEPROM.put(1, s); //save the settings to EEPROM
}

BLYNK_WRITE(30) {     //turn on/off fan function
    s.enableFan = param.asInt();
    EEPROM.put(1, s); //save the settings to EEPROM
        if (s.enableHeat == 0) {
        Blynk.notify("You turned off the exhaust fan.  It will not come on when the terperature gets hot.");
    }
}

BLYNK_WRITE(V32) { //Fan temp select SLIDER
    //sets the high temp for the fan to kick on
    s.fan_setpoint = param.asInt();
    EEPROM.put(1, s); //save the settings to EEPROM
    Blynk.virtualWrite(V31, s.fan_setpoint);
}

BLYNK_WRITE(V40) { //4th receptacle ON/OFF manually
    s.auxReceptState = param.asInt();
    EEPROM.put(1, s); //save the settings to EEPROM
}



#2

A common recommendation is to eliminate Strings.
It appears you are creating one every 10 seconds.


#3

OK, I can do that, but unfortunately that’s not the problem. …I thought maybe the wifi strength was the problem, so I just added that snippet of code in last week to show the wifi strength. But it’s been dropping out even before that.


#4

If no one sees any other issues, I can think of a couple things to do to troubleshoot. First I’ll bring it inside, close to my main router, and connect it to that, rather than going thru the repeater. Let it run a few day and see what happens…
Also, I can just load a very simple sketch that sends the temp value once a minute and does nothing else. though my current sketch isn’t really that complicated.

This is my first experience with the Photon, and an internet connected project. I’ve done LOTS of arduino stuff. Do these Photons normally work quite reliably?


#5

What device OS version? From what I remember reading on this forum, device OS v0.7.0 may have some issues when reconnecting after a signal loss. When it reconnects it needs a large amount of free memory. The Blynk library might come into play there as well but I can’t be sure about that. Maybe try v0.8.0.rc12 if you haven’t already.


#6

Thanks! Yes, I’m using .0.7.0
I’ll try v0.8.0.rc12 when we get home from the mountains!


#7

what is the proper way to publish the RSSI, and eliminate Strings? I just got that code snippet from the particle docs…


#8

search the forum for snprintf(
There are lots of examples :wink:


#9

I’ve looked at some examples, but not sure how to convert the following code to do away with String, and use snprintf(

int rssi = 0;

void wifi_status() {
rssi = WiFi.RSSI();
Particle.publish(“rssi”, String(rssi), 60, PRIVATE);
Blynk.virtualWrite(V50, rssi);
}


#10

You need a charachter array (e.g. char data[16]) into which you feed the string via snprintf() and then publish that via Particle.publish("rssi", data, PRIVATE);.

But this should be discussed either in this thread or your other RSSI code snippet not working


RSSI code snippet not working
#11

@SouthernAtHeart did the DeviceOS upgrade sort your issue?

If not, implementt the logger so as to assist with debug. You can configure it to output DeviceOS messages.