Interfacing Honeywell HPMA 215S0 with Arduino Mega and ESP32

Hi, I am getting a new problem. If I use Arduino Mega with Honeywell HPMA-215S0, I am getting pm2.5-10ug/m3 and pm10-12ug/m3 [Sensor Refresh Rate:1Sec]. If I use ESP32 with the same sensor at the same time with the same code in the same room, I am getting pm2.5- 48ug/m3 and pm10-50ug/m3 [Refresh rate: 1 Sec].

Another point, If I use, Arduino mega with refresh rate:10Sec, sensor reading is reduced[ pm2.5- 1 ug/m3, pm10- 2 ug/m3].
But, with ESP32, with changing the refresh rate, all readings are close.

N.B: I did all the test in the same closed room with the same power supply.

Please Help!!!

I am attaching the code, for better understanding.

mega_pm.c (4.64 KB)

Hi, welcome to the forum, please read the forum guide especially points 7, 11 & 15. Then modify your post above so that we can at least understand your problem and perhaps suggest a solution.

Hi, I am getting a new problem. If I use Arduino Mega with Honeywell HPMA-215S0, I am getting pm2.5-10ug/m3 and pm10-12ug/m3 [Sensor Refresh Rate:1Sec]. If I use ESP32 with the same sensor at the same time with the same code in the same room, I am getting pm2.5- 48ug/m3 and pm10-50ug/m3 [Refresh rate: 1 Sec].

Another point, If I use, Arduino mega with refresh rate:10Sec, sensor reading is reduced[ pm2.5- 1 ug/m3, pm10- 2 ug/m3].
But, with ESP32, with changing the refresh rate, all readings are close.

N.B: I did all the test in the same closed room with the same power supply.

Please Help!!!

I am attaching the code, for better understanding.

ARDUINO MEGA CODE

#define HPM_CMD_RESP_HEAD 0x40
#define HPM_MAX_RESP_SIZE 8 // max command response size is 8 bytes
#define HPM_READ_PARTICLE_MEASURMENT_LEN 5
unsigned int _pm2_5 = 0;

//Latest PM 10 reading
unsigned int _pm10 = 0;
enum CMD_TYPE_T {
    READ_PARTICLE_MEASURMENT = 0x04,
    START_PARTICLE_MEASURMENT = 0x01,
    STOP_PARTICLE_MEASURMENT = 0x02,
    SET_ADJUSTMENT_COEFFICIENT = 0x08,
    READ_ADJUSTMENT_COEFFICIENT = 0x08,
    STOP_AUTO_SEND = 0x20,
    ENABLE_AUTO_SEND = 0x40,
};

enum HPM_PACKET_T {
    HPM_HEAD_IDX,
    HPM_LEN_IDX,
    HPM_CMD_IDX,
    HPM_DATA_START_IDX
};




void SendCmd(unsigned char * cmdBuf, unsigned int cmdSize) {
  //Clear RX
  Serial.println("Serial Printing before sendCmd");
  while (Serial2.available())
    Serial.print(Serial2.read());

  Serial.print("PS- Sending cmd: ");
  unsigned int index = 0;
  for (index = 0; index < cmdSize; index++) {
    Serial.print(cmdBuf[index], HEX);
    Serial.print(" ");
    Serial2.write(cmdBuf[index]);
  }
  Serial.println("");
  return;
}

void Init() {
  Serial.println("PS- Initializing...");
  delay(100);
  StartParticleMeasurement();
  delay(100);
  DisableAutoSend();
}


