Photon blinking red when i dont write in the console

Hi

I have written code to read a dht22 sensor, a pms5003 sensor and send that data to a mosquitto broker in home assistant. To do my tests and see the data, i was writing the output of the pms5003 sensor in the console via particle.publish. The code works fine.

I dont need that publish code anymore, so i tried to remove the particle publish step. But, when i do this, after flashing the code, the photon briefly blinks cyan and then starts to blink red 10 times, until it gets restarted.

This is the code

// This #include statement was automatically added by the Particle IDE.
#include <MQTT.h>
#include "DustSensor.h"

#include <PietteTech_DHT.h>


#define DHTTYPE  DHT22
#define DHTPIN   D4

DustSensor dustSensor;
PietteTech_DHT DHT(DHTPIN, DHTTYPE);

double serverTemp;
double serverHumidity;
static char humidity[4];
static char temperature[4];
char resultstr[128];
pms5003data data;

void callback(char* topic, byte* payload, unsigned int length);
  MQTT client("192.168.1.12", 1883, callback);   


void callback(char* topic, byte* payload, unsigned int length) {
    char p[length + 1];
    memcpy(p, payload, length);
    p[length] = NULL;
}

void setup()
{
    dustSensor.begin();
  Particle.variable("result", resultstr, STRING);

}

void send_dht22_data() {
  int result = DHT.acquireAndWait(2000);
  
  serverTemp = DHT.getCelsius();
  serverHumidity = DHT.getHumidity();

     sprintf(temperature, "%2.1f", serverTemp);
     sprintf(humidity, "%2.1f", serverHumidity);
  client.connect("photon", "XXX", "XXX");
    if (client.isConnected()) {
    client.publish("temperature",temperature);
    client.publish("humidity",humidity);

    } 
}

void send_pms5003_data() {
    if(dustSensor.listen()) {

        data = dustSensor.readData();
        sprintf(resultstr, "{\"pm10\":%i,\"pm25\":%i,\"pm100\":%i,\"checksum\":%i}", data.pm10_standard, data.pm25_standard, data.pm100_standard, data.checksum);
        Particle.publish("reading", resultstr);
    client.connect("photon", "XXX", "XXX");
    if (client.isConnected()) {
        client.publish("pm10",String(data.pm10_standard));
        client.publish("pm25",String(data.pm25_standard));
        client.publish("pm100",String(data.pm100_standard));

    } 
        } 
}

void loop()
{
    send_dht22_data();
    send_pms5003_data();
   
 
  delay(100);
}

What i try to remove is
Particle.publish(“reading”, resultstr);

Any idea why i cant remove it? What can i do to start publishing in the console?
Thanks

This is deprecated syntax. By now this will be enought

  Particle.variable("result", resultstr);

It would also be better to use snprintf() to limit the size of your result strings.
Your char temperature[4] seems too short for any readings like 12.3 degrees - let alone negative temperatures. With an array of four characters you can only store a string of up to 3 characters as you need to have a '\0' zero terminator.
The same goes for humidity.

The potential for dealing with not correctly terminated strings may explain your SOS panic crashes.

The static qualifier for these two arrays is also superfluous.

I'd also unify the publishes (MQTT or Particle) into one single string to reduce overhead.

As for MQTT:
In send_pms5003_data() and send_dht22_data() you check for if(client.isConnected()) but you don't rectify that problem once detected. You just ignore it and have the device not publish anything for till the end of time.

BTW, it would make somewhat more sense if you had one function that does all the publishing, and two independent functions that do the reading of the individual sensors.

With splitting your logic up into dedicated functions you want to reduce redundancy, but with your functions you have both deal with the MQTT stuff and when you need to change anything on that logic (i.e. add the reconnect logic when client.isConnected == false) you'd do that twice for the sake of consistency. With only one publish function you'd have it both: minimal effort but consistent.

Thanks for the code review :slight_smile:

All the considerations are good, those make sense, apart from humidity and temp not being negatives, and the format. Those sensors are inside the house. If it goes below zero inside the house, i have a bigger problem… Also i want it to show just 1 decimal number, eg 19.8.

It makes sense what you mention about terminating the string, but, why does it work when publishing something in the console and gives a SOS panic when i dont publish?

The bottom line is, i dont want to publish anything in the console anymore, but, if i remove that publish command, then, i have the error

So, what can i do to avoid publishing in the console (it is, remove the publish command) and not have the red blink of death

Thanks

As I said four characters will not fit into your array and there you have four.
The potential for negatives may not be there in real life but since you don't check whether the sensor provides valid data via the result you can never be certain to not get a negative reading or a reading > 99.9°C. Hence it does make sense to point out the fact.
A programmer has to expect the unexpected, even the impossible has to be considered!

Hard to tell, but one possibility is that the corrupting call affects some memory location which the Particle.publish() call doesn't care about and may even rectify by being called (especially the state of the stack springs to mind).
When removing that call, the subsequent call may not be as resilient and crash.

While I could come up with several other possible explanations, there is little use in doing so, as it doesn't matter. Erroneous code needs to be corrected in any case, no matter why it crashes. It even needs correcting when it doesn't crash at all.

And I have suggested what to do :wink:

  • use snprintf()
  • address the too small buffer problem

While at it, incorporate the other suggestions to adopt better coding practices.


This would be my take on this
#include <MQTT.h>
#include <PietteTech_DHT.h>
#include <DustSensor.h>

const char      mqttADDR[]  = "192.168.1.12";
const char      mqttTOPIC[] = "photon";
const char      mqttUSER[]  = "User";
const char      mqttPWD[]   = "Pwd";
const char      mqttINFO[]  = "environment";
const int       dhtTYPE     = DHT22;
const int       dhtPIN      = D4;
const uint32_t  msDELAY     = 100;

float           temp;                   // temperature in [°C]
float           hum;                    // relative humidity in [%]
char            envData[128];           // string for Particle.variable and MQTT publish

pms5003data     pmsData;

MQTT            client(mqttADDR, 1883, [](char* topic, byte* payload, unsigned int length) {});  // don't care to receive data (empty lambda)
PietteTech_DHT  DHT(dhtPIN, dhtTYPE);
DustSensor      dustSensor;

void setup() {
  dustSensor.begin();
  Particle.variable(mqttINFO, envData);
  client.connect(mqttTOPIC, mqttUSER, mqttPWD);
}

void loop() {
  static uint32_t ms = 0;
  if (millis() - ms < msDELAY) return;
  ms = millis();
  
  readDHT();
  readPMS5003();
  publishData();
}

int readDHT() {
  int result = DHT.acquireAndWait(2000);
  if (result >= DHTLIB_OK) {
    temp = DHT.getCelsius();
    hum = DHT.getHumidity();
    result = DHTLIB_OK;
  }
  return result;
}

int readPMS5003() {
  if(dustSensor.listen()) {
    pmsData = dustSensor.readData();
    return 0;
  }
  return -1;
}

void publishData() {
  snprintf(envData, sizeof(envData)
          , "{ \"temp\": %.1f, \"rh\": %.1f, \"pm10\": %u, \"pm25\": %u, \"pm100\": %u }"
          , temp
          , hum
          , pmsData.pm10_standard
          , pmsData.pm25_standard
          , pmsData.pm100_standard
          );
  if (client.isConnected()) {
    client.publish(mqttINFO, envData);
  }
  else {
    client.connect(mqttTOPIC, mqttUSER, mqttPWD);
  }
}
1 Like

Thanks. I dont need the sprintf() anymore so i got rid of it completely and also with the arrays. All fine now

Thanks!

1 Like

This topic was automatically closed 30 days after the last reply. New replies are no longer allowed.