started implementing PM sensor

This commit is contained in:
Clemens-Dautermann 2022-02-14 18:39:31 +01:00 committed by Clemens-Dautermann
parent 8097446a16
commit 89d6acf181
9 changed files with 165 additions and 8 deletions

View file

@ -21,7 +21,7 @@ SET(CMAKE_C_STANDARD 99)
set(CMAKE_CXX_STANDARD 11) set(CMAKE_CXX_STANDARD 11)
if (CMAKE_BUILD_TYPE MATCHES "esp32dev") if (CMAKE_BUILD_TYPE MATCHES "esp32dev")
add_definitions(-DPLATFORMIO=50204) add_definitions(-DPLATFORMIO=50205)
add_definitions(-DARDUINO_ESP32_DEV) add_definitions(-DARDUINO_ESP32_DEV)
add_definitions(-DESP32) add_definitions(-DESP32)
add_definitions(-DESP_PLATFORM) add_definitions(-DESP_PLATFORM)
@ -36,6 +36,8 @@ if (CMAKE_BUILD_TYPE MATCHES "esp32dev")
include_directories("${CMAKE_CURRENT_LIST_DIR}/include") include_directories("${CMAKE_CURRENT_LIST_DIR}/include")
include_directories("${CMAKE_CURRENT_LIST_DIR}/src") include_directories("${CMAKE_CURRENT_LIST_DIR}/src")
include_directories("$ENV{HOME}/.platformio/packages/framework-arduinoespressif32/libraries/BLE/src") include_directories("$ENV{HOME}/.platformio/packages/framework-arduinoespressif32/libraries/BLE/src")
include_directories("${CMAKE_CURRENT_LIST_DIR}/.pio/libdeps/esp32dev/esp_sds011/src")
include_directories("${CMAKE_CURRENT_LIST_DIR}/.pio/libdeps/esp32dev/EspSoftwareSerial/src")
include_directories("${CMAKE_CURRENT_LIST_DIR}/.pio/libdeps/esp32dev/Adafruit BMP280 Library") include_directories("${CMAKE_CURRENT_LIST_DIR}/.pio/libdeps/esp32dev/Adafruit BMP280 Library")
include_directories("${CMAKE_CURRENT_LIST_DIR}/.pio/libdeps/esp32dev/Adafruit BusIO") include_directories("${CMAKE_CURRENT_LIST_DIR}/.pio/libdeps/esp32dev/Adafruit BusIO")
include_directories("$ENV{HOME}/.platformio/packages/framework-arduinoespressif32/libraries/SPI/src") include_directories("$ENV{HOME}/.platformio/packages/framework-arduinoespressif32/libraries/SPI/src")

View file

@ -13,3 +13,4 @@ platform = espressif32
board = esp32dev board = esp32dev
framework = arduino framework = arduino
lib_deps = adafruit/Adafruit BMP280 Library@^2.6.1 lib_deps = adafruit/Adafruit BMP280 Library@^2.6.1
dok-net/esp_sds011@^1.0.0

View file

@ -1,6 +1,7 @@
#include <Arduino.h> #include <Arduino.h>
#include <sensors/BmpSensor.h> #include <sensors/BmpSensor.h>
#include <ble/BluetoothServer.h> #include <ble/BluetoothServer.h>
#include <sensors/PmSensor.h>
#define SLEEP_TIME 1 #define SLEEP_TIME 1
#define BAUD_RATE 112500 #define BAUD_RATE 112500
@ -9,6 +10,7 @@
Sensor *bmpSensor; Sensor *bmpSensor;
Sensor *pmSensor;
BluetoothServer *server; BluetoothServer *server;
bool makeDiscoverable = false; bool makeDiscoverable = false;
@ -18,11 +20,16 @@ void IRAM_ATTR startBleServerAdvertising() {
} }
void setup() { void setup() {
//initialize a Serial Connection
Serial.begin(BAUD_RATE); Serial.begin(BAUD_RATE);
//setup the internal LED
pinMode(INTERNAL_LED_PIN, OUTPUT); pinMode(INTERNAL_LED_PIN, OUTPUT);
//create sensor objects
bmpSensor = new BmpSensor(); bmpSensor = new BmpSensor();
pmSensor = new PmSensor();
//setup & start Bluetooth server
server = new BluetoothServer(); server = new BluetoothServer();
server->startServer(); server->startServer();
@ -39,8 +46,22 @@ void loop() {
makeDiscoverable = false; makeDiscoverable = false;
} }
//setup PM sensor measurement TODO: This blocks for 120 seconds and needs to be executed asynchronously
//((PmSensor *) pmSensor)->startAsyncSampling();
//obtain measurement from BMP280 Sensor
sensor_data_t sample = ((BmpSensor *) bmpSensor)->sampleLowEnergy(); sensor_data_t sample = ((BmpSensor *) bmpSensor)->sampleLowEnergy();
server->setPressure(sample.pressure); server->setPressure(sample.pressure);
server->setTemperature(sample.temperature); server->setTemperature(sample.temperature);
//Obtain measurement from PM Sensor
sensor_data_t pmSample = pmSensor->sample();
//Print measured data
Serial.printf("Pressure: %f hPa | Temperature: %f °C | PM10: %f ppm| PM2.5: %f ppm\n",
sample.pressure,
sample.temperature,
pmSample.pm10,
pmSample.pm25);
//wait for one measurement cycle
delay(SLEEP_TIME * 1000); delay(SLEEP_TIME * 1000);
} }