int ReadCmdResp(unsigned char * dataBuf, unsigned int dataBufSize, unsigned int cmdType) {
  static unsigned char respBuf[HPM_MAX_RESP_SIZE];
  static unsigned int respIdx = 0;
  static unsigned int calChecksum = 0;

  //Read response
  respIdx = 0;
  calChecksum = 0;
  memset(respBuf, 0, sizeof(respBuf));
  Serial2.setTimeout(100);
  Serial.println("PS- Waiting for cmd resp...");
  if (Serial2.readStringUntil(HPM_CMD_RESP_HEAD)) {
    delay(1); //wait for the rest of the bytes to arrive
    respBuf[HPM_HEAD_IDX] = HPM_CMD_RESP_HEAD;
    respBuf[HPM_LEN_IDX] = Serial2.read(); 
    Serial.print("Length:");
    Serial.print(respBuf[HPM_LEN_IDX]);

    if (respBuf[HPM_LEN_IDX] && ((respBuf[HPM_LEN_IDX] + 1) <=  sizeof(respBuf) - 2) && (respBuf[HPM_LEN_IDX] - 1) <= dataBufSize ) {
      if (Serial2.readBytes(&respBuf[HPM_CMD_IDX], respBuf[HPM_LEN_IDX] + 1) == (respBuf[HPM_LEN_IDX] + 1)) { 
        if (respBuf[HPM_CMD_IDX] == cmdType) { //check if CMD type matches

          for (respIdx = 0; respIdx < (2 + respBuf[HPM_LEN_IDX]); respIdx++) {
            calChecksum += respBuf[respIdx];
          }
          calChecksum = (65536 - calChecksum) % 256;
          if (calChecksum == respBuf[2 + respBuf[HPM_LEN_IDX]]) {
            Serial.println("PS- Received valid data!!!");
            memset(dataBuf, 0, dataBufSize);
            memcpy(dataBuf, &respBuf[HPM_DATA_START_IDX], respBuf[HPM_LEN_IDX] - 1);
            return (respBuf[HPM_LEN_IDX] - 1);
          }
        }
      }
    }
  }
      while(Serial2.available()>0)
        Serial.print(Serial2.read());

      return true;
  return false;
}

void StartParticleMeasurement() {
  char cmd[] = {0x68, 0x01, 0x01, 0x96};
  SendCmd(cmd, 4);
}
void StopParticleMeasurement() {
 char cmd[] = {0x68, 0x01, 0x02, 0x95};
  SendCmd(cmd, 4);
}
boolean ReadParticleMeasurement(unsigned int * pm2_5, unsigned int * pm10) {
 char cmdBuf[] = {0x68, 0x01, 0x04, 0x93};
  static unsigned char dataBuf[HPM_READ_PARTICLE_MEASURMENT_LEN - 1];

  Serial.println("PS- Reading Particle Measurements..." );

  SendCmd(cmdBuf, 4);

  if (ReadCmdResp(dataBuf, sizeof(dataBuf), READ_PARTICLE_MEASURMENT) == (HPM_READ_PARTICLE_MEASURMENT_LEN - 1)) {
    _pm2_5 = dataBuf[0] * 256 + dataBuf[1];
    _pm10 = dataBuf[2] * 256 + dataBuf[3];
    *pm2_5 = _pm2_5;
    *pm10 = _pm10;

    return true;
  }
  return false;
}

void DisableAutoSend() {
 char cmd[] = {0x68, 0x01, 0x20, 0x77};
  SendCmd(cmd, 4);
}






void setup() {
  Serial.begin(9600);
  Serial2.begin(9600);
  Init();
  StartParticleMeasurement();
}

void loop() {
  unsigned int pm2_5, pm10;
  if (ReadParticleMeasurement(&pm2_5, &pm10)) {
    Serial.println("PM 2.5: " + String(pm2_5) + " ug/m3" );
    Serial.println("PM 10: " + String(pm10) + " ug/m3" );
  }
  delay(1000);

}

ESPRESSIF ESP32 DEV MODULE CODE

#define HPM_CMD_RESP_HEAD 0x40
#define HPM_MAX_RESP_SIZE 8 // max command response size is 8 bytes
#define HPM_READ_PARTICLE_MEASURMENT_LEN 5
unsigned int _pm2_5 = 0;

//Latest PM 10 reading
unsigned int _pm10 = 0;
enum CMD_TYPE_T {
    READ_PARTICLE_MEASURMENT = 0x04,
    START_PARTICLE_MEASURMENT = 0x01,
    STOP_PARTICLE_MEASURMENT = 0x02,
    SET_ADJUSTMENT_COEFFICIENT = 0x08,
    READ_ADJUSTMENT_COEFFICIENT = 0x08,
    STOP_AUTO_SEND = 0x20,
    ENABLE_AUTO_SEND = 0x40,
};

enum HPM_PACKET_T {
    HPM_HEAD_IDX,
    HPM_LEN_IDX,
    HPM_CMD_IDX,
    HPM_DATA_START_IDX
};




void SendCmd(char * cmdBuf, unsigned int cmdSize) {
  //Clear RX
  Serial.println("Serial Printing before sendCmd");
  while (Serial2.available())
    Serial.print(Serial2.read());

  //Send command
  Serial.print("PS- Sending cmd: ");
  unsigned int index = 0;
  for (index = 0; index < cmdSize; index++) {
    Serial.print(cmdBuf[index], HEX);
    Serial.print(" ");
    Serial2.write(cmdBuf[index]);
  }
  Serial.println("");
  return;
}

