Created
December 5, 2019 09:06
-
-
Save Electronza/0fa8b0bcc111a10a59812e8af882689e to your computer and use it in GitHub Desktop.
Arduino Due code for Honeywell HPMA115S0-XXX particle sensor
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
// Arduino Due code for Honeywell HPMA115S0-XXX particle sensor | |
// https://electronza.com/arduino-measuring-pm25-pm10-honeywell-hpma115s0/ | |
bool my_status; | |
// IMPORTANT!!! We are working on an Arduino DUE, | |
// so int is 32 bit (-2,147,483,648 to 2,147,483,647) | |
// For Arduino Uno int size is 8 bit, that is -32,768 to 32,767 | |
// Use long or float if working with an Uno or simmilar 8-bit board | |
int PM25; | |
int PM10; | |
void setup() { | |
Serial.begin(9600); | |
while (!Serial); | |
Serial3.begin(9600); | |
delay(100); | |
// Stop autosend | |
my_status = stop_autosend(); | |
// Serial print is used just for debugging | |
// But one can design a more complex code if desired | |
Serial.print("Stop autosend status is "); | |
Serial.println(my_status, BIN); | |
Serial.println(" "); | |
delay(500); | |
// Start fan | |
my_status = start_measurement(); | |
// Serial print is used just for debugging | |
// But one can design a more complex code if desired | |
Serial.print("Start measurement status is "); | |
Serial.println(my_status, BIN); | |
Serial.println(" "); | |
delay(5000); | |
} | |
void loop() { | |
// Read the particle data every minute | |
my_status = read_measurement(); | |
// Serial print is used just for debugging | |
// But one can design a more complex code if desired | |
Serial.print("Read measurement status is "); | |
Serial.println(my_status, BIN); | |
Serial.print("PM2.5 value is "); | |
Serial.println(PM25, DEC); | |
Serial.print("PM10 value is "); | |
Serial.println(PM10, DEC); | |
Serial.println(" "); | |
// Wait one minute | |
delay(60000); | |
} | |
bool start_measurement(void) | |
{ | |
// First, we send the command | |
byte start_measurement[] = {0x68, 0x01, 0x01, 0x96 }; | |
Serial3.write(start_measurement, sizeof(start_measurement)); | |
//Then we wait for the response | |
while(Serial3.available() < 2); | |
char read1 = Serial3.read(); | |
char read2 = Serial3.read(); | |
// Test the response | |
if ((read1 == 0xA5) && (read2 == 0xA5)){ | |
// ACK | |
return 1; | |
} | |
else if ((read1 == 0x96) && (read2 == 0x96)) | |
{ | |
// NACK | |
return 0; | |
} | |
else return 0; | |
} | |
bool stop_measurement(void) | |
{ | |
// First, we send the command | |
byte stop_measurement[] = {0x68, 0x01, 0x02, 0x95 }; | |
Serial3.write(stop_measurement, sizeof(stop_measurement)); | |
//Then we wait for the response | |
while(Serial3.available() < 2); | |
char read1 = Serial3.read(); | |
char read2 = Serial3.read(); | |
// Test the response | |
if ((read1 == 0xA5) && (read2 == 0xA5)){ | |
// ACK | |
return 1; | |
} | |
else if ((read1 == 0x96) && (read2 == 0x96)) | |
{ | |
// NACK | |
return 0; | |
} | |
else return 0; | |
} | |
bool read_measurement (void) | |
{ | |
// Send the command 0x68 0x01 0x04 0x93 | |
byte read_particle[] = {0x68, 0x01, 0x04, 0x93 }; | |
Serial3.write(read_particle, sizeof(read_particle)); | |
// A measurement can return 0X9696 for NACK | |
// Or can return eight bytes if successful | |
// We wait for the first two bytes | |
while(Serial3.available() < 1); | |
byte HEAD = Serial3.read(); | |
while(Serial3.available() < 1); | |
byte LEN = Serial3.read(); | |
// Test the response | |
if ((HEAD == 0x96) && (LEN == 0x96)){ | |
// NACK | |
Serial.println("NACK"); | |
return 0; | |
} | |
else if ((HEAD == 0x40) && (LEN == 0x05)) | |
{ | |
// The measuremet is valid, read the rest of the data | |
// wait for the next byte | |
while(Serial3.available() < 1); | |
byte COMD = Serial3.read(); | |
while(Serial3.available() < 1); | |
byte DF1 = Serial3.read(); | |
while(Serial3.available() < 1); | |
byte DF2 = Serial3.read(); | |
while(Serial3.available() < 1); | |
byte DF3 = Serial3.read(); | |
while(Serial3.available() < 1); | |
byte DF4 = Serial3.read(); | |
while(Serial3.available() < 1); | |
byte CS = Serial3.read(); | |
// Now we shall verify the checksum | |
if (((0x10000 - HEAD - LEN - COMD - DF1 - DF2 - DF3 - DF4) % 0XFF) != CS){ | |
Serial.println("Checksum fail"); | |
return 0; | |
} | |
else | |
{ | |
// Checksum OK, we compute PM2.5 and PM10 values | |
PM25 = DF1 * 256 + DF2; | |
PM10 = DF3 * 256 + DF4; | |
return 1; | |
} | |
} | |
} | |
bool stop_autosend(void) | |
{ | |
// Stop auto send | |
byte stop_autosend[] = {0x68, 0x01, 0x20, 0x77 }; | |
Serial3.write(stop_autosend, sizeof(stop_autosend)); | |
//Then we wait for the response | |
while(Serial3.available() < 2); | |
char read1 = Serial3.read(); | |
char read2 = Serial3.read(); | |
// Test the response | |
if ((read1 == 0xA5) && (read2 == 0xA5)){ | |
// ACK | |
return 1; | |
} | |
else if ((read1 == 0x96) && (read2 == 0x96)) | |
{ | |
// NACK | |
return 0; | |
} | |
else return 0; | |
} | |
bool start_autosend(void) | |
{ | |
// Start auto send | |
byte start_autosend[] = {0x68, 0x01, 0x40, 0x57 }; | |
Serial3.write(start_autosend, sizeof(start_autosend)); | |
//Then we wait for the response | |
while(Serial3.available() < 2); | |
char read1 = Serial3.read(); | |
char read2 = Serial3.read(); | |
// Test the response | |
if ((read1 == 0xA5) && (read2 == 0xA5)){ | |
// ACK | |
return 1; | |
} | |
else if ((read1 == 0x96) && (read2 == 0x96)) | |
{ | |
// NACK | |
return 0; | |
} | |
else return 0; | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment