diff --git a/Adafruit_PM25AQI.cpp b/Adafruit_PM25AQI.cpp
index a6aee3b..010c7d0 100644
--- a/Adafruit_PM25AQI.cpp
+++ b/Adafruit_PM25AQI.cpp
@@ -9,6 +9,8 @@
* Arduino platform. It is designed specifically to work with the
* Adafruit PM2.5 Air quality sensors: http://www.adafruit.com/products/4632
*
+ * This library also works with the Cubic PM1006 UART Air Quality Sensor.
+ *
* These sensors use I2C or UART to communicate.
*
* Adafruit invests time and resources providing this open source code,
@@ -18,6 +20,8 @@
*
* @section author Author
* Written by Ladyada for Adafruit Industries.
+ * Modified by Brent Rubell for Adafruit Industries for use with Cubic PM1006
+ * Air Quality Sensor.
*
* @section license License
* BSD license, all text here must be included in any redistribution.
@@ -69,7 +73,10 @@ bool Adafruit_PM25AQI::begin_UART(Stream *theSerial) {
*/
bool Adafruit_PM25AQI::read(PM25_AQI_Data *data) {
uint8_t buffer[32];
+ size_t bufLen = sizeof(buffer);
uint16_t sum = 0;
+ uint8_t csum = 0;
+ bool is_pm1006 = false;
if (!data) {
return false;
@@ -83,48 +90,81 @@ bool Adafruit_PM25AQI::read(PM25_AQI_Data *data) {
if (!serial_dev->available()) {
return false;
}
+
int skipped = 0;
- while ((skipped < 32) && (serial_dev->peek() != 0x42)) {
+ while ((skipped < 32) && (serial_dev->peek() != 0x42) &&
+ (serial_dev->peek() != 0x16)) {
serial_dev->read();
skipped++;
if (!serial_dev->available()) {
return false;
}
}
- if (serial_dev->peek() != 0x42) {
+
+ // Check for the start character in the stream for both sensors
+ if ((serial_dev->peek() != 0x42) && (serial_dev->peek() != 0x16)) {
serial_dev->read();
return false;
}
- // Now read all 32 bytes
- if (serial_dev->available() < 32) {
+
+ // Are we using the Cubic PM1006 sensor?
+ if (serial_dev->peek() == 0x16) {
+ is_pm1006 = true; // Set flag to indicate we are using the PM1006
+ bufLen =
+ 20; // Reduce buffer read length to 20 bytes. Last 12 bytes ignored.
+ }
+
+ // Are there enough bytes to read from?
+ if (serial_dev->available() < bufLen) {
return false;
}
- serial_dev->readBytes(buffer, 32);
+
+ // Read all available bytes from the serial stream
+ serial_dev->readBytes(buffer, bufLen);
} else {
return false;
}
- // Check that start byte is correct!
- if (buffer[0] != 0x42) {
+ // Validate start byte is correct if using Adafruit PM sensors
+ if ((!is_pm1006 && buffer[0] != 0x42)) {
return false;
}
- // get checksum ready
- for (uint8_t i = 0; i < 30; i++) {
- sum += buffer[i];
+ // Validate start header is correct if using Cubic PM1006 sensor
+ if (is_pm1006 &&
+ (buffer[0] != 0x16 || buffer[1] != 0x11 || buffer[2] != 0x0B)) {
+ return false;
}
- // 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);
+ // Calculate checksum
+ if (!is_pm1006) {
+ for (uint8_t i = 0; i < 30; i++) {
+ sum += buffer[i];
+ }
+ } else {
+ for (uint8_t i = 0; i < bufLen; i++) {
+ csum += buffer[i];
+ }
}
- // put it into a nice struct :)
- memcpy((void *)data, (void *)buffer_u16, 30);
+ // Since header and checksum are OK, parse data from the buffer
+ if (!is_pm1006) {
+ // 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);
+ } else {
+ // Cubic PM1006 sensor only produces a pm25_env reading
+ data->pm25_env = (buffer[5] << 8) | buffer[6];
+ data->checksum = sum;
+ }
- if (sum != data->checksum) {
+ // Validate checksum
+ if ((is_pm1006 && csum != 0) || (!is_pm1006 && sum != data->checksum)) {
return false;
}
diff --git a/README.md b/README.md
index 527954a..3a50b4a 100644
--- a/README.md
+++ b/README.md
@@ -5,6 +5,8 @@ Tested and works great with the Adafruit PM2.5 Air Quality Sensor and Breadboard
[](https://www.adafruit.com/products/3686)
+This library also works with the Cubic PM1006 air quality sensor present on the [IKEA VINDSTYRKA](https://www.ikea.com/us/en/p/vindriktning-air-quality-sensor-60515911/). Please use the `pm1006_test.ino` sketch to use this sensor.
+
Adafruit invests time and resources providing this open source code, please support Adafruit and open-source hardware by purchasing products from Adafruit!
# Installation
diff --git a/examples/PM1006_test/.uno.test.skip b/examples/PM1006_test/.uno.test.skip
new file mode 100644
index 0000000..8b13789
--- /dev/null
+++ b/examples/PM1006_test/.uno.test.skip
@@ -0,0 +1 @@
+
diff --git a/examples/PM1006_test/PM1006_test.ino b/examples/PM1006_test/PM1006_test.ino
new file mode 100644
index 0000000..26faa11
--- /dev/null
+++ b/examples/PM1006_test/PM1006_test.ino
@@ -0,0 +1,71 @@
+/****************************************************************************************
+ Test sketch for using the Adafruit_PM25AQI library with
+ the Cubic PM1006 UART Air Quality Sensor.
+
+ This sensor is present on the VINDRIKTNING Air Quality sensor, sold by IKEA.
+
+ Check out the guide below for the wiring diagram:
+ https://learn.adafruit.com/ikea-vindriktning-hack-with-qt-py-esp32-s3-and-adafruit-io
+
+
+ Adafruit invests time and resources providing this open source code,
+ please support Adafruit and open-source hardware by purchasing
+ products from Adafruit!
+
+ Written by Limor Fried/Ladyada for Adafruit Industries.
+ Modified by Brent Rubell for Adafruit Industries
+ MIT license, all text above must be included in any redistribution
+ *****************************************************************************************/
+#include "Adafruit_PM25AQI.h"
+
+// For UNO and others (without hardware serial) we must use software serial...
+// pin #2 is IN from sensor (TX pin on sensor), leave pin #3 disconnected
+// comment these two lines if using hardware serial
+//#include
+//SoftwareSerial pmSerial(2, 3);
+
+Adafruit_PM25AQI aqi = Adafruit_PM25AQI();
+
+void setup() {
+ // Wait for serial monitor to open
+ Serial.begin(115200);
+ while (!Serial) delay(10);
+
+ Serial.println("Cubic PM1006 Air Quality Sensor");
+
+ // Wait one second for sensor to boot up!
+ delay(1000);
+
+ // If using serial, initialize it and set baudrate before starting!
+ Serial1.begin(9600);
+ // Uncomment the following for use with software serial
+ //pmSerial.begin(9600);
+
+ if (! aqi.begin_UART(&Serial1)) { // connect to the sensor over hardware serial
+ //if (! aqi.begin_UART(&pmSerial)) { // connect to the sensor over software serial
+ Serial.println("Could not find Cubic PM1006 sensor!");
+ while (1) delay(10);
+ }
+
+ Serial.println("Cubic PM1006 found!");
+}
+
+void loop() {
+ PM25_AQI_Data data;
+
+ if (! aqi.read(&data)) {
+ Serial.println("Could not read from PM1006 sensor");
+ delay(5000); // Sample every 5 seconds
+ return;
+ }
+ Serial.println("AQI reading success");
+
+ Serial.println();
+ Serial.println(F("---------------------------------------"));
+ Serial.println(F("Concentration Units (environmental)"));
+ Serial.println(F("---------------------------------------"));
+ Serial.print(F("PM 1.0: ")); Serial.print(data.pm25_env);
+ Serial.println(F("---------------------------------------"));
+
+ delay(20000); // Wait 20 seconds and get another reading from the IKEA Vindriktning
+}
diff --git a/library.properties b/library.properties
index e80ce02..402e5a3 100644
--- a/library.properties
+++ b/library.properties
@@ -1,5 +1,5 @@
name=Adafruit PM25 AQI Sensor
-version=1.0.8
+version=1.1.0
author=Adafruit
maintainer=Adafruit
sentence=This is an Arduino library for the Adafruit PM2.5 Air Quality Sensor