ESP32-C3 Super Mini tx rx not working with sda/scl

Hi,
I am using ESP32-C3 super mini to receive data from a pressure sensor (using sda/scl on pins 9/10) and an air quality sensor (using rx/tx on pins 3/2). I only get data from the sda/scl and not from rx/tx. When i omit the code for sda/scl i start getting data from the tx/rx. Earlier with ESP32-Wroom32 i used to get both the data without any trouble. I have tried the 5v for rx/tx and 3.3v for sda/scl but that does not solve my problem on ESP32-C3. Please help

#include <XGZP6897D.h>

#define K 8192 // see table above for the correct value for your sensor, according to the sensitivity.
XGZP6897D mysensor(K);
float pressure, temperature;

#include <SoftwareSerial.h>
SoftwareSerial pmsSerial(3, 2);
 
void setup() {
  // our debugging output
  Serial.begin(115200);
   // sensor baud rate is 9600
  pmsSerial.begin(9600);
  
  while (!mysensor.begin())  // initialize and check the device
  {
    Serial.println("Device not responding.");
    delay(500);
  }
  
}
 
struct pms5003data {
  uint16_t framelen;
  uint16_t pm10_standard, pm25_standard, pm100_standard;
  uint16_t pm10_env, pm25_env, pm100_env;
  uint16_t particles_03um, particles_05um, particles_10um, particles_25um, particles_50um, particles_100um;
  uint16_t unused;
  uint16_t checksum;
};
 
struct pms5003data data;
    
void loop() {
  if (readPMSdata(&pmsSerial)) {
    Serial.println(data.pm10_standard);
    Serial.println(data.pm25_standard);
    Serial.println(data.pm100_standard);
    Serial.println(data.particles_03um);                                                                
    Serial.println(data.particles_05um);
    Serial.println(data.particles_10um);
    Serial.println(data.particles_25um);
    Serial.println(data.particles_50um);
    Serial.println(data.particles_100um);

  }

     if (mysensor.readSensor(temperature, pressure))
      {
          Serial.println(temperature);
          Serial.println(pressure); 
          Serial.println();
        }
        else Serial.println("Reading fails. Timeout ??");
        delay(10);

}

 
boolean readPMSdata(Stream *s) {
  if (! s->available()) {
    return false;
  }
  
  // Read a byte at a time until we get to the special '0x42' start-byte
  if (s->peek() != 0x42) {
    s->read();
    return false;
  }
 
  // Now read all 32 bytes
  if (s->available() < 32) {
    return false;
  }
    
  uint8_t buffer[32];    
  uint16_t sum = 0;
  s->readBytes(buffer, 32);
 
  // get checksum ready
  for (uint8_t i=0; i<30; i++) {
    sum += buffer[i];
  }
 
  /* debugging
  for (uint8_t i=2; i<32; i++) {
    Serial.print("0x"); Serial.print(buffer[i], HEX); Serial.print(", ");
  }
  Serial.println();
  */
  
  // The data comes in endian'd, this solves it so it works on all platforms
  uint16_t buffer_u16[15];
  for (uint8_t i=0; i<15; i++) {
    buffer_u16[i] = buffer[2 + i*2 + 1];
    buffer_u16[i] += (buffer[2 + i*2] << 8);
  }
 
  // put it into a nice struct :)
  memcpy((void *)&data, (void *)buffer_u16, 30);
 
  if (sum != data.checksum) {
    Serial.println("Checksum failure");
    return false;
  }
  // success!
  return true;
}

I don't think I can tell you what the problem is, but the supermini has a second hardware serial at pins 20/21, so why use Softwareserial?

thanks. for sda/scl i need to use sofwareserial. I tried many alternates but doesnt help.

I don't follow your reasoning...
SDA/SCL are typical on I2C protocol. Softwareserial simulates a UART (Rx/Tx) on pins that are not hardware serial. Hence SDA/SCL has nothing to do with softwareserial :thinking:

Can you give links to the sensors that you actually have and provide a schematic of your setup?

Sorry, my mistake. As can be seen from the the code I need to use software serial for rx/tx from the air quality sensor. I use I2C scl/sda for pressure sensor data.

air quality PMS5003 Series Manual Datasheet by Adafruit Industries LLC | Digi-Key Electronics
pressure sensor
https://cfsensor.com/product/i2c-differential-pressure-sensor-xgzp6897d/

