My Final Project Phases :
Project
Conception
Project
Planning
2D & 3D Design,
3D Print & Laser Cut
Electronics Design
and Fabrication
Programming &
Testing of
Electronics
Project
Presentation
Following is the minimum code to run my dust sensor.
However I continue to explore and added in some improvements to my original working code. These improvements are commentted off, like serial communication to PC and LED. While testing the serial output to my PC via FTDI adaptor, it still need more work and testing.
/* Title: PMS5003_dust_sensor_ver3.0.ino by Lucas Lim Date Created: 16/6/2020 Purpose: Receive data from PMS Dust Sensor Module and display PM2.5 and PM10 results to LCD display module. with I2C adaptor. Sound buzzer if pre-defined unhealthy limit is reach or exceeded. (Optional) Output result to PC via serial communication. PS : The code for the PMS5003 dust sensor module was adapted and modified from the orignal code by Lady Ada published on https://learn.adafruit.com/pm25-air-quality-sensor/arduino-code The work is provided for academic purpose for Fab Academy 2020. Users accept all as is, no warranty is provided, no call/email from users will get a response. Users accept all liability. */ // I2C library #include < Wire.h> // LCD with I2C library #include < LiquidCrystal_I2C.h> #include < SoftwareSerial.h> // variable declaration // const value will not change //const int ledpin=2; // LED connected to PD2 on Arduino pin 2(not use) const int buzzpin=5; // buzzer connected to PD5 on Arduino pin 5 const int pms5003_RX = 17; // PMS5003 dust sensor Rx, on Arduino pin 17 const int pms5003_TX = 16; // PMS5003 dust sensor Tx, on Arduino pin 16(not use) int pms_interval_time=2000; // PMS5003 delay time between taking next reading, 1000 = 1sec SoftwareSerial pmsSerial(pms5003_RX, pms5003_TX); LiquidCrystal_I2C lcd(0x3F, 16, 2); // set the LCD address to 0x3F for a 16 chars and 2 line display void setup() { // our debugging, output to serial on PC //Serial.begin(115200); // sensor baud rate is 9600 pmsSerial.begin(9600); Wire.begin(); // Initialize the LCD, must be called in order to initialize I2C communication lcd.begin(); // Turn on the backlight lcd.backlight(); // Buzzer pinMode(buzzpin,OUTPUT); // LED - for power status indicator (not use as LCD display is lit up already) //pinMode(ledpin,OUTPUT); } 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)) { //Output PM2.5 and PM10 measurements to LCD display //LCD first row display PM10 lcd.setCursor(0, 0); lcd.print("PM10 :"); lcd.setCursor(8, 0); lcd.print(data.pm100_standard); //LCD second row display PM2.5 lcd.setCursor(0,1); lcd.print("PM2.5 :"); lcd.setCursor(8, 1); lcd.print(data.pm25_standard); // Sound off buzzer if PM2.5 or PM10 read the 'moderate polluted range' // Good : PM10 (1-50) PM2.5(0-30) // Satisfactory : PM10 (51-100) PM2.5(31-60) // Moderately polluted : PM10 (101-250) PM2.5(61-90) // Poor : PM10 (251-350) PM2.5(91-120) // Very poor : PM10 (351-430) PM2.5(121-250) // Severe : PM10 (430+) PM2.5(250+) if (data.pm100_standard >= 251) { tone(buzzpin, 1000, 10000); //turns on buzzer, tone( pin number, frequency in hertz, in milliseconds) //Serial.print("Buzzer sounded. PM10 reach or exceed limit!"); lcd.setCursor(0, 0); lcd.print("PM10 :"); lcd.setCursor(8, 0); lcd.print(data.pm100_standard); lcd.setCursor(20, 0); lcd.print("!!!"); } else { noTone(buzzpin); } if (data.pm25_standard >= 91) { tone(buzzpin, 1000, 10000); //turns on buzzer, tone( pin number, frequency in hertz, in milliseconds) //Serial.print("Buzzer sounded. PM2.5 reach or limit!"); lcd.setCursor(0,1); lcd.print("PM2.5 :"); lcd.setCursor(8, 1); lcd.print(data.pm25_standard); lcd.setCursor(20, 1); lcd.print("!!!"); } else { noTone(buzzpin); } } // Wait for xx seconds before PMS5003 take next reading delay(pms_interval_time); } 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; }
Duration : 1 min.
Please switch on your audio speaker.
Areas of improvement :
1) To take reading at 10 minutes or longer interval.
2) Take a few readings and average out the readings before displaying to the LCD screen.
My code :
PMS5003_sensor_with_LCD_display.ino