Argon Particle.Publish() issues

Hello,

I have created code that publishes data from 3 digital float sensors. I am getting events published right away when I flash the code to the Argon but when the float sensors position change the variables change as per the code with no issues but it only sometimes publishes events. Can anyone help me with this? Here is my code:

#include "Particle.h"
#define FLOAT_SENSOR  0     // the number of the pushbutton pin
#define FLOAT_SENSOR1  1     // the number of the pushbutton pin
#define FLOAT_SENSOR2  2     // the number of the pushbutton pin
int float_value = 0;


void setup() 
{

  pinMode(FLOAT_SENSOR, INPUT_PULLUP);
  pinMode(FLOAT_SENSOR1, INPUT_PULLUP);
  pinMode(FLOAT_SENSOR2, INPUT_PULLUP);
  Particle.variable("float_value", float_value);

}

void loop() 
{
  if(digitalRead(FLOAT_SENSOR) == LOW && digitalRead(FLOAT_SENSOR1) == LOW && digitalRead(FLOAT_SENSOR2) == LOW)
  {
    float_value = 1;
    String floaty = "Above 80%";
    Particle.connect();
    Particle.publish("Level is", floaty, PUBLIC);
  }
  else if (digitalRead(FLOAT_SENSOR) == HIGH && digitalRead(FLOAT_SENSOR1) == LOW && digitalRead(FLOAT_SENSOR2) == LOW)
  {
    float_value = 2;
    String floaty = "60%";
    Particle.connect();
    Particle.publish("Level is", floaty, PUBLIC);
  }
  else if (digitalRead(FLOAT_SENSOR) == HIGH && digitalRead(FLOAT_SENSOR1) == HIGH && digitalRead(FLOAT_SENSOR2) == LOW)
  {
    float_value = 3;
    String floaty = "40%";
    Particle.connect();
    Particle.publish("Level is", floaty, PUBLIC);
  }
  else if (digitalRead(FLOAT_SENSOR) == HIGH && digitalRead(FLOAT_SENSOR1) == HIGH && digitalRead(FLOAT_SENSOR2) == HIGH)
  {
    float_value = 4;
    String floaty = "Below 20%";
    Particle.connect();
    Particle.publish("Level is", floaty, PUBLIC);
  }
  else
  {  
    float_value = 0;
    String floaty = "Error";
    Particle.connect();
    Particle.publish("Configuration", floaty, PUBLIC);
  }
}
  

Welcome to the community :+1:
We do see such questions on a regular basis and hence chances are quite hight that you would have found the answer to this common problem in muliple places.
Please do search the forum before (re)asking already answered questions.
That’s also what the forum etiquette would urge you to do (have a read).

Additionally the docs for Particle.publish() would also provide the answer

In your code you are not taking any precautions against violating that rate limit and hence your device does most likely get silenced.

BTW, your code is running default SYSTEM_MODE(AUTOMATIC) hence there is no need (and should be avoided) to repeatedly call Particle.connect() when it’s not warranted.

And finally, I don’t think you actually want/should publish as PUBLIC or what other entity would need to see your events?

1 Like

Thanks for the quick reply. I see that I am receiving 4 events each time the code publishes, I guess this is because of the loop it is maxing out at 4? Is there a way to limit this to only 1 publish?

There are multiple ways.
The simplest is to just add a delay(1000) after any given publish.

But what you always should do is to check for a change of state and only act once per change.
This is typically done via a global or local static variable that holds the previous state and on each iteration of loop() you compare the current state with the previously stored value and just don’t do anything when both are still the same.

In order to make your comparison easier - and use a switch() instead of multiple if() you may want to hold all your sensor states in one single variable
e.g.

int prevState = 0;

