Electron firmware alerting depending on a variable

Hi

I’m using a script to read temps from sensors. The Electron in order to save energy only sends the info every 4 cycles of measurements.

Now I want to wakeup the electron if the temp is higer than alert variable, but I’m doing something wrong, anybody could help to me?

Thank’s

STARTUP(System.enableFeature(FEATURE_RETAINED_MEMORY));
SYSTEM_MODE(SEMI_AUTOMATIC);
// This #include statement was automatically added by the Particle IDE.
#include <Adafruit_BMP280.h>
#include "Adafruit_Sensor.h"
#include "Adafruit_BMP280.h"

Adafruit_BMP280 bmp; // I2C
retained float temp[5];
retained float press[5];
retained  float vtime[5];
retained  float Abatt[5];
retained  float Alertfrozen=29;
String dest1;
String dest2;
String dest3;
String dest4;

// The variable we'll use to keep track of where we are in the array
retained unsigned int contador = 1;
void setup() {
Time.zone(+2); 
bmp.begin();
        //Reading battery level
        FuelGauge fuel;
        float batt;
        batt = fuel.getVCell();
        
        temp[contador] = bmp.readTemperature();
        press[contador] = bmp.readPressure();
        vtime[contador] = Time.now();
        Abatt[contador] = batt;
        
        if (bmp.readTemperature() >= Alertfrozen){
        Particle.connect();

                if (contador==1){
                
                dest1 = "{";
                dest1 = dest1 + "\"2\":\""+ (Time.now()-(360))+"\",";    
                dest1 = dest1 + "\"10\":\""+ Abatt[0] +"\",";
                dest1 = dest1 + "\"32\":\""+ press[0] +"\",";
                dest1 = dest1 + "\"33\":\""+ temp[0] +"\"";
                + "}";
                Particle.publish("******",dest1);
                }
                else if (contador==2){
                
                dest1 = "{";
                dest1 = dest1 + "\"2\":\""+ (Time.now()-(360))+"\",";    
                dest1 = dest1 + "\"10\":\""+ Abatt[0] +"\",";
                dest1 = dest1 + "\"32\":\""+ press[0] +"\",";
                dest1 = dest1 + "\"33\":\""+ temp[0] +"\"";
                + "}";
                Particle.publish("******",dest1);
                delay(4001);
                
                dest2 = "{";
                dest2 = dest2 + "\"2\":\""+ (Time.now()-(240))+"\",";    
                dest2 = dest2 + "\"10\":\""+ Abatt[1] +"\",";
                dest2 = dest2 + "\"32\":\""+ press[1] +"\",";
                dest2 = dest2 + "\"33\":\""+ temp[1] +"\"";
                + "}";
                Particle.publish("*****",dest2);
                }
                else if(contador==3){
                
                dest1 = "{";
                dest1 = dest1 + "\"2\":\""+ (Time.now()-(360))+"\",";    
                dest1 = dest1 + "\"10\":\""+ Abatt[0] +"\",";
                dest1 = dest1 + "\"32\":\""+ press[0] +"\",";
                dest1 = dest1 + "\"33\":\""+ temp[0] +"\"";
                + "}";
                Particle.publish("******",dest1);
                delay(4001);
                
                dest2 = "{";
                dest2 = dest2 + "\"2\":\""+ (Time.now()-(240))+"\",";    
                dest2 = dest2 + "\"10\":\""+ Abatt[1] +"\",";
                dest2 = dest2 + "\"32\":\""+ press[1] +"\",";
                dest2 = dest2 + "\"33\":\""+ temp[1] +"\"";
                + "}";
                Particle.publish("*********",dest2);
                delay(4001);
    
                dest3 = "{";
                dest3 = dest3 + "\"2\":\""+ (Time.now()-(120))+"\",";    
                dest3 = dest3 + "\"10\":\""+ Abatt[2] +"\",";
                dest3 = dest3 + "\"32\":\""+ press[2] +"\",";
                dest3 = dest3 + "\"33\":\""+ temp[2] +"\"";
                + "}";
                Particle.publish("********",dest3);
                }
                 
            }

What exactly is wrong? What result does this code give you?

1 Like

First, you are not doing anything "wrong", you are "not sending the devics to sleep" anywhere at all and hence no waking will be required :sunglasses:

But I'm also not aware of the BMP280 being capable of taking measurements, checking against a temperature range and issue an alert/wake interrupt while the host contoller is asleep.
Where have you read of that feature?

Hi @ScruffR, thank’s again for help me

sorry, my falt, I did not put all the code, I’m sending to sleep at the end of the if then.

I tried to do with the variable [array] but did not work. If contador(counter) is 3 and the temp[3] is >= than Alertfrozen then send the 3 arrays recorded in RAM. but the condition temp[3] did not work, may be I have to use a current variable for temp to do the condition?
float currenttemp = bmp.readTemperature();
and do the if with currenttemp?

See the code below

STARTUP(System.enableFeature(FEATURE_RETAINED_MEMORY));
SYSTEM_MODE(SEMI_AUTOMATIC);
// This #include statement was automatically added by the Particle IDE.
#include <Adafruit_BMP280.h>
#include "Adafruit_Sensor.h"
#include "Adafruit_BMP280.h"

Adafruit_BMP280 bmp; // I2C
retained float temp[5];
retained float press[5];
retained  float vtime[5];
retained  float Abatt[5];
retained  float Alertfrozen=29;
String dest1;
String dest2;
String dest3;
String dest4;

// The variable we'll use to keep track of where we are in the array
retained unsigned int contador = 1;

void setup() {
Time.zone(+2); 
bmp.begin();
        //Reading battery level
        FuelGauge fuel;
        float batt;
        batt = fuel.getVCell();
        
        temp[contador] = bmp.readTemperature();
        press[contador] = bmp.readPressure();
        vtime[contador] = Time.now();
        Abatt[contador] = batt;
        
        if (bmp.readTemperature() >= Alertfrozen){
        Particle.connect();

                if (contador==1){
                
                dest1 = "{";
                dest1 = dest1 + "\"2\":\""+ (Time.now()-(360))+"\",";    
                dest1 = dest1 + "\"10\":\""+ Abatt[0] +"\",";
                dest1 = dest1 + "\"32\":\""+ press[0] +"\",";
                dest1 = dest1 + "\"33\":\""+ temp[0] +"\"";
                + "}";
                Particle.publish("******",dest1);
                }
                else if (contador==2){
                
                dest1 = "{";
                dest1 = dest1 + "\"2\":\""+ (Time.now()-(360))+"\",";    
                dest1 = dest1 + "\"10\":\""+ Abatt[0] +"\",";
                dest1 = dest1 + "\"32\":\""+ press[0] +"\",";
                dest1 = dest1 + "\"33\":\""+ temp[0] +"\"";
                + "}";
                Particle.publish("******",dest1);
                delay(4001);
                
                dest2 = "{";
                dest2 = dest2 + "\"2\":\""+ (Time.now()-(240))+"\",";    
                dest2 = dest2 + "\"10\":\""+ Abatt[1] +"\",";
                dest2 = dest2 + "\"32\":\""+ press[1] +"\",";
                dest2 = dest2 + "\"33\":\""+ temp[1] +"\"";
                + "}";
                Particle.publish("******",dest2);
                }
                else if(contador==3){
                
                dest1 = "{";
                dest1 = dest1 + "\"2\":\""+ (Time.now()-(360))+"\",";    
                dest1 = dest1 + "\"10\":\""+ Abatt[0] +"\",";
                dest1 = dest1 + "\"32\":\""+ press[0] +"\",";
                dest1 = dest1 + "\"33\":\""+ temp[0] +"\"";
                + "}";
                Particle.publish("******",dest1);
                delay(4001);
                
                dest2 = "{";
                dest2 = dest2 + "\"2\":\""+ (Time.now()-(240))+"\",";    
                dest2 = dest2 + "\"10\":\""+ Abatt[1] +"\",";
                dest2 = dest2 + "\"32\":\""+ press[1] +"\",";
                dest2 = dest2 + "\"33\":\""+ temp[1] +"\"";
                + "}";
                Particle.publish("******",dest2);
                delay(4001);
    
                dest3 = "{";
                dest3 = dest3 + "\"2\":\""+ (Time.now()-(120))+"\",";    
                dest3 = dest3 + "\"10\":\""+ Abatt[2] +"\",";
                dest3 = dest3 + "\"32\":\""+ press[2] +"\",";
                dest3 = dest3 + "\"33\":\""+ temp[2] +"\"";
                + "}";
                Particle.publish("******",dest3);
                }
                 
            }

            
        else{
            if(contador >= 4){
                Particle.connect();
                 
                
                dest1 = "{";
                dest1 = dest1 + "\"2\":\""+ (Time.now()-(360))+"\",";    
                dest1 = dest1 + "\"10\":\""+ Abatt[0] +"\",";
                dest1 = dest1 + "\"32\":\""+ press[0] +"\",";
                dest1 = dest1 + "\"33\":\""+ temp[0] +"\"";
                + "}";
                Particle.publish("******",dest1);
                delay(4001);
                
                dest2 = "{";
                dest2 = dest2 + "\"2\":\""+ (Time.now()-(240))+"\",";    
                dest2 = dest2 + "\"10\":\""+ Abatt[1] +"\",";
                dest2 = dest2 + "\"32\":\""+ press[1] +"\",";
                dest2 = dest2 + "\"33\":\""+ temp[1] +"\"";
                + "}";
                Particle.publish("******",dest2);
                delay(4001);
    
                dest3 = "{";
                dest3 = dest3 + "\"2\":\""+ (Time.now()-(120))+"\",";    
                dest3 = dest3 + "\"10\":\""+ Abatt[2] +"\",";
                dest3 = dest3 + "\"32\":\""+ press[2] +"\",";
                dest3 = dest3 + "\"33\":\""+ temp[2] +"\"";
                + "}";
                Particle.publish("******",dest3);
                delay(4001);
                
                dest4 = "{";
                dest4 = dest4 + "\"2\":\""+ Time.now()+"\",";    
                dest4 = dest4 + "\"10\":\""+ Abatt[3] +"\",";
                dest4 = dest4 + "\"32\":\""+ press[3] +"\",";
                dest4 = dest4 + "\"33\":\""+ temp[3] +"\"";
                + "}";
                Particle.publish("******",dest4);
                delay(4001);
                
                
                
                //Particle.publish("Temp", String::format("%d,%d,%d,%d,%d", temp[0],temp[1],temp[2],temp[3],temp[4]));
                //Particle.publish("press", String::format("%d,%d,%d,%d,%d", press[0],press[1],press[2],press[3],press[4]));
                //Particle.publish("time", String::format("%d,%d,%d,%d,%d", vtime[0],vtime[1],vtime[2],vtime[3],vtime[4]));
                Particle.publish("retained", String(contador));
                // Reset index to 0
                contador = 0;
                temp[0]=0;
                temp[1]=0;
                temp[2]=0;
                temp[3]=0;
                temp[4]=0;
                
                press[0]=0;
                press[1]=0;
                press[2]=0;
                press[3]=0;
                press[4]=0;
                
                vtime[0]=0;
                vtime[1]=0;
                vtime[2]=0;
                vtime[3]=0;
                vtime[4]=0;
                
                Abatt[0]=0;
                Abatt[1]=0;
                Abatt[2]=0;
                Abatt[3]=0;
                Abatt[4]=0;
            }
            else {
                // increase the index by 1
                contador++;
                //Particle.publish("retained", String(contador));
                
            }
        }
/////////////////////////Sleep for 15 minutes to save battery/////////////////////////
System.sleep(SLEEP_MODE_DEEP, 2 * 60);    
}
void loop() {
}

How about this?

STARTUP(System.enableFeature(FEATURE_RETAINED_MEMORY));
SYSTEM_MODE(SEMI_AUTOMATIC)
SYSTEM_THREAD(ENABLED)            // due to @Ric's comment (see following discussion)

#include "Adafruit_Sensor.h"
#include "Adafruit_BMP280.h"

SerialLogHandler traceLog(LOG_LEVEL_TRACE);

Adafruit_BMP280 bmp; // I2C

const    int   sleepPeriode = 2 * 60; // 2 minutes sleep time
const    int   backLog      = 5;

retained int   contador     = -1;     // The variable we'll use to keep track of where we are in the array
retained int   vtime[backLog];
retained float temp[backLog];
retained float press[backLog];
retained float Abatt[backLog];
retained float Alertfrozen  = 29;

char dest[backLog][128];

void setup()
{
  FuelGauge fuel;                      

  Time.zone(+2);
  bmp.begin();
          
  contador++;
  if (contador >= backLog) contador = 0;

  vtime[contador] = Time.now();
  temp[contador] = bmp.readTemperature();
  press[contador] = bmp.readPressure();
  Abatt[contador] = fuel.getVCell();

  if (temp[contador] >= Alertfrozen)
  {
    Particle.connect();
    if (waitFor(Particle.connected, 60000))
    { // proceede only if a connection could be established within 60 seconds 
      for (int i = 0; i <= contador; i++)
      { // publish backlog 
        snprintf(dest[i], sizeof(dest[i]),
                 "{\"2\":\"%d\",\"10\":\"%.2f\"\"32\":\"%.2f\"\"33\":\"%.2f\"}"
                 , vtime[i]
                 , Abatt[i]
                 , press[i]
                 , temp[i]
                 );
        Log.trace("%d: %s", i, dest[i]);
        Particle.publish("******", dest[i]);
        delay(1000);

        temp[i] = 0;
        press[i] = 0;
        vtime[i] = 0;
        Abatt[i] = 0;
      }
      contador = -1;
    }
  }

  System.sleep(SLEEP_MODE_DEEP, sleepPeriode); //Sleep a while to save battery
}

void loop()
{}

You may want to learn the concept of loops instead of just copy/pasting code blocks that just do the same thing over and over again :wink:
I’d also avoid String objects and rather go with char[] strings.

Don't you also need to be using SYSTEM_THREAD(ENABLED) for this to work, since Particle.connect() will block the code if the device doesn't connect, and the if-statement will never execute. That would result in the device never going into sleep mode if it could not connect to the cloud.

1 Like

I’m pretty sure Particle.connect() is not blocking for the entire connection process. And even if it was, the waitFor() statement would just render redundant but won’t cause any trouble.
If Particle.connect() was hard blocking any non-AUTOMATIC program pre FreeRTOS (SYSTEM_THREAD(ENABLED)) would have been in trouble :wink:

SYSTEM_THREAD(ENABLED) would be a good option nonetheless.

It seemed to be in my tests (at least when not connected to WiFi as well as the cloud). Maybe it eventually times out (I only watched for a few minutes), but I didn't see it. I tested with this code,

SYSTEM_MODE(SEMI_AUTOMATIC);
//SYSTEM_THREAD(ENABLED);

int   sleepPeriod;

void setup() {
    
    Particle.connect();
    
    if (waitFor(Particle.connected, 30000)) { 
        sleepPeriod = 30;
        // do stuff here
    }else{
        sleepPeriod = 15;
    }

    System.sleep(SLEEP_MODE_DEEP, sleepPeriod); 
}


void loop() {}

Run as above, when my Photon was out of range of my router, it never connected (blinking green), and it never went to sleep. If it was in range of the router, the device slept for 30 seconds.

If I uncomment the SYSTEM_THREAD(ENABLED) line, the code worked as I expected; if out of range of the router, the else-clause is entered after 30 seconds, and the device sleeps for 15 seconds.

Maybe not trouble, but the presence of that line gives the false impression that one has taken care of the non-connection problem, when in fact one hasn't. I don't know if the behavior is the same on an Electron, since I've only tested on a Photon.

1 Like

Yup, you are right - I’m flabbergasted :flushed: (So I added the SYSTEM_THREAD(ENABLED) line to the sketch above)

In the past I had done some experiments with Particle.connect() in non-AUTOMATIC modes and was sure it wouldn’t block.
So I tried to backtrack and found that this hard blocking nature of Particle.connect() must have been introduced sometime between 0.6.0 and 0.6.1-rc.1.
When I build the following against 0.6.0 the D7 LED in deed shows, that Particle.connect() is not blocking but leaves immediately.
Granted, the actuall connection process keeps the controller occupied for extended periodes but not inside Particle.connect() otherwise the LED would never come on - but it does even blink several cycles.

SYSTEM_MODE(SEMI_AUTOMATIC);

void setup() 
{
    pinMode(D7, OUTPUT);
    Particle.connect();

    while(1)
    {
      digitalWrite(D7, !digitalRead(D7));
      delay(100);
    }
}

Although this is a Photon, I’d think the Electron should behave likewise.

However, I’d consider this a breaking change since 0.6.0 code that relied on this behaviour will not work reliably anymore with 0.6.1-rc.1+
Also people like myself - who knew the original behaviour - will be scratching their head why perfectly fine code just starts behaving oddly with an alegedly more stable system version (providing you’ll consider this as reason when this creeps up some times after the last update - took me from 0.6.0 till 0.7.0-rc.3 to get bitten by this change).

@rickkas7, would you consider this worth a “regression ticket”? Can you bring this forward with the team?

Hi Guys

I tried your re-code and something is not working,

When I publish the data I received and illogical data when in my script give info correctly.

{“data”:"{“2”:"-1660944384",“10”:"1506429312.00"“32”:“4.08"“33”:“101326.58”}”,“ttl”:60,“published_at”:“2017-09-26T12:36:22.104Z”,“coreid”:“590031001451343334363036”,“name”:“test”}

