bertmelis / SDS011

Non blocking SDS011 sensor library for ESP8266
MIT License
15 stars 8 forks source link

Can't compile on ESP32 with hardware serial 2 #9

Closed esp13 closed 2 months ago

esp13 commented 2 months ago

Hi,

I wanted to give a try with your non blocking library, But I can't successfully compile it with arduino IDE 2.3.2. The board I use is a ESP32 developpement board with 38 yellow pins https://arduino-projekte.info/wp-content/uploads/2021/08/Node_MCU_ESP32_38Pin_pinout.webp https://raw.githubusercontent.com/AchimPieters/esp32-homekit-camera/master/Images/ESP32-38%20PIN-DEVBOARD.png

I cloned the library this way:

cd Arduino/libraries
git clone https://github.com/bertmelis/SDS011.git

I modified the example this way:

#include <HardwareSerial.h>
#include <SDS011.h>//librairie clonee manuellement 1.0.0 du 14/09/2018 mais fichiers plus récents https://github.com/bertmelis/SDS011

#define RXD2 16
#define TXD2 17

HardwareSerial usbSerial(0);
HardwareSerial sds011Serial(2);
//HardwareSerial sds011Serial(Serial2);

SDS011 sds011;

void setup() {
  usbSerial.begin(115200);
  //Serial2.begin(9600, SERIAL_8N1, RXD2, TXD2);//SDS011

  sds011.setup(&sds011Serial, RXD2, TXD2);  // Rx on GPIO14; Tx on GPIO12
  //sds011.setup(&Serial2, RXD2, TXD2);  // Rx on GPIO14; Tx on GPIO12

  sds011.onData([](float pm25Value, float pm10Value) {
    usbSerial.println("Data arrived: PM2.5 = " + String(pm25Value, 1) + " μg/m³; PM10 = " + String(pm10Value, 1) + " μg/m³");
  });

  sds011.onResponse([](uint8_t command, uint8_t set, uint8_t result) {
    usbSerial.println("Response to command 0x" + String(command, HEX) + " received: 0x" + String(result, HEX));
  });

  sds011.onError([](int8_t error) {
    usbSerial.println("Error occurred: 0x" + String(error, HEX));
  });

  sds011.setWorkingPeriod(1);
  usbSerial.println("Data should appear on the default serial port in less than a minute");
}

void loop() {
  sds011.loop();
}

But I get this error:

WARNING: library SDS011 claims to run on esp8266 architecture(s) and may be incompatible with your current board which runs on esp32 architecture(s).
Arduino/libraries/SDS011/src/SDS011.cpp: In member function 'void SDS011::setup(HardwareSerial*, uint8_t, uint8_t)':
Arduino/libraries/SDS011/src/SDS011.cpp:58:12: error: 'class Stream' has no member named 'begin'
   _serial->begin(9600, SERIAL_8N1, rx_pin, tx_pin);
            ^~~~~

exit status 1

Compilation error: exit status 1

I previously could use my sds011 with this other library https://github.com/lewapek/sds-dust-sensors-arduino-library/tree/master with this code:

#include "SdsDustSensor.h" //Nova Fitness Sds dust sensors library by Paweł Kołodziejczyk 1.5.1 du 14/02/2022 https://github.com/lewapek/sds-dust-sensors-arduino-library/tree/master

// tested on Arduino Leonardo with Serial1
SdsDustSensor sds(Serial2); // passing HardwareSerial& as parameter
#define RXD2 16
#define TXD2 17

void setup() {
  Serial.begin(115200);
  Serial2.begin(9600, SERIAL_8N1, RXD2, TXD2);//SDS011
  sds.begin(9600); // this line will begin Serial1 with given baud rate (9600 by default)

  Serial.println(sds.queryFirmwareVersion().toString()); // prints firmware version
  Serial.println(sds.setQueryReportingMode().toString()); // ensures sensor is in 'query' reporting mode
}

void loop() {
  sds.wakeup();
  delay(10000); // working 30 seconds

  PmResult pm = sds.queryPm();
  if (pm.isOk()) {
    //Serial.print("PM2.5 = ");
    //Serial.print(pm.pm25);
    //Serial.print(", PM10 = ");
    //Serial.println(pm.pm10);

    // if you want to just print the measured values, you can use toString() method as well
    Serial.println(pm.toString());
  } else {
    Serial.print("Could not read values from sensor, reason: ");
    Serial.println(pm.statusToString());
  }

  WorkingStateResult state = sds.sleep();
  if (state.isWorking()) {
    Serial.println("Problem with sleeping the sensor.");
  } else {
    Serial.println("Sensor is sleeping");
    delay(10000); // wait 1 minute
  }
}

Could you please help me to find what I am missing?

bertmelis commented 2 months ago

The cast to HardwareSerial was missing. I think it is fixed now.

esp13 commented 2 months ago

