Arduino Code For PM Outdoor & Indoor Sensor

pm sensor connection with arduino

//Prana Air, AQI(Air Quality Index) Sensor Code
//NOTE:
//This code is compaitable with Arduino board

#include
SoftwareSerial PMSerial2(2,3);

typedef enum eCmd {
BOOT_UP,
RD_CURRENT_OP_MODE,
REL_CONT_SENDING_OF_DATA,
RD_32B_MEASUREMENT_DATA

} eCmd_t;

struct pms5003data {
//uint16_t frameStart;
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;
};

class aqi {
private:
boolean sendCmd(eCmd_t cmd, Stream *s);

public:
Stream *aqiStream;
struct pms5003data data;
aqi();
boolean readPMSdata();
};

#define RXD2 2
#define TXD2 3

#define HDR_OFFSET 0
#define FRAME_CMD_OFFSET 1
#define FRAME_CONTENT_OFFSET 2
#define FRAME_CHKSUM_OFFSET 6
#define FRAME_TAIL_OFFSET 8

typedef union uchecksum {
uint8_t checksum[2];
uint16_t checksum_s;
} uchecksum_t;

uint8_t cmdFrame[9];

aqi::aqi () {
PMSerial2.begin(9600);
this->aqiStream = &PMSerial2;

this->sendCmd(RD_CURRENT_OP_MODE, aqiStream);

}

boolean aqi::sendCmd(eCmd_t cmd, Stream *s) {
uchecksum_t checksum_u;
cmdFrame[HDR_OFFSET] = 0xAA;
cmdFrame[FRAME_CONTENT_OFFSET] = 0x00;
cmdFrame[FRAME_CONTENT_OFFSET+1] = 0x00;
cmdFrame[FRAME_CONTENT_OFFSET+2] = 0x00;
cmdFrame[FRAME_CONTENT_OFFSET+3] = 0x00;
cmdFrame[FRAME_TAIL_OFFSET] = 0xBB;
//Serial.print(“2”);
switch(cmd) {
case BOOT_UP:
cmdFrame[FRAME_CMD_OFFSET] = 0x01;
//cmdFrame[FRAME_CHKSUM_OFFSET 0-1] = ;
break;
case RD_CURRENT_OP_MODE:
cmdFrame[FRAME_CMD_OFFSET] = 0x0A;
break;
case REL_CONT_SENDING_OF_DATA:
cmdFrame[FRAME_CMD_OFFSET] = 0x09;
break;
case RD_32B_MEASUREMENT_DATA:
cmdFrame[FRAME_CMD_OFFSET] = 0x05;
break;
default:
Serial.println(“Unknown command”);
}

checksum_u.checksum_s = cmdFrame[0]+cmdFrame[1]+cmdFrame[2]+cmdFrame[3]+cmdFrame[4]+cmdFrame[5]+cmdFrame[8];
cmdFrame[FRAME_CHKSUM_OFFSET] = checksum_u.checksum[1];
cmdFrame[FRAME_CHKSUM_OFFSET+1] = checksum_u.checksum[0];

int count=0;
#if 0
for(;count < sizeof(cmdFrame); count++) { Serial.printf(“%d : %x \n”, count, cmdFrame[count]); } #endif s->write(cmdFrame, sizeof(cmdFrame));

//Serial.println(“Response to cmd: “);
#if 0
while (s->available()) {
/* if (s->available()) */ {
Serial.printf(“response = %x”, s->read());
}

}
#endif

//cmdFrame[FRAME_CMD_OFFSET] = ;
//cmdFrame[FRAME_CHKSUM_OFFSET 0-1] = ;
}

boolean aqi::readPMSdata() {
Stream *s = aqiStream;
sendCmd(RD_32B_MEASUREMENT_DATA, s);

if (! s->available()) {
Serial.println(“PMS data not available”);
delay(1000);
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++) {
//Serial.print(“here”);
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; } void setup() { // put your setup code here, to run once: Serial.begin(115200); } void loop() { // put your main code here, to run repeatedly: // aqi abc; aqi abc; if(abc.readPMSdata()==true) { Serial.println(“Everything is okay Sensor is working fine”);} Serial.print(“Particles > 0.3um / 0.1L air:”); Serial.println(abc.data.particles_03um);
Serial.print(“Particles > 0.5um / 0.1L air:”); Serial.println(abc.data.particles_05um);
Serial.print(“Particles > 1.0um / 0.1L air:”); Serial.println(abc.data.particles_10um);
Serial.print(“Particles > 2.5um / 0.1L air:”); Serial.println(abc.data.particles_25um);
Serial.print(“Particles > 5.0um / 0.1L air:”); Serial.println(abc.data.particles_50um);
Serial.print(“Particles > 10.0 um / 0.1L air:”); Serial.println(abc.data.particles_100um);
Serial.println(“—————————————“);
Serial.println(“Concentration Units (standard)”);
Serial.print(“PM 1.0: “); Serial.print(abc.data.pm10_standard);
Serial.print(“\t\tPM 2.5: “); Serial.print(abc.data.pm25_standard);
Serial.print(“\t\tPM 10: “); Serial.println(abc.data.pm100_standard);
Serial.println(“—————————————“);
Serial.println(“Concentration Units (environmental)”);
Serial.print(“PM 1.0: “); Serial.print(abc.data.pm10_env);
Serial.print(“\t\tPM 2.5: “); Serial.print(abc.data.pm25_env);
Serial.print(“\t\tPM 10: “); Serial.println(abc.data.pm100_env);
Serial.println(“—————————————“);
delay(1000);
}