From fe18044edd176c45a78a79311eb2c3bf89e24740 Mon Sep 17 00:00:00 2001 From: CDaut Date: Mon, 14 Feb 2022 20:09:10 +0100 Subject: [PATCH] implemented async PM sensor sampling --- firmware/src/main.cpp | 24 +++++++++++---- firmware/src/sensors/PmSensor.cpp | 50 +++++++++++++++++-------------- firmware/src/sensors/PmSensor.h | 2 +- 3 files changed, 48 insertions(+), 28 deletions(-) diff --git a/firmware/src/main.cpp b/firmware/src/main.cpp index f9fc036..51b119b 100644 --- a/firmware/src/main.cpp +++ b/firmware/src/main.cpp @@ -14,11 +14,16 @@ Sensor *pmSensor; BluetoothServer *server; bool makeDiscoverable = false; - +//interrupt handler for sensor being pressed void IRAM_ATTR startBleServerAdvertising() { makeDiscoverable = true; } +//helper function to create task for PM measurement +void startPmAsyncSampling(void * param){ + ((PmSensor *) pmSensor)->startAsyncSampling(); +} + void setup() { //initialize a Serial Connection Serial.begin(BAUD_RATE); @@ -38,17 +43,25 @@ void setup() { attachInterrupt(digitalPinToInterrupt(INTERRUPT_MAKE_DISCOVERABLE_PIN), startBleServerAdvertising, RISING); + + //start an async task for measuring PM so the sensor won't block the whole system + xTaskCreate( + startPmAsyncSampling, + "Async PM sampling", + 1024, + nullptr, + 1, + nullptr + ); } void loop() { + //check if the button has been pressed and handle appropriately if (makeDiscoverable) { server->startAdvertising(); 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(); server->setPressure(sample.pressure); @@ -57,11 +70,12 @@ void loop() { 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", + 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); } \ No newline at end of file diff --git a/firmware/src/sensors/PmSensor.cpp b/firmware/src/sensors/PmSensor.cpp index 7e0fc03..b43a7bd 100644 --- a/firmware/src/sensors/PmSensor.cpp +++ b/firmware/src/sensors/PmSensor.cpp @@ -21,19 +21,35 @@ PmSensor::PmSensor() { this->PmSensor::sensor_setup(); } -void PmSensor::startAsyncSampling() { +[[noreturn]] void PmSensor::startAsyncSampling() { - this->enableStandbyMode(); - PmSensor::sensorWait(SLEEP_TIME); + Serial.println("Started async task for PM sensor sampling."); - this->wakeUp(); - sds011.perform_work(); + while (true) { + this->wakeUp(); - if (!sds011.query_data_auto_async(pm_tablesize, pm25_table, pm10_table)) { - Serial.println("measurement capture start failed"); + //attach a callback on what to do when data sampling is complete + sds011.on_query_data_auto_completed([this](int n) { + Serial.println("Sampled new PM data."); + 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; + } + }); + + if (!sds011.query_data_auto_async(pm_tablesize, pm25_table, pm10_table)) { + Serial.println("measurement capture start failed"); + } + + PmSensor::sensorWait(MEASURE_TIME); + + this->enableStandbyMode(); + PmSensor::sensorWait(SLEEP_TIME); } - - PmSensor::sensorWait(MEASURE_TIME); } /** @@ -41,6 +57,7 @@ void PmSensor::startAsyncSampling() { */ void PmSensor::enableStandbyMode() { if (sds011.set_sleep(true)) { this->state = SensorState::ASLEEP; } + Serial.println("PM sensor went to sleep mode."); } /** @@ -48,6 +65,7 @@ void PmSensor::enableStandbyMode() { */ void PmSensor::wakeUp() { if (sds011.set_sleep(false)) { this->state = SensorState::AWAKE; } + Serial.println("PM sensor woke up."); } /** @@ -64,18 +82,6 @@ void PmSensor::sensor_setup() { //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; - } - }); } /** @@ -85,7 +91,7 @@ void PmSensor::sensor_setup() { void PmSensor::sensorWait(int time) { uint32_t deadline = millis() + time * 1000; while (static_cast(deadline - millis()) > 0) { - delay(1000); + vTaskDelay(1000 / portTICK_PERIOD_MS); sds011.perform_work(); } } diff --git a/firmware/src/sensors/PmSensor.h b/firmware/src/sensors/PmSensor.h index 3a3bd84..626b586 100644 --- a/firmware/src/sensors/PmSensor.h +++ b/firmware/src/sensors/PmSensor.h @@ -17,7 +17,7 @@ public: sensor_data_t sample() override; - void startAsyncSampling(); + [[noreturn]] void startAsyncSampling(); void enableStandbyMode() override;