void Init() {
  Serial.println("PS- Initializing...");
  delay(100);
  StartParticleMeasurement();
  delay(100);
  DisableAutoSend();
}


int ReadCmdResp(unsigned char * dataBuf, unsigned int dataBufSize, unsigned int cmdType) {
  static unsigned char respBuf[HPM_MAX_RESP_SIZE];
  static unsigned int respIdx = 0;
  static unsigned int calChecksum = 0;

  respIdx = 0;
  calChecksum = 0;
  memset(respBuf, 0, sizeof(respBuf));
  Serial2.setTimeout(100);
  Serial.println("PS- Waiting for cmd resp...");
  if (Serial2.readStringUntil(HPM_CMD_RESP_HEAD)) {
    delay(1); //wait for the rest of the bytes to arrive
    respBuf[HPM_HEAD_IDX] = HPM_CMD_RESP_HEAD;
    respBuf[HPM_LEN_IDX] = Serial2.read(); //Read the command length

    if (respBuf[HPM_LEN_IDX] && ((respBuf[HPM_LEN_IDX] + 1) <=  sizeof(respBuf) - 2) && (respBuf[HPM_LEN_IDX] - 1) <= dataBufSize ) {
      if (Serial2.readBytes(&respBuf[HPM_CMD_IDX], respBuf[HPM_LEN_IDX] + 1) == (respBuf[HPM_LEN_IDX] + 1)) { 
        if (respBuf[HPM_CMD_IDX] == cmdType) {

          //Calculate and validate checksum
          for (respIdx = 0; respIdx < (2 + respBuf[HPM_LEN_IDX]); respIdx++) {
            calChecksum += respBuf[respIdx];
          }
          calChecksum = (65536 - calChecksum) % 256;
          if (calChecksum == respBuf[2 + respBuf[HPM_LEN_IDX]]) {
            Serial.println("PS- Received valid data!!!");
            memset(dataBuf, 0, dataBufSize);
            memcpy(dataBuf, &respBuf[HPM_DATA_START_IDX], respBuf[HPM_LEN_IDX] - 1);
            return (respBuf[HPM_LEN_IDX] - 1);
          }
        }
      }
    }
  }
      while(Serial2.available()>0)
        Serial.print(Serial2.read());

      return true;
  return false;
}

void StartParticleMeasurement() {
  char cmd[] = {0x68, 0x01, 0x01, 0x96};
  SendCmd(cmd, 4);
}
void StopParticleMeasurement() {
 char cmd[] = {0x68, 0x01, 0x02, 0x95};
  SendCmd(cmd, 4);
}
boolean ReadParticleMeasurement(unsigned int * pm2_5, unsigned int * pm10) {
 char cmdBuf[] = {0x68, 0x01, 0x04, 0x93};
  static unsigned char dataBuf[HPM_READ_PARTICLE_MEASURMENT_LEN - 1];

  Serial.println("PS- Reading Particle Measurements..." );

  //Send command
  SendCmd(cmdBuf, 4);

  //Read response
  if (ReadCmdResp(dataBuf, sizeof(dataBuf), READ_PARTICLE_MEASURMENT) == (HPM_READ_PARTICLE_MEASURMENT_LEN - 1)) {
    _pm2_5 = dataBuf[0] * 256 + dataBuf[1];
    _pm10 = dataBuf[2] * 256 + dataBuf[3];
    *pm2_5 = _pm2_5;
    *pm10 = _pm10;

    return true;
  }
  return false;
}

void DisableAutoSend() {
 char cmd[] = {0x68, 0x01, 0x20, 0x77};
  SendCmd(cmd, 4);
}






void setup() {
  Serial.begin(9600);
  Serial2.begin(9600);
  Init();
  StartParticleMeasurement();
}

void loop() {
  unsigned int pm2_5, pm10;
  if (ReadParticleMeasurement(&pm2_5, &pm10)) {
    Serial.println("PM 2.5: " + String(pm2_5) + " ug/m3" );
    Serial.println("PM 10: " + String(pm10) + " ug/m3" );
  }
  delay(1000);

}

OK, I see you re-posted your unintelligible question but with code attached in code tags. What I was asking you to do was to modify your original post, not just to add your code but to include all the other information mentioned in the forum guide, and following all the advice in the forum guide about how to ask questions on the forum. If you do not know what this other information is or what advice to follow, then read the forum guide again, paying particular attention to the sections I mentioned before. If you can't understand the guide, please quote the parts you cannot understand and ask for assistance.