Using a PMS5003 Sensor to detect particle sizes of 1um, 2.5um and 10um, implemented via ESP Home on Home Assistant:
PMS5003 wiring
The PMS5003 uses 5V power and 3.3V for control.
- Connect pin one to the 5v VIN pin on the ESP8266
- Connect Pin 2 to any ground pin.
- Connect Pin 3 to D3
- Connect Pin 4 to D6
- Connect Pin 5 to D7
esphome: name: aqspms5003 esp8266: board: d1_mini # Enable logging logger: # Enable Home Assistant API api: ota: password: "db13249d8b5dff2bf079cbe585af974d" wifi: ssid: "your Wi-Fi SSID" password: "your Wi-Fi PASSWORD" # Enable fallback hotspot (captive portal) in case wifi connection fails ap: ssid: "Aqs Fallback Hotspot" password: "uOrOJjJeYvqg" captive_portal: uart: rx_pin: D7 tx_pin: D6 baud_rate: 9600 id: pms5003_uart sensor: - platform: pmsx003 type: PMSX003 pm_1_0: name: "PMS5003 <1.0µm Concentration" accuracy_decimals: 1 pm_2_5: name: "PMS5003 <2.5µm Concentration" accuracy_decimals: 1 pm_10_0: name: "PMS5003 <10.0µm Concentration" accuracy_decimals: 1 update_interval: 120s
Arduino Serial Interface
#include <SoftwareSerial.h> SoftwareSerial pmsSerial(2, 3); void setup() { // our debugging output Serial.begin(115200); // sensor baud rate is 9600 pmsSerial.begin(9600); } 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)) { // 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("---------------------------------------"); } } 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; }