For example:

the field Time, 2: is the epoch time, but see the value reported is negative and this time is for 2022 year "-1660944384

field 10 has to be 4,15 that is the batt voltage and returns 1506429312.00

field 32 temp is 4.08

and field 34: pressure is 101326.58

Something illogical is doing, no?

thank’s for your incredible help

Thank’s

retained float vtime[5]; is incorrect. Time.now() returns an int, so you need to change that to

retained int vtime[5];

Also, I'm not sure about this,

snprintf(dest[i], sizeof(dest[i]),
                 "{\"2\":\"%d\",\"10\":\"%.2f\"\"32\":\"%.2f\"\"33\":\"%.2f\"}"
                 , vtime[contador]
                 , Abatt[i]
                 , press[i]
                 , temp[i]
                 );

should vtime[contador] be vtime[i]?

My bad - thanks for catching that :thumbsup:

(corrected in above code)

Hi,

I’m still having problems, the electron when I load the firmware the Electron remains sleep forever, never wakeup, you know why?

Thank’s

What code are you currently running?

Hi,

I loaded your corrected code, I saw that reads 2 times and enter sleep for ever

STARTUP(System.enableFeature(FEATURE_RETAINED_MEMORY));
SYSTEM_MODE(SEMI_AUTOMATIC)
SYSTEM_THREAD(ENABLED)            // due to @Ric's comment (see following discussion)