void loop() {
  char floaty[16];
  int  currState = digitalRead(FLOAT_SENSOR0) << 0
                 | digitalRead(FLOAT_SENSOR1) << 1
                 | digitalRead(FLOAT_SENSOR2) << 2;

  if (currState == prevState) return; // no change, no action

  switch(currState) {
    case 0b000:
      float_value = 1;
      strcpy(floaty, "Above 80%");
      break;

    case 0b001:
      float_value = 2;
      strcpy(floaty, "60%");
      break;

    case 0b011:
      float_value = 3;
      strcpy(floaty, "40%");
      break;

    case 0b111:
      float_value = 4;
      strcpy(floaty, "Below 20%");
      break;

    default:
      float_value = 0;
      snprintf(floaty, sizeof(floaty), "Error (%d)", currState);
      break;      
  }
  Particle.publish("Level", floaty, PRIVATE);
  delay(1000);
  prevState = currState;
}

I’d actually use arrays for the messages, an enum for the states and get rid of float_value since prevState already tells me what I need to know outside of loop().

1 Like

Thank you very much for the insight ScruffR!!

Hi ScruffR,

I know this is off-topic but I’m stuck here and need some help with the code. I am trying to create an array in order to give each sensor a position so that I can create error scenarios whereby if a lower sensor is not floating and a higher sensor is floating it will produce an error. I tried to use a switch statement but cannot be done with arrays. Here is what I came up with but need some guidance:

#include "Particle.h"
#define FLOAT_SENSOR0  0     // the number of the pushbutton pin
#define FLOAT_SENSOR1  1     // the number of the pushbutton pin
#define FLOAT_SENSOR2  2     // the number of the pushbutton pin
int prevState[3] = {2,2,2};
int float_value = 0;

void setup() 
{
  pinMode(FLOAT_SENSOR0, INPUT_PULLUP); // initiate the sensor
  pinMode(FLOAT_SENSOR1, INPUT_PULLUP);
  pinMode(FLOAT_SENSOR2, INPUT_PULLUP);
  Particle.variable("float_value", float_value);
  int currState[3]; 
  currState[0] = digitalRead(FLOAT_SENSOR0);
  currState[1] = digitalRead(FLOAT_SENSOR1);
  currState[2] = digitalRead(FLOAT_SENSOR2);
}

void loop()
{
  if (prevState = currState){
    return;
    }
  if (currState = {1,1,1}){
    float_value = 4;
    Particle.publish("Level is above 80%", PRIVATE);
    return;
    }
  if (currState = {0,1,1}){
    float_value = 3;
    Particle.publish("Level is around 60%", PRIVATE);
    return;
    }
  if (currState = {0,0,1}){
    float_value = 1;
    Particle.publish("Level is around 35%", PRIVATE);
    return;
    }
  if (currState = {0,0,0}){
    float_value = 1;
    Particle.publish("Level is below 20%", PRIVATE);
    return;
    }
  if (currState = {1,0,0}){
    float_value = 0;
    Particle.publish("Error Float 1", PRIVATE);
    return;
    }
  if (currState = {1,0,1}){
    float_value = 0;
    Particle.publish("Error Float 2", PRIVATE);
    return;
    }
  if (currState = {0,1,0}){
    float_value = 0;
    Particle.publish("Error Float 1 and 3", PRIVATE);
    return;
    }
  if (currState = {1,1,0}){
    float_value = 0;
    Particle.publish("Error Float 3", PRIVATE);
    return;
    }
  delay(1000);
  prevState[0] = currState[0];
  prevState[1] = currState[1];
  prevState[2] = currState[2];
 }

you are assigning new value to currState on each “if”:

instead to compare them. Try to change them like this:

