Continue working with loss of internet?

Hi :slight_smile:

One question: I’ve noticed that if my Photon loses connection to the internet void loop() doesn’t work anymore. Is there a setting which I can choose that it the loop is still working?

If you search for “no internet”, you’ll find countless topics discussing this already.
Have a look at system modes, and system threading. Both are documented, and shouldn’t be too hard to implement.

3 Likes

Hi :slight_smile:

According to the docs SYSTEM_THREAD(ENABLED); is used for “seperate” the running of your code and system stuff. I’ve enabled it but my code still stops if it loses the connection to the cloud or wifi. AFAIK SYSTEM_MODE(SEMIAUTOMATIC); (which I use) is used if you want to start the connection not automatic but it will reconnect automatically to the cloud/wifi if it loses connection. Is that true?

But however, I still have the problem that my code isn’t running when the Photon loses connection.

Seeing your code may help.

2 Likes
#include <Wire.h>
#include <Adafruit_SSD1306.h>
#include <Adafruit_GFX.h>

// OLED display TWI address
#define OLED_ADDR   0x3C

Adafruit_SSD1306 display(-1);

#if (SSD1306_LCDHEIGHT != 64)
#error("Height incorrect, please fix Adafruit_SSD1306.h!");
#endif

 
float tempf;
float tempc;
float humidity;
float inches;

int altitude = 73;
double pot3;
float pot2;
float pot1;
float pressurehpa;

char id[] = "xxxxxxxx";
char pwd[] = "xxxxxxx";

char data[180];
char data2[360];
char data3[180];

unsigned long previousMillis = 0;        // will store last time LED was updated

// constants won't change:
const long interval = 600000;           // interval at which to blink (milliseconds)

int counters = 0;
float sumwspavg = 0;
float sumwdiravg = 0;

float gustms = 0;

#include "Adafruit_Sensor.h"
#include "Adafruit_BME280.h"

#define BME_SCK D0
#define BME_MISO D3
#define BME_MOSI D2
#define BME_CS D1

char* SSID = "xxxxxxx";
char* PASSWORD = "";


#define SEALEVELPRESSURE_HPA (1013.25)
Adafruit_BME280 bme; // I2C
//Adafruit_BME280 bme(BME_CS); // hardware SPI
//Adafruit_BME280 bme(BME_CS, BME_MOSI, BME_MISO,  BME_SCK);


SYSTEM_THREAD(ENABLED);
SYSTEM_MODE(SEMI_AUTOMATIC);
STARTUP(WiFi.selectAntenna(ANT_EXTERNAL));

int VaneValue;// raw analog value from wind vane
int Direction;// translated 0 - 360 direction
int CalDirection;// converted value with offset applied
int LastValue;

#define Offset 0; 

#include <math.h>

#define WindSensorPin (D6) // The pin location of the anemometer sensor

volatile unsigned long Rotations; // cup rotation counter used in interrupt routine
volatile unsigned long ContactBounceTime; // Timer to avoid contact bounce in interrupt routine

float WindSpeed; // speed miles per hour
float WindSpeedkt;
float WindSpeedms;
int displays = 0;

void setup() {
  // initialize and clear display
  LastValue = 1; 
    Serial.begin(9600);
  Serial.println(F("BME280 test"));

pinMode(WindSensorPin, INPUT);

WiFi.on();
WiFi.disconnect();
WiFi.setCredentials(SSID, PASSWORD);
WiFi.connect();
waitUntil(WiFi.ready);
Particle.connect();



  display.begin(SSD1306_SWITCHCAPVCC, OLED_ADDR);
  display.clearDisplay();
  display.display();
  

  if (!bme.begin(0x76)) {
    Serial.println("Could not find a valid BME280 sensor, check wiring!");
    display.setTextSize(5);
  display.setTextColor(WHITE);
  display.setCursor(0,0);
  display.print("N/A");
  display.display();
    
  }




}