Thank you :)

Now it compiles but I don't get measurements I only get this:

Data should appear on the default serial port in less than a minute
Response to command 0x8 received: 0x1

And the fan start and stop periodically. Maybe I'm just missing the display of measurements

bertmelis commented 2 months ago

So, does the fan run periodically?

It's been a long time since I made this and the Arduino core for ESP32 has changed significally.

try this:

#include <HardwareSerial.h>
#include <SDS011.h>//librairie clonee manuellement 1.0.0 du 14/09/2018 mais fichiers plus récents https://github.com/bertmelis/SDS011

#define RXD2 16
#define TXD2 17

HardwareSerial usbSerial(0);

SDS011 sds011;

void setup() {
  usbSerial.begin(115200);
  sds011.setup(&Serial2, RXD2, TXD2);  // Rx on GPIO14; Tx on GPIO12
 ...

Now what I don't understand is that the sensor does respond to the command but afterwards doesn't seem to send any data. I have to test this myself...

esp13 commented 2 months ago

So, does the fan run periodically?

~~First this was what I thought but after some more tests it is always running. I don't know if something has changed or if I have done a mistake.~~ Edit: Yes : I had accidentally replaced the period with 0 while playing with port numbers I think which caused the fan to run non stop.

It's been a long time since I made this and the Arduino core for ESP32 has changed significally.

try this:

#include <HardwareSerial.h>
#include <SDS011.h>//librairie clonee manuellement 1.0.0 du 14/09/2018 mais fichiers plus récents https://github.com/bertmelis/SDS011

#define RXD2 16
#define TXD2 17

HardwareSerial usbSerial(0);

SDS011 sds011;

void setup() {
  usbSerial.begin(115200);
  sds011.setup(&Serial2, RXD2, TXD2);  // Rx on GPIO14; Tx on GPIO12
 ...

I tested it but still can't get the measurements. The output is now:

Data should appear on the default serial port in less than a minute
Response to command 0x8 received: 0x0

Notice the previous 0x1 answer that now is always 0x0 !?

Now what I don't understand is that the sensor does respond to the command but afterwards doesn't seem to send any data. I have to test this myself...

If I disconnect TX / RX (or invert it) I don't get this answer anymore: Response to command 0x8 received: 0x0 So I guess communication is working at first at least

bertmelis commented 2 months ago

Make sure you setup the sensor completely. Some settings are preserved after poweroff. Maybe yours is set up differently:

active report mode, 1-30 working period

  void setReportMode(bool mode);  // false: active, true: query
  void setWorkingPeriod(uint8_t period);  // period in minutes: work 30 seconds, sleep period*60 - 30 seconds

Also, rewrite to avoid the function objects. (bad example in the repo).

#include <Arduino.h>
#include <SDS011.h>

#define RXD2 16
#define TXD2 17

HardwareSerial usbSerial(0);

SDS011 sds011;

void onSensorData(float pm25Value, float pm10Value) {
  usbSerial.println("Data arrived: PM2.5 = " + String(pm25Value, 1) + " μg/m³; PM10 = " + String(pm10Value, 1) + " μg/m³");
}

void onSensorResponse(uint8_t command, uint8_t set, uint8_t result) {
  usbSerial.println("Response to command 0x" + String(command, HEX) + " received: 0x" + String(result, HEX));
}

void onSensorError(int8_t error) {
  usbSerial.println("Error occurred: 0x" + String(error, HEX));
}

void setup() {
  usbSerial.begin(115200);
  sds011.setup(&Serial2, RXD2, TXD2);  // Rx on GPIO14; Tx on GPIO12

  sds011.onData(onSensorData);
  sds011.onResponse(onSensorResponse);
  sds011.onError(onSensorError);

  sds011.setWorkingPeriod(1);
  usbSerial.println("Data should appear on the default serial port in less than a minute");
}

void loop() {
  sds011.loop();
}
esp13 commented 2 months ago

Make sure you setup the sensor completely. Some settings are preserved after poweroff. Maybe yours is set up differently:

active report mode, 1-30 working period

  void setReportMode(bool mode);  // false: active, true: query
  void setWorkingPeriod(uint8_t period);  // period in minutes: work 30 seconds, sleep period*60 - 30 seconds

Thank you :) this was what I was missing it works now like a charm :) Maybe this should be added in the readme / examples?

  sds011.setReportMode(false);  // false: active, true: query
  sds011.setWorkingMode(true);  // false: sleep, true, work

The fan first alternating then always running was due to the period accidentally set to 0... I guess when I tried to edit port number I accidentally replaced it instead of port number... I think the issue can be closed.


I go with this, does it seems the good way?

//#include <HardwareSerial.h>
#include <SDS011.h>//librairie clonee manuellement 1.0.0 du 14/09/2018 mais fichiers plus récents https://github.com/bertmelis/SDS011