Ok, try this version:
(both your sensors work at 3.3V, don't try them at 5V)

#include <XGZP6897D.h>

#define K 8192 // see table above for the correct value for your sensor, according to the sensitivity.
XGZP6897D mysensor(K);
float pressure, temperature;

//#include <SoftwareSerial.h>
//SoftwareSerial pmsSerial(3, 2);
#define RXD1 3
#define TXD1 2

 
void setup() {
  // our debugging output
  Serial.begin(115200);
   // sensor baud rate is 9600
  //pmsSerial.begin(9600);
  Serial1.begin(9600, SERIAL_8N1, RXD1, TXD1);

  
  while (!mysensor.begin())  // initialize and check the device
  {
    Serial.println("Device not responding.");
    delay(500);
  }
  
}
 
struct pms5003data {
  uint16_t framelen;
  uint16_t pm10_standard, pm25_standard, pm100_standard;
  uint16_t pm10_env, pm25_env, pm100_env;
  uint16_t particles_03um, particles_05um, particles_10um, particles_25um, particles_50um, particles_100um;
  uint16_t unused;
  uint16_t checksum;
};
 
struct pms5003data data;
    
void loop() {
  if (readPMSdata(&Serial1)) {
    Serial.println(data.pm10_standard);
    Serial.println(data.pm25_standard);
    Serial.println(data.pm100_standard);
    Serial.println(data.particles_03um);                                                                
    Serial.println(data.particles_05um);
    Serial.println(data.particles_10um);
    Serial.println(data.particles_25um);
    Serial.println(data.particles_50um);
    Serial.println(data.particles_100um);

  }

     if (mysensor.readSensor(temperature, pressure))
      {
          Serial.println(temperature);
          Serial.println(pressure); 
          Serial.println();
        }
        else Serial.println("Reading fails. Timeout ??");
        delay(10);

}

 
boolean readPMSdata(Stream *s) {
  if (! s->available()) {
    return false;
  }
  
  // Read a byte at a time until we get to the special '0x42' start-byte
  if (s->peek() != 0x42) {
    s->read();
    return false;
  }
 
  // Now read all 32 bytes
  if (s->available() < 32) {
    return false;
  }
    
  uint8_t buffer[32];    
  uint16_t sum = 0;
  s->readBytes(buffer, 32);
 
  // get checksum ready
  for (uint8_t i=0; i<30; i++) {
    sum += buffer[i];
  }
 
  /* debugging
  for (uint8_t i=2; i<32; i++) {
    Serial.print("0x"); Serial.print(buffer[i], HEX); Serial.print(", ");
  }
  Serial.println();
  */
  
  // The data comes in endian'd, this solves it so it works on all platforms
  uint16_t buffer_u16[15];
  for (uint8_t i=0; i<15; i++) {
    buffer_u16[i] = buffer[2 + i*2 + 1];
    buffer_u16[i] += (buffer[2 + i*2] << 8);
  }
 
  // put it into a nice struct :)
  memcpy((void *)&data, (void *)buffer_u16, 30);
 
  if (sum != data.checksum) {
    Serial.println("Checksum failure");
    return false;
  }
  // success!
  return true;
}

Thanks for the help Brazilino. I tried your code on ESP32 Wroom. The pins are as follows
GPIO22 SCL (yours RXD13) ---Pressure sensor pin SCL
GPIO 21 SDA (yours RXD11)--Pressure sensor pin SDA
GPIO1 TX0 -- (not declared in code) -- PMS5003 Sensor pin RX
GPIO3 RX0 (not declared in code) -- PMS5003 Sensor pin TX

So the only change i made in your code was RXD1 to 3 is now 22 and TXD1 2 is now 21.

This gives me the pressure sensor data and not the PMS5003 data . If i change pins from 22/21 to 3/1 i dont get anything.

It seems to me that the declaration for Pressure Sensor is set at some default pins as the mysensor.begin uses the XGZP6897D.h and that uses the Wire Library. So I am actually defining the pins for PMS5003 in your code as RXD1/22 and TXD1/21 and that allows the Pressure sensor to operate on its default pins in the Wire Library. When I change the 22/21 to 3/1 suggested by you the ESP hangs.

You're welcome!

I believe that happens because the code I suggested was to be used in ESP32 C3 Supermini, as it was previously intended, but...

if this definition is done, it's done somewhere inside the library XGZP6897D.h
Unfortnately I can't check it now, but can be a clue.

Hi. Have you solved the problem?

I still believe there's some lack of understanding about your I2C interface (the pressure sensor) and your Serial interface (the air quality sensor).

GPIOs 22 and 21 are the default I2C interface for many of the ESP32 boards. Thus, your pressure sensor should be connected to those pins and the library XGZP6897D.h will expect to have the sensor there.

In the other hand, Rx/Tx cannot be set for those same pins, you need to choose another pair. If you use ESP32 Wroom, try the version below. The air quality sensor RX pin should be connected to the ESP pin 10 and the sensor TX pin to the ESP pin 9.

#include <XGZP6897D.h>

#define K 8192 // see table above for the correct value for your sensor, according to the sensitivity.
XGZP6897D mysensor(K);
float pressure, temperature;

//#include <SoftwareSerial.h>
//SoftwareSerial pmsSerial(3, 2);
#define RXD1 9
#define TXD1 10

 
void setup() {
  // our debugging output
  Serial.begin(115200);
   // sensor baud rate is 9600
  //pmsSerial.begin(9600);
  Serial1.begin(9600, SERIAL_8N1, RXD1, TXD1);

  
  while (!mysensor.begin())  // initialize and check the device
  {
    Serial.println("Device not responding.");
    delay(500);
  }
  
}
 
struct pms5003data {
  uint16_t framelen;
  uint16_t pm10_standard, pm25_standard, pm100_standard;
  uint16_t pm10_env, pm25_env, pm100_env;
  uint16_t particles_03um, particles_05um, particles_10um, particles_25um, particles_50um, particles_100um;
  uint16_t unused;
  uint16_t checksum;
};
 
struct pms5003data data;
    
void loop() {
  if (readPMSdata(&Serial1)) {
    Serial.println(data.pm10_standard);
    Serial.println(data.pm25_standard);
    Serial.println(data.pm100_standard);
    Serial.println(data.particles_03um);                                                                
    Serial.println(data.particles_05um);
    Serial.println(data.particles_10um);
    Serial.println(data.particles_25um);
    Serial.println(data.particles_50um);
    Serial.println(data.particles_100um);

  }

     if (mysensor.readSensor(temperature, pressure))
      {
          Serial.println(temperature);
          Serial.println(pressure); 
          Serial.println();
        }
        else Serial.println("Reading fails. Timeout ??");
        delay(10);

}

 
boolean readPMSdata(Stream *s) {
  if (! s->available()) {
    return false;
  }
  
  // Read a byte at a time until we get to the special '0x42' start-byte
  if (s->peek() != 0x42) {
    s->read();
    return false;
  }
 
  // Now read all 32 bytes
  if (s->available() < 32) {
    return false;
  }
    
  uint8_t buffer[32];    
  uint16_t sum = 0;
  s->readBytes(buffer, 32);
 
  // get checksum ready
  for (uint8_t i=0; i<30; i++) {
    sum += buffer[i];
  }
 
  /* debugging
  for (uint8_t i=2; i<32; i++) {
    Serial.print("0x"); Serial.print(buffer[i], HEX); Serial.print(", ");
  }
  Serial.println();
  */
  
  // The data comes in endian'd, this solves it so it works on all platforms
  uint16_t buffer_u16[15];
  for (uint8_t i=0; i<15; i++) {
    buffer_u16[i] = buffer[2 + i*2 + 1];
    buffer_u16[i] += (buffer[2 + i*2] << 8);
  }
 
  // put it into a nice struct :)
  memcpy((void *)&data, (void *)buffer_u16, 30);
 
  if (sum != data.checksum) {
    Serial.println("Checksum failure");
    return false;
  }
  // success!
  return true;
}

Hi, I solved the issue both with ESP32 Wroom and with XiaoESP32C3.

For the ESP32Wroom the UART for serial monitor (TX0/RX0) interferes with the software or hardware serial if the pins 21/22 are used. So i changed the pins to 16/17 and the PMS5003 air quality sensor works. The pressure sensor library for XGZP6897D.h uses the pins 21/22 for SDA/SCL and need not be declared.

For the XiaoESP32C3 the XGZP6897D.h pressure sensor library uses by default the GPIO6/7 (marked SDA/SCL on xiao) so they have to be declared before this serial begins as Wire.begin(6,7) in order to use it. For the air quality PMS5003 is connected to (I was wrong here:3/4 RX/TX instead of the board declared 22/21 where it wont work). The PMS5003 can be connected to any available GPIO and in the code below I used pins 3/4 RX/TX and the pins 20/21 can also be used. In the files link I posted below codes with both of these connections are available. Both work.

Thank you for your persistent guidance. I will attach the codes and wiring soon.

You can't use the default UART1 pins (9/10) on Wroom32, they are connected to SPI flash.

Here is the working code for Xiao ESP32 C3 and Air Quality PMS5003 and Pressure Sensor XGZP6897D

#include <XGZP6897D.h>

#define K 8192 // see table above for the correct value for your sensor, according to the sensitivity.
XGZP6897D mysensor(K);
float pressure, temperature;

#include <SoftwareSerial.h>
SoftwareSerial pmsSerial(3, 4);
 
void setup() {
  // our debugging output
  Serial.begin(115200);
   // sensor baud rate is 9600
  pmsSerial.begin(9600);
    Wire.begin(6,7);
  while (!mysensor.begin())  // initialize and check the device
  {
    Serial.println("Device not responding.");
    delay(500);
  }
  
}
 
struct pms5003data {
  uint16_t framelen;
  uint16_t pm10_standard, pm25_standard, pm100_standard;
  uint16_t pm10_env, pm25_env, pm100_env;
  uint16_t particles_03um, particles_05um, particles_10um, particles_25um, particles_50um, particles_100um;
  uint16_t unused;
  uint16_t checksum;
};
 
struct pms5003data data;
    
void loop() {

  int count=0;
  while(count<10){
      if (mysensor.readSensor(temperature, pressure))
      {
          Serial.print(temperature); // Serial.print("C\t ");
          Serial.print(pressure); //Serial.print("Pa");
          Serial.println();
        }
        
        else Serial.println("Reading fails. Timeout ??");
        delay(1000);
        count++;
  }

  
  pmsSerial.listen(); 
  count=0;
  while(count<10){

  if (readPMSdata(&pmsSerial)) {
    // reading data was successful!
    Serial.println();
    Serial.println("---------------------------------------");
    Serial.println("Concentration Units (standard)");
    Serial.print("PM 1.0: "); Serial.print(data.pm10_standard);
    Serial.print("\t\tPM 2.5: "); Serial.print(data.pm25_standard);
    Serial.print("\t\tPM 10: "); Serial.println(data.pm100_standard);
    Serial.println("---------------------------------------");
    Serial.println("Concentration Units (environmental)");
    Serial.print("PM 1.0: "); Serial.print(data.pm10_env);
    Serial.print("\t\tPM 2.5: "); Serial.print(data.pm25_env);
    Serial.print("\t\tPM 10: "); Serial.println(data.pm100_env);
    Serial.println("---------------------------------------");
    Serial.print("Particles > 0.3um / 0.1L air:"); Serial.println(data.particles_03um);
    Serial.print("Particles > 0.5um / 0.1L air:"); Serial.println(data.particles_05um);
    Serial.print("Particles > 1.0um / 0.1L air:"); Serial.println(data.particles_10um);
    Serial.print("Particles > 2.5um / 0.1L air:"); Serial.println(data.particles_25um);
    Serial.print("Particles > 5.0um / 0.1L air:"); Serial.println(data.particles_50um);
    Serial.print("Particles > 10.0 um / 0.1L air:"); Serial.println(data.particles_100um);
    Serial.println("---------------------------------------");
  
    delay(10);
        count++;
  }
  }
  

//    mysensor.listen();
 
}

 
boolean readPMSdata(Stream *s) {
  if (! s->available()) {
    return false;
  }
  
  // Read a byte at a time until we get to the special '0x42' start-byte
  if (s->peek() != 0x42) {
    s->read();
    return false;
  }
 
  // Now read all 32 bytes
  if (s->available() < 32) {
    return false;
  }
    
  uint8_t buffer[32];    
  uint16_t sum = 0;
  s->readBytes(buffer, 32);
 
  // get checksum ready
  for (uint8_t i=0; i<30; i++) {
    sum += buffer[i];
  }
 
  /* debugging
  for (uint8_t i=2; i<32; i++) {
    Serial.print("0x"); Serial.print(buffer[i], HEX); Serial.print(", ");
  }
  Serial.println();
  */
  
  // The data comes in endian'd, this solves it so it works on all platforms
  uint16_t buffer_u16[15];
  for (uint8_t i=0; i<15; i++) {
    buffer_u16[i] = buffer[2 + i*2 + 1];
    buffer_u16[i] += (buffer[2 + i*2] << 8);
  }
 
  // put it into a nice struct :)
  memcpy((void *)&data, (void *)buffer_u16, 30);
 
  if (sum != data.checksum) {
    Serial.println("Checksum failure");
    return false;
  }
  // success!
  return true;
}

and the pin connections
XiaoESP32C3 GP3-PMSPin5TX
GP4-PMSPin4RX
GP6-XGZPin6SDA
GP7-XGZPin7SCL
Ground - XGZPin8GND - PMSPin2GND
3.3V - XGZPin2VDD - PMSPin1
and here are the links to the circuit diagrams etc https://drive.google.com/drive/folders/1w19_NuyX3lm0rq-gaPjgD4nJVC2fjYWu?usp=sharing