void loop() {
  // put your main code here, to run repeatedly:
  // display a line of text
  
  
  Rotations = 0; // Set Rotations count to 0 ready for calculations

	attachInterrupt(WindSensorPin, isr_rotation, FALLING);
	delay(3000);
	detachInterrupt(WindSensorPin);
	// convert to mp/h using the formula V=P(2.25/T)
	// V = P(2.25/3) = P * 0.75

	WindSpeed = Rotations * 0.75;
	WindSpeedkt = WindSpeed /  1.151;
    WindSpeedms = WindSpeed /  2.237;
  
 VaneValue = analogRead(A4);
Direction = map(VaneValue, 0, 4095, 0, 360);
CalDirection = Direction + Offset;

if(CalDirection > 360)
CalDirection = CalDirection - 360;

if(CalDirection < 0)
CalDirection = CalDirection + 360; 
  
  
  counters = counters + 1;
 sumwspavg = sumwspavg + WindSpeedms;
 sumwdiravg = sumwdiravg + CalDirection;
 
 if (WindSpeedms >= gustms) {
    gustms = WindSpeedms; 
}


   tempc = bme.readTemperature();
    tempf = tempc * 1.8 + 32;
    humidity = bme.readHumidity();
    pressurehpa = (bme.readPressure() / 100.0F);
    inches =  0.02952998751 * pressurehpa;
    
  float a = 17.271;
  float b = 237.7;
  float taupunktTemp = (a *  bme.readTemperature()) / (b +  bme.readTemperature()) + log(humidity/100);
  float pPre= (b * taupunktTemp) / (a - taupunktTemp);
  float pf = pPre * 1.8 + 32;
  
  pot1 = 1 - 0.0065 * altitude / (bme.readTemperature() + 0.0065 * altitude + 273.15);
  pot2 = (0.03416 / 0.0065);
  pot3 = pow(pot1,pot2);
  float relhpa = pressurehpa / pot3;
  float relinches = 0.02952998751 * relhpa;
  
  displays = displays + 1;
  
  if (displays > 3) {
      displays = 0;
  }
  
  if ((displays == 0) or (displays == 1)) {
      

 display.clearDisplay();
  display.setTextSize(2);
  display.setTextColor(WHITE);
  display.setCursor(0,0);
  display.print(tempc,1);
  display.print(" Grad");
  
  display.setTextSize(2);
  display.setTextColor(WHITE);
  display.setCursor(0,20);
  display.print(WindSpeedkt,1);
  display.print(" kt");

  display.setTextSize(2);
  display.setTextColor(WHITE);
  display.setCursor(0,40);
  display.print(CalDirection);
  display.print(" deg");
  
 
  // update display with all of the above graphics
  display.display();
  
  
  }
  
   if ((displays == 2) or (displays == 3)) {
  
 display.clearDisplay();
  display.setTextSize(2);
  display.setTextColor(WHITE);
  display.setCursor(0,0);
  display.print(tempc,1);
  display.print(" Grad");

  display.setTextSize(2);
  display.setTextColor(WHITE);
  display.setCursor(0,20);
  display.print(relhpa,2);
  display.print(" hP");
  
  display.setTextSize(2);
  display.setTextColor(WHITE);
  display.setCursor(0,40);
  display.print(humidity,1);
  display.print(" %");
  // update display with all of the above graphics
  display.display();
  
  
  }
  
  
  
   snprintf(data, sizeof(data)
        ,"{\"id\":\"%s\""
         ",\"pw\":\"%s\""
         ",\"dt\":\"%s\""
         ",\"tf\":\"%.1f\""
         ",\"hum\":\"%.1f\""
         ",\"baro\":\"%.2f\""
         ",\"tau\":\"%.1f\""
         ",\"wsm\":\"%.1f\""
         ",\"wd\":\"%.d\""
         "}"
        ,id
        ,pwd
        ,"now"
        ,tempf
        ,humidity
        ,relinches
        ,pf
        ,WindSpeed
        ,CalDirection
        );
        
        
        
        
snprintf(data3, sizeof(data3)
        ,"{\"tf\":\"%.1f\""
         ",\"hum\":\"%.1f\""
         ",\"baro\":\"%.2f\""
         ",\"wsm\":\"%.1f\""
         ",\"wd\":\"%.d\""
         ",\"tau\":\"%.1f\""
         "}"
        ,tempf
        ,humidity
        ,relinches
        ,WindSpeed
        ,CalDirection
        ,pPre
        );




 Particle.publish("spanienwunderground", data, PRIVATE);
 Particle.publish("windyspain", data3, PRIVATE);


unsigned long currentMillis = millis();


if (currentMillis - previousMillis >= interval) {
    // save the last time you blinked the LED
    previousMillis = currentMillis;


  float wspdavg = sumwspavg / counters;
  float wdiravg = sumwdiravg / counters;
  
  
  
 int barw = relhpa * 10;
 int humw = humidity;
  int tempw = tempc * 10;
 int wspdw = WindSpeedms * 10;
  int wdirw = CalDirection;
  int wspdavgw = wspdavg * 10;
  int wdiravgw = wdiravg;
  int wsphdiw = gustms * 10;
  int dew = pPre * 10;
  
    snprintf(data2, sizeof(data2)
        ,"{\"bar\":\"%d\""
         ",\"hum\":\"%d\""
         ",\"temp\":\"%d\""
         ",\"wspd\":\"%d\""
         ",\"wdir\":\"%d\""
         ",\"wspdavg\":\"%d\""
         ",\"wdiravg\":\"%d\""
         ",\"wspdhi\":\"%d\""
         ",\"dew\":\"%d\""
         "}"
        ,barw
        ,humw
        ,tempw
        ,wspdw
        ,wdirw
        ,wspdavgw
        ,wdiravgw
        ,wsphdiw
        ,dew
        );

 Particle.publish("weathercloud", data2, PRIVATE);


  
  gustms =  0;
  counters = 0;
  sumwspavg = 0;
  sumwdiravg = 0;

}
}

void isr_rotation () {

	if ((millis() - ContactBounceTime) > 15 ) { // debounce the switch contact.
		Rotations++;
		ContactBounceTime = millis();
	}

} 

any ideas or guesses?

I’ve seen multiple things I’d do differently but each of them by itself wouldn’t explain your issue.
However, they might interact in some non-obvious way to lead to some undesirable effects.

e.g. I’d not do this

  attachInterrupt(WindSensorPin, isr_rotation, FALLING);
  delay(3000);
  detachInterrupt(WindSensorPin);

I’d rather leave the interrupt attached and avoid the delay().

I already have previously suggested some better way to update your display here (I’m somewhat wondering why I wasted my time to offer these suggestions since I didn’t even get a reply on that post).

Additionally these elaborate calculations may also benefit from some rework.

BTW, what kind of WindSensor are you using?
Does it have an external pull-up resistor attached?
If not, you need to set pinMode(WindSensorPin, INPUT_PULLUP);

However, one thing that would cause your code to block while it’s not connected is that you are calling Particle.publish() irrespective of the connection. This is bad.
But this shouldn’t prevent an automatic reconnect.

Try this (slightly) cleand-up code
https://go.particle.io/shared_apps/5ce1777bec6e390005e3f612

Thank you! :slight_smile:

1 Like