#include "Adafruit_Sensor.h"
#include "Adafruit_BMP280.h"

SerialLogHandler traceLog(LOG_LEVEL_TRACE);

Adafruit_BMP280 bmp; // I2C

const    int   sleepPeriode = 2 * 60; // 2 minutes sleep time
const    int   backLog      = 5;

retained int   contador     = -1;     // The variable we'll use to keep track of where we are in the array
retained int   vtime[backLog];
retained float temp[backLog];
retained float press[backLog];
retained float Abatt[backLog];
retained float Alertfrozen  = 29;

char dest[backLog][128];

void setup()
{
  FuelGauge fuel;                      

  Time.zone(+2);
  bmp.begin();
      
  contador++;
  if (contador >= backLog) contador = 0;

  vtime[contador] = Time.now();
  temp[contador] = bmp.readTemperature();
  press[contador] = bmp.readPressure();
  Abatt[contador] = fuel.getVCell();

  if (temp[contador] >= Alertfrozen)
  {
    Particle.connect();
    if (waitFor(Particle.connected, 60000))
    { // proceede only if a connection could be established within 60 seconds 
      for (int i = 0; i <= contador; i++)
      { // publish backlog 
        snprintf(dest[i], sizeof(dest[i]),
                 "{\"2\":\"%d\",\"10\":\"%.2f\"\"32\":\"%.2f\"\"33\":\"%.2f\"}"
                 , vtime[i]
                 , Abatt[i]
                 , press[i]
                 , temp[i]
                 );
        Log.trace("%d: %s", i, dest[i]);
        Particle.publish("test", dest[i]);
        delay(1000);

        temp[i] = 0;
        press[i] = 0;
        vtime[i] = 0;
        Abatt[i] = 0;
      }
      contador = -1;
    }
  }

  System.sleep(SLEEP_MODE_DEEP, sleepPeriode); //Sleep a while to save battery
}

void loop()
{}

I’m correcting, The electron wake up, but never publish data and register in particle website

Do you get log output via USB Serial?

Since you are working with an Electron you might increase the waitFor() time from 60000 to 300000 and also use

  System.sleep(SLEEP_MODE_DEEP, sleepPeriode, SLEEP_NETWORK_STANDBY); //Sleep a while to save battery

to cut down on reconnection time.

1 Like

Hi @ScruffR
I did the changes and put a battery but the electron still without publishing on counter. Reads but not publish, but when the temperature trigger is on the publish is ok but not when the trigger is off and only "counts"

Thank's

This is an easy fix.

Change

 if (temp[contador] >= Alertfrozen)

to

 if (temp[contador] >= Alertfrozen || contador >= (backlog-1))

Hi @ScruffR

Thank’s!!! now is working perfect!!! thank’s

If you come to Barcelona, you have a Paella waiting you :wink:

Best

Eduard

1 Like