if (currState == {1,1,1}){

edit:
also looks like your sensors are not assigned to any digital pins

#define FLOAT_SENSOR0 0 // the number of the pushbutton pin
#define FLOAT_SENSOR1 1 // the number of the pushbutton pin
#define FLOAT_SENSOR2 2 // the number of the pushbutton pin

try to assign a pin to each sensor eg:

#define FLOAT_SENSOR0 D0 // the number of the pin
#define FLOAT_SENSOR1 D1 // the number of the pin
#define FLOAT_SENSOR2 D2 // the number of the pin

Thanks I corrected that for all if statements.

However, I am getting an error that currState is undefined, eventhough I defined it in void setup()?

no you did not defined “currState” as global just locally in setup and in this case you just assigned some values to not defined array
try to move “currState[3]” from your setup to make “currState[3]” global:

int prevState[3] = {2,2,2};
int currState[3] = {0,0,0};
int float_value = 0;

Now the only issue is the if statement. It is giving an “expected an expression” error for the if statements something like if(currState == {1,1,1}) is not allowed. I don’t think I can call upon an array like this in an if statement.

You have absolutely right ! sorry :slight_smile:
try this:

#include "Particle.h"
#define FLOAT_SENSOR0  D1     // the number of the pushbutton pin
#define FLOAT_SENSOR1  D2     // the number of the pushbutton pin
#define FLOAT_SENSOR2  D3    // the number of the pushbutton pin
int prevState[3] = {2,2,2};
int currState[3] = {0,0,0};
int float_value = 0;

void setup() 
{
  pinMode(FLOAT_SENSOR0, INPUT_PULLUP); // initiate the sensor
  pinMode(FLOAT_SENSOR1, INPUT_PULLUP);
  pinMode(FLOAT_SENSOR2, INPUT_PULLUP);
  Particle.variable("float_value", float_value);
   
  currState[0] = digitalRead(FLOAT_SENSOR0);
  currState[1] = digitalRead(FLOAT_SENSOR1);
  currState[2] = digitalRead(FLOAT_SENSOR2);
}

void get_sensors(){
  currState[0] = digitalRead(FLOAT_SENSOR0);
  currState[1] = digitalRead(FLOAT_SENSOR1);
  currState[2] = digitalRead(FLOAT_SENSOR2);   
}

void loop()
{
 
 get_sensors();

  if (((prevState[0] == currState[0])&&(prevState[1] == currState[1])&&(prevState[2] == currState[2]))){
    return;
    }
  if (((currState[0] == 1)&&(currState[1] == 1)&&(currState[2] == 1))){
    float_value = 4;
    Particle.publish("Level is above 80%", PRIVATE);
    return;
    }
  if (((currState[0] == 0)&&(currState[1] == 1)&&(currState[2] == 1))){
    float_value = 3;
    Particle.publish("Level is around 60%", PRIVATE);
    return;
    }
  if (((currState[0] == 0)&&(currState[1] == 0)&&(currState[2] == 1))){
    float_value = 1; 
    Particle.publish("Level is around 35%", PRIVATE);
    return;
    }
  if (((currState[0] == 0)&&(currState[1] == 0)&&(currState[2] == 0))){
    float_value = 1;
    Particle.publish("Level is below 20%", PRIVATE);
    return;
    }
  if(((currState[0] == 1)&&(currState[1 ] == 0)&&(currState[2] == 0))){
    float_value = 0;
    Particle.publish("Error Float 1", PRIVATE);
    return;
    }
  if (((currState[0] == 1)&&(currState[1] == 0)&&(currState[2] == 1))){
    float_value = 0;
    Particle.publish("Error Float 2", PRIVATE);
    return;
    }
  if (((currState[0] == 0)&&(currState[1] == 1)&&(currState[2] == 0))){
    float_value = 0; 
    Particle.publish("Error Float 1 and 3", PRIVATE);
    return;
    }
  if (((currState[0] == 1)&&(currState[1] == 1)&&(currState[2] == 0))){
    float_value = 0;
    Particle.publish("Error Float 3", PRIVATE);
    return;
    }
  delay(1000);
  prevState[0] = currState[0];
  prevState[1] = currState[1];
  prevState[2] = currState[2];
 }

pin D1 is assigned for sensor 1, D2 for sensor 2 and D3 for sensor 3

EDIT:

also you are using “PULLUP” on each pins make sure that your float sensors are using NC (normal close) contacts and the second “terminal” of your float sensors has to be connected to Argon GND

A union with a bit field or a binary combination of the states would make for a much neater code as it would allow for a switch case instead of all these if ... else if conditions :wink: