asking
March 19, 2024, 10:31am
1
Hello everyone,
I had been trying to integrate Honeywell IH-PMC-002 sensor to ESP32 via I2C Protocol using 3.3V level shifter.
I am able to detect I2C Address of 0x08. (IH-PMC-002 on i2c scanner).
I had written below program using Datasheet . Still getting CRC checksum error and values not updating further.
#include <Wire.h>
int i=0;
#define PMS_ADDRESS 0x08
void setup() {
// put your setup code here, to run once:
Wire.begin();
Serial.begin(115200);
Wire.beginTransmission(PMS_ADDRESS);
Wire.write(0xFF);
delay(10);
Wire.write(0x10);
Wire.write(0x00);
Wire.write(0x10);
Wire.write(0x05);
Wire.write(0x00);
Wire.write(0xF6);
Wire.endTransmission();
}
void loop() {
// Send command to read data
byte command[] = {0x10, 0x03, 0x00, 0x11};
Wire.beginTransmission(PMS_ADDRESS);
Wire.write(command, sizeof(command));
Wire.endTransmission();
// Request 30 bytes of data from the slave device
Wire.requestFrom(PMS_ADDRESS, 30);
// Check if all bytes are available
if (Wire.available() >= 30) {
// Read and interpret data
byte received_data[24]; // Array to hold received data bytes
for (int i = 0; i < 24; i++) {
received_data[i] = Wire.read(); // Read data bytes
}
byte crc = Wire.read(); // Read CRC byte
// Calculate CRC checksum for the received data
byte calculated_crc = Calc_CRC8(received_data, sizeof(received_data));
// Verify CRC checksum
if (crc == calculated_crc) {
// CRC checksum matches, data is valid
// Interpret data and print measurements
unsigned int pm1_concentration = (received_data[0] << 8) | received_data[1];
unsigned int pm25_concentration = (received_data[3] << 8) | received_data[4];
unsigned int pm4_concentration = (received_data[6] << 8) | received_data[7];
unsigned int pm10_concentration = (received_data[9] << 8) | received_data[10];
Serial.print("PM1.0 concentration: ");
Serial.print(pm1_concentration);
Serial.println(" mg/m^3");
Serial.print("PM2.5 concentration: ");
Serial.print(pm25_concentration);
Serial.println(" mg/m^3");
Serial.print("PM4.0 concentration: ");
Serial.print(pm4_concentration);
Serial.println(" mg/m^3");
Serial.print("PM10 concentration: ");
Serial.print(pm10_concentration);
Serial.println(" mg/m^3");
} else {
// CRC checksum does not match, data is invalid
Serial.println("CRC checksum error!");
}
}
delay(1000); // Delay between readings
}
byte Calc_CRC8(byte *data, byte Num) {
byte bit, byte, crc = 0xFF;
for (byte = 0; byte < Num; byte++) {
crc ^= data[byte];
for (bit = 8; bit > 0; --bit) {
if (crc & 0x80)
crc = (crc << 1) ^ 0x31;
else
crc = (crc << 1);
}
}
return crc;
}
gcjr
March 19, 2024, 11:17am
2
can you provide the raw data values the checksum is being calculated on?
asking
March 19, 2024, 11:28am
3
Getting debug data as below:
For byte[0] byte[1] = 255 and checksum byte[2] = 172.
As per datasheet PM1.0 Concentration = byte[0]*256+byte[1] = 65535 Getting right now.
gcjr
March 19, 2024, 11:29am
4
i'm asking you to post the data, not explain how you get it
asking
March 19, 2024, 11:32am
5
Here's the data.
byte command[] = {0x10, 0x03, 0x00, 0x11};
Wire.beginTransmission(PMS_ADDRESS);
Wire.write(command, sizeof(command));
//Wire.endTransmission();
// Request 3 bytes of data from the slave device
Wire.requestFrom(PMS_ADDRESS,3);
received_data[0] = Wire.read(); // Read data bytes
received_data[1] = Wire.read(); // Read data bytes
received_data[2] = Wire.read(); // Read data bytes
Serial.println(received_data[0]);
Serial.println(received_data[1]);
Serial.println(received_data[2]);
unsigned int pm1_concentration = (received_data[0] << 8) | received_data[1];
Serial.println(pm1_concentration);
Serial Print output.
17:06:10.597 -> 65452
17:06:11.589 -> 255
17:06:11.589 -> 172
17:06:11.589 -> 0
17:06:11.589 -> 65452
17:06:12.593 -> 255
17:06:12.593 -> 172
17:06:12.593 -> 0
17:06:12.593 -> 65452
17:06:13.611 -> 255
17:06:13.611 -> 172
17:06:13.611 -> 0
17:06:13.611 -> 65452
17:06:14.603 -> 255
17:06:14.603 -> 172
17:06:14.603 -> 0
asking
March 19, 2024, 11:37am
7
Just updated my code. actually i missed
Wire.requestFrom(PMS_ADDRESS,3);
asking
March 19, 2024, 12:23pm
8
Oscilloscope is reading i2C Channel with 0x11 Read command.
asking
March 20, 2024, 6:12am
9
DSO Debug details
I2C, Time, Address, R/W, Data
1,-10.0140us,0x10,W,0x10 03 00
2,389.044us,0x10,W,0x11
3,1.60918ms,0x11,R,0xFF FF AC FF FF AC FF FF AC FF FF AC FF FF AC FF FF AC FF FF AC FF FF AC FF FF AC FF FF AC~A
reading this datasheet , I do not think you are using the right bytes to compute the CRC:
so maybe try something like this then:
(Compiles, NOT tested!)
#include <Wire.h>
#define PMS_ADDRESS 0x08
void setup() {
// put your setup code here, to run once:
Wire.begin();
Serial.begin(115200);
Wire.beginTransmission(PMS_ADDRESS);
Wire.write(0xFF);
delay(10);
Wire.write(0x10);
Wire.write(0x00);
Wire.write(0x10);
Wire.write(0x05);
Wire.write(0x00);
Wire.write(0xF6);
Wire.endTransmission();
}
void loop() {
// Send command to read data
byte command[] = {0x10, 0x03, 0x00, 0x11};
Wire.beginTransmission(PMS_ADDRESS);
Wire.write(command, sizeof(command));
Wire.endTransmission();
// Request 30 bytes of data from the slave device
Wire.requestFrom(PMS_ADDRESS, 30);
delay(1000); // Delay between readings
// Check if all bytes are available
if (Wire.available()) {
// Read and interpret data
byte received_data[3]; // Array to hold received data bytes
for (int j = 0; j < 4; j++) {
for (int i = 0; i < 3; i++) {
received_data[i] = Wire.read(); // Read data bytes
}
// Calculate CRC checksum for the received data
byte calculated_crc = Calc_CRC8(received_data, 2);
Serial.print("pm data");
Serial.print(j+1);
Serial.print(": ");
for (int i = 0; i < 3; i++) {
Serial.print(received_data[i]);
Serial.print(", ");
}
Serial.print("calculated Crc: ");
Serial.println(calculated_crc); //does is match 'received_data[2]' value?
}
//purge remaining bytes:
while (Wire.available()) Wire.read();
}
}
byte Calc_CRC8(byte *data, byte Num) {
byte bit, byte, crc = 0xFF;
for (byte = 0; byte < Num; byte++) {
crc ^= data[byte];
for (bit = 8; bit > 0; --bit) {
if (crc & 0x80)
crc = (crc << 1) ^ 0x31;
else
crc = (crc << 1);
}
}
return crc;
}
hope that helps...
gcjr
March 20, 2024, 8:58am
11
asking:
3,1.60918ms,0x11,R,0xFF FF AC FF FF AC FF FF AC FF FF AC FF FF AC FF FF AC FF FF AC FF FF AC FF FF AC FF FF AC~A
if this is the data, it looks repetitious. are you sure the chip is configured correctly and is being read properly
asking
March 20, 2024, 9:05am
12
sherzaad:
#include <Wire.h>
#define PMS_ADDRESS 0x08
void setup() {
// put your setup code here, to run once:
Wire.begin();
Serial.begin(115200);
Wire.beginTransmission(PMS_ADDRESS);
Wire.write(0xFF);
delay(10);
Wire.write(0x10);
Wire.write(0x00);
Wire.write(0x10);
Wire.write(0x05);
Wire.write(0x00);
Wire.write(0xF6);
Wire.endTransmission();
}
void loop() {
// Send command to read data
byte command[] = {0x10, 0x03, 0x00, 0x11};
Wire.beginTransmission(PMS_ADDRESS);
Wire.write(command, sizeof(command));
Wire.endTransmission();
// Request 30 bytes of data from the slave device
Wire.requestFrom(PMS_ADDRESS, 30);
delay(1000); // Delay between readings
// Check if all bytes are available
if (Wire.available()) {
// Read and interpret data
byte received_data[3]; // Array to hold received data bytes
for (int j = 0; j < 4; j++) {
for (int i = 0; i < 3; i++) {
received_data[i] = Wire.read(); // Read data bytes
}
// Calculate CRC checksum for the received data
byte calculated_crc = Calc_CRC8(received_data, 2);
Serial.print("pm data");
Serial.print(j+1);
Serial.print(": ");
for (int i = 0; i < 3; i++) {
Serial.print(received_data[i]);
Serial.print(", ");
}
Serial.print("calculated Crc: ");
Serial.println(calculated_crc); //does is match 'received_data[2]' value?
}
//purge remaining bytes:
while (Wire.available()) Wire.read();
}
}
byte Calc_CRC8(byte *data, byte Num) {
byte bit, byte, crc = 0xFF;
for (byte = 0; byte < Num; byte++) {
crc ^= data[byte];
for (bit = 8; bit > 0; --bit) {
if (crc & 0x80)
crc = (crc << 1) ^ 0x31;
else
crc = (crc << 1);
}
}
return crc;
}
out is something like this
14:35:01.250 -> pm data4: 255, 255, 172, calculated Crc: 172
14:35:02.253 -> pm data1: 255, 255, 172, calculated Crc: 172
14:35:02.254 -> pm data2: 255, 255, 172, calculated Crc: 172
14:35:02.254 -> pm data3: 255, 255, 172, calculated Crc: 172
14:35:02.254 -> pm data4: 255, 255, 172, calculated Crc: 172
14:35:03.277 -> pm data1: 255, 255, 172, calculated Crc: 172
14:35:03.277 -> pm data2: 255, 255, 172, calculated Crc: 172
14:35:03.277 -> pm data3: 255, 255, 172, calculated Crc: 172
14:35:03.277 -> pm data4: 255, 255, 172, calculated Crc: 172
14:35:04.286 -> pm data1: 255, 255, 172, calculated Crc: 172
14:35:04.286 -> pm data2: 255, 255, 172, calculated Crc: 172
14:35:
asking
March 20, 2024, 9:15am
13
Yes i checked basic details like Voltage levels is 4.76 and connection are proper. Sensor Pin 3 is set to 0. for I2C Selection and its working but receiving data in 0xFF.
so the CRC is correct!
just strange that all the pm data is 255(0xFF)...
did you try putting the sensor in a test environment (like blowing some smoke onto it) to see if those value change?
gcjr
March 20, 2024, 9:28am
15
the IH-PMC-002 datasheet says the returned data has the following format, prefixed with 0x10 0x03 0x00 0x11
10 03 00 11 Data0_H Data0_L Data0_CRC......
i don't believe you are reading the data correctly
no it doesn't.
you SEND those to get reply is what the datasheet says (see screenshot is reply #10 )
at least that's how I read it!
but yes, there could be a prefix of 0x11 though...
OP should probably simply do a trial a print out the RAW 30 (or 31) bytes to see what that gives for ONE readout....
gcjr
March 20, 2024, 9:44am
17
it says you send the following to start a measurement
3.3.1 Start measurement: 10 00 10 05 00 F6
and receive the following
3.3.3 Read the data: 10 03 00 11 Data0_H Data0_L Data0_CRC......
asking
March 20, 2024, 9:46am
18
Correct.
I had only doubt regarding after reading datasheet thoroughly.
after 0x00 - ACK - P - S .
Do we need to user Wire.endTransmission(false); with false parameter ?
asking
March 20, 2024, 9:48am
19
Just below 3.3.3 its written.
Send this command to read the measured value.
was just about to point that out!
maybe try the code again from post #10 again and but comment out this line to see if that makes any difference:
byte command[] = {0x10, 0x03, 0x00}; //<------- change this command
Wire.beginTransmission(PMS_ADDRESS);
Wire.write(command, sizeof(command));
Wire.endTransmission(); // <----------------comment out this line
if you now see the 0x11 prefix then that would match the datasheet
then would need to adjust the code one more to compute the CRC correctly (all CRC with modded post #10 code should not match it what I expect)
no harm doing a bit of trial and error!