#define RXD2 16
#define TXD2 17

//HardwareSerial usbSerial(0);
//HardwareSerial sds011Serial(2);
//HardwareSerial sds011Serial(Serial2);

SDS011 sds011;

void onSensorData(float pm25Value, float pm10Value) {
  //usbSerial.println("Data arrived: PM2.5 = " + String(pm25Value, 1) + " μg/m³; PM10 = " + String(pm10Value, 1) + " μg/m³");
  Serial.println("Data arrived: PM2.5 = " + String(pm25Value, 1) + " μg/m³; PM10 = " + String(pm10Value, 1) + " μg/m³");
}

void onSensorResponse(uint8_t command, uint8_t set, uint8_t result) {
  //usbSerial.println("Response to command 0x" + String(command, HEX) + " received: 0x" + String(result, HEX));
  Serial.println("Response to command 0x" + String(command, HEX) + " received: 0x" + String(result, HEX));
}

void onSensorError(int8_t error) {
  //usbSerial.println("Error occurred: 0x" + String(error, HEX));
  Serial.println("Error occurred: 0x" + String(error, HEX));
}

void setup() {
  //usbSerial.begin(115200);
  Serial.begin(115200);
  //Serial2.begin(9600, SERIAL_8N1, RXD2, TXD2);//SDS011

  //sds011.setup(&sds011Serial, RXD2, TXD2);  // Rx on GPIO14; Tx on GPIO12
  sds011.setup(&Serial2, RXD2, TXD2);
  sds011.setReportMode(false);  // false: active, true: query
  sds011.setWorkingMode(true);  // false: sleep, true, work
  sds011.setWorkingPeriod(5);

  sds011.onData(onSensorData);
  sds011.onResponse(onSensorResponse);
  sds011.onError(onSensorError);

  /*
  sds011.onData([](float pm25Value, float pm10Value) {
    //usbSerial.println("Data arrived: PM2.5 = " + String(pm25Value, 1) + " μg/m³; PM10 = " + String(pm10Value, 1) + " μg/m³");
    Serial.println("Data arrived: PM2.5 = " + String(pm25Value, 1) + " μg/m³; PM10 = " + String(pm10Value, 1) + " μg/m³");
  });
  */

  /*
  sds011.onResponse([](uint8_t command, uint8_t set, uint8_t result) {
    //usbSerial.println("Response to command 0x" + String(command, HEX) + " received: 0x" + String(result, HEX));
    Serial.println("Response to command 0x" + String(command, HEX) + " received: 0x" + String(result, HEX));
  });
  */

  /*
  sds011.onError([](int8_t error) {
    //usbSerial.println("Error occurred: 0x" + String(error, HEX));
    Serial.println("Error occurred: 0x" + String(error, HEX));
  });
  */

  //usbSerial.println("Data should appear on the default serial port in less than 5 minute");
  Serial.println("Data should appear on the default serial port in less than 5 minutes");
}

void loop() {
  sds011.loop();
}

While searching I found that you have a non blocking mqtt library too: https://github.com/bertmelis/espMqttClient As I'm having some issues with my tries to get wifi / mqtt non blocking usage, I will try yours, so thank you for your work! :)

I found this one too https://github.com/HamzaHajeir/H4AsyncMQTT but looks a lot more complex.

bertmelis commented 2 months ago

your solution seems the right way.

And yes, I can only recommend my MQTT lib 😄 .

esp13 commented 2 months ago

And yes, I can only recommend my MQTT lib 😄 .

This libraries requires AsyncTCP and ESPAsnycTCP. These libraries are not actively maintained and have some bugs. There are alternatives available on Github but make sure these alternatives fit in your project.

Because of this, I have removed the explicit dependency. You will have to manually add the libraries so you can choose the version which best suites your code.

Quelles librairies utilises tu du coup? Toujours celles citées mais plus maintenues ou de plus récentes?

Côté https://github.com/khoih-prog/AsyncMQTT_Generic ils semblent utiliser https://github.com/khoih-prog/ESPAsyncTCP qui semble pourtant avoir été archivée?

The new ESP8266 cores v3.0.2+ introduces many new breaking features, such as replacing axtls with bearssl, as well as good ones such as LwIP Ethernet W5500lwIP, W5100lwIP and ENC28J60lwIP libraries.

Because the original ESPAsyncTCP library is not well maintained to cope with dynamic environment of new cores, features, etc., this forked ESPAsyncTCP library is created as an effort to try the best to keep up with the fast changes and avoid compile errors in future cores or dependent libraries.

Hopefully the bearssl feature of new ESP8266 cores will be added to this library in the near future to support SSL.


PS: Si un jour tu fais une librairie non bloquante pour le capteur MH-Z19 qui communique également sur un port série, ce serait cool d'avoir les deux qui puissent être interrogés sur la même ligne TX/RX ;)