View file

@ -69,7 +69,9 @@ sensor_data_t BmpSensor::sample() {
return sensor_data_t return sensor_data_t
{ {
temp_event.temperature, temp_event.temperature,
pressure_event.pressure pressure_event.pressure,
0.0,
0.0
}; };
} }

View file

@ -14,6 +14,7 @@ public:
BmpSensor(); BmpSensor();
sensor_data_t sample() override; sensor_data_t sample() override;
sensor_data_t sampleLowEnergy(); sensor_data_t sampleLowEnergy();
void enableStandbyMode() override; void enableStandbyMode() override;

View file

@ -0,0 +1,95 @@
#include "PmSensor.h"
#include <SoftwareSerial.h>
#include <Sds011.h>
#define SDS_PIN_RX 18
#define SDS_PIN_TX 19
#define SENSOR_BAUD_RATE 9600
#define SLEEP_TIME 90
#define MEASURE_TIME 30
#ifdef ESP32
HardwareSerial &serialSDS(Serial2);
Sds011Async<HardwareSerial> sds011(serialSDS);
#else
SoftwareSerial serialSDS;
Sds011Async< SoftwareSerial > sds011(serialSDS);
#endif
PmSensor::PmSensor() {
this->PmSensor::sensor_setup();
}
void PmSensor::startAsyncSampling() {
this->enableStandbyMode();
PmSensor::sensorWait(SLEEP_TIME);
this->wakeUp();
sds011.perform_work();
if (!sds011.query_data_auto_async(pm_tablesize, pm25_table, pm10_table)) {
Serial.println("measurement capture start failed");
}
PmSensor::sensorWait(MEASURE_TIME);
}
/**
* Put the sensor to standby mode
*/
void PmSensor::enableStandbyMode() {
if (sds011.set_sleep(true)) { this->state = SensorState::ASLEEP; }
}
/**
* Activate the sensor
*/
void PmSensor::wakeUp() {
if (sds011.set_sleep(false)) { this->state = SensorState::AWAKE; }
}
/**
* Method to set up and initialize the sensor
*/
void PmSensor::sensor_setup() {
#ifdef ESP32
serialSDS.begin(SENSOR_BAUD_RATE, SERIAL_8N1, SDS_PIN_RX, SDS_PIN_TX);
delay(100);
#else
serialSDS.begin(SENSOR_BAUD_RATE, SWSERIAL_8N1, SDS_PIN_RX, SDS_PIN_TX, false, 192);
#endif
//put the sensor into standby mode initially
this->PmSensor::enableStandbyMode();
Serial.println("SDS011 sensor initialized to standby mode.");
//attach a callback on what to do when data sampling is complete
sds011.on_query_data_auto_completed([this](int n) {
int pm25;
int pm10;
if (sds011.filter_data(n, pm25_table, pm10_table, pm25, pm10) &&
!isnan(pm10) && !isnan(pm25)) {
//set the right values
this->latestPM10 = float(pm10) / 10;
this->latestPM25 = float(pm25) / 10;
}
});
}
/**
* Method to wait for some time and perform the appropriate task
* @param time the time to wait for in seconds
*/
void PmSensor::sensorWait(int time) {
uint32_t deadline = millis() + time * 1000;
while (static_cast<int32_t>(deadline - millis()) > 0) {
delay(1000);
sds011.perform_work();
}
}
sensor_data_t PmSensor::sample() {
return {0.0, 0.0, this->latestPM10, this->latestPM25};
}

View file

@ -0,0 +1,35 @@
#ifndef FIRMWARE_PMSENSOR_H
#define FIRMWARE_PMSENSOR_H
#include "Sensor.h"
#include "sensor_data_t.h"
class PmSensor : public Sensor {
public:
static const int pm_tablesize = 20;
int pm25_table[pm_tablesize];
int pm10_table[pm_tablesize];
float latestPM10;
float latestPM25;
PmSensor();
sensor_data_t sample() override;
void startAsyncSampling();
void enableStandbyMode() override;
void wakeUp() override;
protected:
void sensor_setup() override;
private:
static void sensorWait(int time);
};
#endif //FIRMWARE_PMSENSOR_H

View file

@ -1,5 +1,5 @@
#ifndef NEW_CLIMTE_GO_SENSOR_H #ifndef FIRMWARE_SENSOR_H
#define NEW_CLIMTE_GO_SENSOR_H #define FIRMWARE_SENSOR_H
#include <sensors/sensor_data_t.h> #include <sensors/sensor_data_t.h>

View file

@ -1,7 +1,5 @@
#ifndef NEW_CLIMTE_GO_SENSOR_DATA_T_H #ifndef FIRMWARE_SENSOR_DATA_T_H
#define NEW_CLIMTE_GO_SENSOR_DATA_T_H #define FIRMWARE_SENSOR_DATA_T_H
#include <types.h>
/** /**
* This struct represents data read from any sensor. * This struct represents data read from any sensor.
@ -11,6 +9,8 @@
struct sensor_data_t { struct sensor_data_t {
float temperature; float temperature;
float pressure; float pressure;
float pm10;
float pm25;
}; };
#endif #endif