Compare commits

..

6 commits

19 changed files with 387 additions and 86 deletions

1
.envrc
View file

@ -1 +0,0 @@
use_flake

4
.gitignore vendored
View file

@ -444,4 +444,6 @@ obj/
# End of https://www.toptal.com/developers/gitignore/api/platformio,c,cmake,c++,intellij,android,androidstudio,clion+all,java # End of https://www.toptal.com/developers/gitignore/api/platformio,c,cmake,c++,intellij,android,androidstudio,clion+all,java
.direnv
###only in firmware_dev
ClimateGoApp/

View file

@ -1,3 +0,0 @@
{
"cmake.sourceDirectory": "/home/clara/repositorys/climate-go/firmware"
}

View file

@ -1,5 +1,5 @@
# Climate GO # Climate GO
Climate GO is a fully open source open hardware Sensor pack, to track and analyze personal air quality data. Its goal is to provide a way to monitor ones own air quality and motivate people to avoid polluted places and protect the environment. Climate GO is a fully open source open hardware Sensor pack, to track and analyze personal air quality data. It's goal is to provide a way to monitor ones own air quality and motivate people to avoid polluted places and protect the environment.
## Paradigms ## Paradigms
This project is intended to be open source, open hardware and open data oriented. It is of central importance to make this available to anyone who whishes to build a climate go device and to ensure no personal data is collected and stored. This is especially important because the climate data collected will be correlated with GPS information and could thus be used to construct a movement profile if not handled with uttermost care. This project is intended to be open source, open hardware and open data oriented. It is of central importance to make this available to anyone who whishes to build a climate go device and to ensure no personal data is collected and stored. This is especially important because the climate data collected will be correlated with GPS information and could thus be used to construct a movement profile if not handled with uttermost care.
@ -8,9 +8,9 @@ This project is intended to be open source, open hardware and open data oriented
### Stack ### Stack
The sensor pack itself is based around the ESP32 microprocessor and contains several sensors: The sensor pack itself is based around the ESP32 microprocessor and contains several sensors:
- BMP280 air pressure and temperature monitoring sensor - BMP280 air pressure and temperature monitoring sensor
- Nova SDS011 particulate matter sensor - [name] particulate matter sensor
- [name] CO2 sensor - [name] CO2 sensor
- MISC 2714 NO2 sensor - [name] NO2 sensor
A custom PCB/housing is yet to be designed and manufactured. Data collection is made possible by an Android App, that will connect to the sensor pack via Bluetooth low energy. It is imperative to design the sensor pack to be lightweight and consume as little as possible energy to ensure comfort in transporting the sensor pack (it is intended to be clipped to e.g. a backpack) and long battery life. A custom PCB/housing is yet to be designed and manufactured. Data collection is made possible by an Android App, that will connect to the sensor pack via Bluetooth low energy. It is imperative to design the sensor pack to be lightweight and consume as little as possible energy to ensure comfort in transporting the sensor pack (it is intended to be clipped to e.g. a backpack) and long battery life.

5
firmware/.gitignore vendored
View file

@ -1,5 +0,0 @@
.pio
.vscode/.browse.c_cpp.db*
.vscode/c_cpp_properties.json
.vscode/launch.json
.vscode/ipch

View file

@ -1,10 +0,0 @@
{
// See http://go.microsoft.com/fwlink/?LinkId=827846
// for the documentation about the extensions.json format
"recommendations": [
"platformio.platformio-ide"
],
"unwantedRecommendations": [
"ms-vscode.cpptools-extension-pack"
]
}

View file

@ -0,0 +1,152 @@
# !!! WARNING !!! AUTO-GENERATED FILE, PLEASE DO NOT MODIFY IT AND USE
# https://docs.platformio.org/page/projectconf/section_env_build.html#build-flags
#
# If you need to override existing CMake configuration or add extra,
# please create `CMakeListsUser.txt` in the root of project.
# The `CMakeListsUser.txt` will not be overwritten by PlatformIO.
set(CMAKE_CONFIGURATION_TYPES "esp32dev" CACHE STRING "Build Types reflect PlatformIO Environments" FORCE)
# Convert "Home Directory" that may contain unescaped backslashes on Windows
SET(CMAKE_C_COMPILER "$ENV{HOME}/.platformio/packages/toolchain-xtensa32/bin/xtensa-esp32-elf-gcc")
SET(CMAKE_CXX_COMPILER "$ENV{HOME}/.platformio/packages/toolchain-xtensa32/bin/xtensa-esp32-elf-g++")
SET(CMAKE_CXX_FLAGS "-fno-rtti -fno-exceptions -std=gnu++11 -Os -g3 -Wall -nostdlib -Wpointer-arith -Wno-error=unused-but-set-variable -Wno-error=unused-variable -mlongcalls -ffunction-sections -fdata-sections -fstrict-volatile-bitfields -Wno-error=deprecated-declarations -Wno-error=unused-function -Wno-unused-parameter -Wno-sign-compare -fstack-protector -fexceptions -Werror=reorder")
SET(CMAKE_C_FLAGS "-std=gnu99 -Wno-old-style-declaration -Os -g3 -Wall -nostdlib -Wpointer-arith -Wno-error=unused-but-set-variable -Wno-error=unused-variable -mlongcalls -ffunction-sections -fdata-sections -fstrict-volatile-bitfields -Wno-error=deprecated-declarations -Wno-error=unused-function -Wno-unused-parameter -Wno-sign-compare -fstack-protector -fexceptions -Werror=reorder")
SET(CMAKE_C_STANDARD 99)
set(CMAKE_CXX_STANDARD 11)
if (CMAKE_BUILD_TYPE MATCHES "esp32dev")
add_definitions(-DPLATFORMIO=50205)
add_definitions(-DARDUINO_ESP32_DEV)
add_definitions(-DESP32)
add_definitions(-DESP_PLATFORM)
add_definitions(-DF_CPU=240000000L)
add_definitions(-DHAVE_CONFIG_H)
add_definitions(-DMBEDTLS_CONFIG_FILE=\"mbedtls/esp_config.h\")
add_definitions(-DARDUINO=10805)
add_definitions(-DARDUINO_ARCH_ESP32)
add_definitions(-DARDUINO_VARIANT=\"esp32\")
add_definitions(-DARDUINO_BOARD=\"Espressif\ ESP32\ Dev\ Module\")
include_directories("${CMAKE_CURRENT_LIST_DIR}/include")
include_directories("${CMAKE_CURRENT_LIST_DIR}/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 BusIO")
include_directories("$ENV{HOME}/.platformio/packages/framework-arduinoespressif32/libraries/SPI/src")
include_directories("$ENV{HOME}/.platformio/packages/framework-arduinoespressif32/libraries/Wire/src")
include_directories("${CMAKE_CURRENT_LIST_DIR}/.pio/libdeps/esp32dev/Adafruit Unified Sensor")
include_directories("$ENV{HOME}/.platformio/packages/framework-arduinoespressif32/tools/sdk/include/config")
include_directories("$ENV{HOME}/.platformio/packages/framework-arduinoespressif32/tools/sdk/include/app_trace")
include_directories("$ENV{HOME}/.platformio/packages/framework-arduinoespressif32/tools/sdk/include/app_update")
include_directories("$ENV{HOME}/.platformio/packages/framework-arduinoespressif32/tools/sdk/include/asio")
include_directories("$ENV{HOME}/.platformio/packages/framework-arduinoespressif32/tools/sdk/include/bootloader_support")
include_directories("$ENV{HOME}/.platformio/packages/framework-arduinoespressif32/tools/sdk/include/bt")
include_directories("$ENV{HOME}/.platformio/packages/framework-arduinoespressif32/tools/sdk/include/coap")
include_directories("$ENV{HOME}/.platformio/packages/framework-arduinoespressif32/tools/sdk/include/console")
include_directories("$ENV{HOME}/.platformio/packages/framework-arduinoespressif32/tools/sdk/include/driver")
include_directories("$ENV{HOME}/.platformio/packages/framework-arduinoespressif32/tools/sdk/include/efuse")
include_directories("$ENV{HOME}/.platformio/packages/framework-arduinoespressif32/tools/sdk/include/esp-tls")
include_directories("$ENV{HOME}/.platformio/packages/framework-arduinoespressif32/tools/sdk/include/esp32")
include_directories("$ENV{HOME}/.platformio/packages/framework-arduinoespressif32/tools/sdk/include/esp_adc_cal")
include_directories("$ENV{HOME}/.platformio/packages/framework-arduinoespressif32/tools/sdk/include/esp_event")
include_directories("$ENV{HOME}/.platformio/packages/framework-arduinoespressif32/tools/sdk/include/esp_http_client")
include_directories("$ENV{HOME}/.platformio/packages/framework-arduinoespressif32/tools/sdk/include/esp_http_server")
include_directories("$ENV{HOME}/.platformio/packages/framework-arduinoespressif32/tools/sdk/include/esp_https_ota")
include_directories("$ENV{HOME}/.platformio/packages/framework-arduinoespressif32/tools/sdk/include/esp_https_server")
include_directories("$ENV{HOME}/.platformio/packages/framework-arduinoespressif32/tools/sdk/include/esp_ringbuf")
include_directories("$ENV{HOME}/.platformio/packages/framework-arduinoespressif32/tools/sdk/include/esp_websocket_client")
include_directories("$ENV{HOME}/.platformio/packages/framework-arduinoespressif32/tools/sdk/include/espcoredump")
include_directories("$ENV{HOME}/.platformio/packages/framework-arduinoespressif32/tools/sdk/include/ethernet")
include_directories("$ENV{HOME}/.platformio/packages/framework-arduinoespressif32/tools/sdk/include/expat")
include_directories("$ENV{HOME}/.platformio/packages/framework-arduinoespressif32/tools/sdk/include/fatfs")
include_directories("$ENV{HOME}/.platformio/packages/framework-arduinoespressif32/tools/sdk/include/freemodbus")
include_directories("$ENV{HOME}/.platformio/packages/framework-arduinoespressif32/tools/sdk/include/freertos")
include_directories("$ENV{HOME}/.platformio/packages/framework-arduinoespressif32/tools/sdk/include/heap")
include_directories("$ENV{HOME}/.platformio/packages/framework-arduinoespressif32/tools/sdk/include/idf_test")
include_directories("$ENV{HOME}/.platformio/packages/framework-arduinoespressif32/tools/sdk/include/jsmn")
include_directories("$ENV{HOME}/.platformio/packages/framework-arduinoespressif32/tools/sdk/include/json")
include_directories("$ENV{HOME}/.platformio/packages/framework-arduinoespressif32/tools/sdk/include/libsodium")
include_directories("$ENV{HOME}/.platformio/packages/framework-arduinoespressif32/tools/sdk/include/log")
include_directories("$ENV{HOME}/.platformio/packages/framework-arduinoespressif32/tools/sdk/include/lwip")
include_directories("$ENV{HOME}/.platformio/packages/framework-arduinoespressif32/tools/sdk/include/mbedtls")
include_directories("$ENV{HOME}/.platformio/packages/framework-arduinoespressif32/tools/sdk/include/mdns")
include_directories("$ENV{HOME}/.platformio/packages/framework-arduinoespressif32/tools/sdk/include/micro-ecc")
include_directories("$ENV{HOME}/.platformio/packages/framework-arduinoespressif32/tools/sdk/include/mqtt")
include_directories("$ENV{HOME}/.platformio/packages/framework-arduinoespressif32/tools/sdk/include/newlib")
include_directories("$ENV{HOME}/.platformio/packages/framework-arduinoespressif32/tools/sdk/include/nghttp")
include_directories("$ENV{HOME}/.platformio/packages/framework-arduinoespressif32/tools/sdk/include/nvs_flash")
include_directories("$ENV{HOME}/.platformio/packages/framework-arduinoespressif32/tools/sdk/include/openssl")
include_directories("$ENV{HOME}/.platformio/packages/framework-arduinoespressif32/tools/sdk/include/protobuf-c")
include_directories("$ENV{HOME}/.platformio/packages/framework-arduinoespressif32/tools/sdk/include/protocomm")
include_directories("$ENV{HOME}/.platformio/packages/framework-arduinoespressif32/tools/sdk/include/pthread")
include_directories("$ENV{HOME}/.platformio/packages/framework-arduinoespressif32/tools/sdk/include/sdmmc")
include_directories("$ENV{HOME}/.platformio/packages/framework-arduinoespressif32/tools/sdk/include/smartconfig_ack")
include_directories("$ENV{HOME}/.platformio/packages/framework-arduinoespressif32/tools/sdk/include/soc")
include_directories("$ENV{HOME}/.platformio/packages/framework-arduinoespressif32/tools/sdk/include/spi_flash")
include_directories("$ENV{HOME}/.platformio/packages/framework-arduinoespressif32/tools/sdk/include/spiffs")
include_directories("$ENV{HOME}/.platformio/packages/framework-arduinoespressif32/tools/sdk/include/tcp_transport")
include_directories("$ENV{HOME}/.platformio/packages/framework-arduinoespressif32/tools/sdk/include/tcpip_adapter")
include_directories("$ENV{HOME}/.platformio/packages/framework-arduinoespressif32/tools/sdk/include/ulp")
include_directories("$ENV{HOME}/.platformio/packages/framework-arduinoespressif32/tools/sdk/include/unity")
include_directories("$ENV{HOME}/.platformio/packages/framework-arduinoespressif32/tools/sdk/include/vfs")
include_directories("$ENV{HOME}/.platformio/packages/framework-arduinoespressif32/tools/sdk/include/wear_levelling")
include_directories("$ENV{HOME}/.platformio/packages/framework-arduinoespressif32/tools/sdk/include/wifi_provisioning")
include_directories("$ENV{HOME}/.platformio/packages/framework-arduinoespressif32/tools/sdk/include/wpa_supplicant")
include_directories("$ENV{HOME}/.platformio/packages/framework-arduinoespressif32/tools/sdk/include/xtensa-debug-module")
include_directories("$ENV{HOME}/.platformio/packages/framework-arduinoespressif32/tools/sdk/include/esp-face")
include_directories("$ENV{HOME}/.platformio/packages/framework-arduinoespressif32/tools/sdk/include/esp32-camera")
include_directories("$ENV{HOME}/.platformio/packages/framework-arduinoespressif32/tools/sdk/include/fb_gfx")
include_directories("$ENV{HOME}/.platformio/packages/framework-arduinoespressif32/cores/esp32")
include_directories("$ENV{HOME}/.platformio/packages/framework-arduinoespressif32/variants/esp32")
include_directories("$ENV{HOME}/.platformio/packages/framework-arduinoespressif32/libraries/ArduinoOTA/src")
include_directories("$ENV{HOME}/.platformio/packages/framework-arduinoespressif32/libraries/AsyncUDP/src")
include_directories("$ENV{HOME}/.platformio/packages/framework-arduinoespressif32/libraries/AzureIoT/src")
include_directories("$ENV{HOME}/.platformio/packages/framework-arduinoespressif32/libraries/BluetoothSerial/src")
include_directories("$ENV{HOME}/.platformio/packages/framework-arduinoespressif32/libraries/DNSServer/src")
include_directories("$ENV{HOME}/.platformio/packages/framework-arduinoespressif32/libraries/EEPROM/src")
include_directories("$ENV{HOME}/.platformio/packages/framework-arduinoespressif32/libraries/ESP32/src")
include_directories("$ENV{HOME}/.platformio/packages/framework-arduinoespressif32/libraries/ESPmDNS/src")
include_directories("$ENV{HOME}/.platformio/packages/framework-arduinoespressif32/libraries/FFat/src")
include_directories("$ENV{HOME}/.platformio/packages/framework-arduinoespressif32/libraries/FS/src")
include_directories("$ENV{HOME}/.platformio/packages/framework-arduinoespressif32/libraries/HTTPClient/src")
include_directories("$ENV{HOME}/.platformio/packages/framework-arduinoespressif32/libraries/HTTPUpdate/src")
include_directories("$ENV{HOME}/.platformio/packages/framework-arduinoespressif32/libraries/HTTPUpdateServer/src")
include_directories("$ENV{HOME}/.platformio/packages/framework-arduinoespressif32/libraries/NetBIOS/src")
include_directories("$ENV{HOME}/.platformio/packages/framework-arduinoespressif32/libraries/Preferences/src")
include_directories("$ENV{HOME}/.platformio/packages/framework-arduinoespressif32/libraries/SD/src")
include_directories("$ENV{HOME}/.platformio/packages/framework-arduinoespressif32/libraries/SD_MMC/src")
include_directories("$ENV{HOME}/.platformio/packages/framework-arduinoespressif32/libraries/SPIFFS/src")
include_directories("$ENV{HOME}/.platformio/packages/framework-arduinoespressif32/libraries/SimpleBLE/src")
include_directories("$ENV{HOME}/.platformio/packages/framework-arduinoespressif32/libraries/Ticker/src")
include_directories("$ENV{HOME}/.platformio/packages/framework-arduinoespressif32/libraries/Update/src")
include_directories("$ENV{HOME}/.platformio/packages/framework-arduinoespressif32/libraries/WebServer/src")
include_directories("$ENV{HOME}/.platformio/packages/framework-arduinoespressif32/libraries/WiFi/src")
include_directories("$ENV{HOME}/.platformio/packages/framework-arduinoespressif32/libraries/WiFiClientSecure/src")
include_directories("$ENV{HOME}/.platformio/packages/framework-arduinoespressif32/libraries/WiFiProv/src")
include_directories("$ENV{HOME}/.platformio/packages/toolchain-xtensa32/xtensa-esp32-elf/include/c++/5.2.0")
include_directories("$ENV{HOME}/.platformio/packages/toolchain-xtensa32/xtensa-esp32-elf/include/c++/5.2.0/xtensa-esp32-elf")
include_directories("$ENV{HOME}/.platformio/packages/toolchain-xtensa32/lib/gcc/xtensa-esp32-elf/5.2.0/include-fixed")
include_directories("$ENV{HOME}/.platformio/packages/toolchain-xtensa32/lib/gcc/xtensa-esp32-elf/5.2.0/include")
include_directories("$ENV{HOME}/.platformio/packages/toolchain-xtensa32/xtensa-esp32-elf/include")
FILE(GLOB_RECURSE EXTRA_LIB_SOURCES
${CMAKE_CURRENT_LIST_DIR}/.pio/libdeps/esp32dev/*.*
)
endif()
FILE(GLOB_RECURSE SRC_LIST
${CMAKE_CURRENT_LIST_DIR}/src/*.*
${CMAKE_CURRENT_LIST_DIR}/lib/*.*
${CMAKE_CURRENT_LIST_DIR}/test/*.*
)
list(APPEND SRC_LIST ${EXTRA_LIB_SOURCES})

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

@ -8,6 +8,8 @@
#define SERVICE_UUID "2150123c-af53-4038-bc92-ba3d0870a9e4" #define SERVICE_UUID "2150123c-af53-4038-bc92-ba3d0870a9e4"
#define TEMPERATURE_CHARACTERISTIC_UUID "cba1d466-344c-4be3-ab3f-189f80dd7518" #define TEMPERATURE_CHARACTERISTIC_UUID "cba1d466-344c-4be3-ab3f-189f80dd7518"
#define PRESSURE_CHARACTERISTIC_UUID "ca73b3ba-39f6-4ab3-91ae-186dc9577d99" #define PRESSURE_CHARACTERISTIC_UUID "ca73b3ba-39f6-4ab3-91ae-186dc9577d99"
#define BLINK_TIME_DELAY_MS 500
#define BLINK_TIMES 5
//Setup callbacks onConnect and onDisconnect //Setup callbacks onConnect and onDisconnect
class ServerCallbacks : public BLEServerCallbacks { class ServerCallbacks : public BLEServerCallbacks {
@ -51,6 +53,9 @@ BluetoothServer::BluetoothServer() {
//set initial values //set initial values
temperatureCharacteristic->setValue("NA"); temperatureCharacteristic->setValue("NA");
pressureCharacteristic->setValue("NA"); pressureCharacteristic->setValue("NA");
//allow advertiser function to be called
this->advertiserLock = false;
} }
/** /**
@ -89,4 +94,22 @@ void BluetoothServer::setPressure(float pressure) {
->setValue(pressure); ->setValue(pressure);
} }
/**
* This method will start advertising via Bluetooth and blink the LED
*/
void BluetoothServer::startAdvertising() {
if (!this->advertiserLock) {
this->advertiserLock = true;
this->bleServer->getAdvertising()->start();
Serial.println("Starting Bluetooth advertising...");
for (int i = 0; i < BLINK_TIMES; ++i) {
digitalWrite(INTERNAL_LED_PIN, HIGH);
delay(BLINK_TIME_DELAY_MS);
digitalWrite(INTERNAL_LED_PIN, LOW);
delay(BLINK_TIME_DELAY_MS);
}
this->advertiserLock = false;
}
}

View file

@ -13,9 +13,11 @@ class BluetoothServer {
private: private:
BLEService *sensorService; BLEService *sensorService;
BLEServer *bleServer; BLEServer *bleServer;
bool advertiserLock;
public: public:
BluetoothServer(); BluetoothServer();
void startAdvertising();
void startServer(); void startServer();
void setTemperature(float temperature); void setTemperature(float temperature);
void setPressure(float pressure); void setPressure(float pressure);

View file

@ -1,28 +1,81 @@
#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 2 #define SLEEP_TIME 1
#define BAUD_RATE 112500 #define BAUD_RATE 112500
#define INTERNAL_LED_PIN 2 #define INTERNAL_LED_PIN 2
#define INTERRUPT_MAKE_DISCOVERABLE_PIN 15
Sensor *bmpSensor; Sensor *bmpSensor;
Sensor *pmSensor;
BluetoothServer *server; 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() { 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();
//set up Interrupt to enable make discoverable button
pinMode(INTERRUPT_MAKE_DISCOVERABLE_PIN, INPUT_PULLDOWN);
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() { void loop() {
//check if the button has been pressed and handle appropriately
if (makeDiscoverable) {
server->startAdvertising();
makeDiscoverable = false;
}
//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,101 @@
#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();
}
[[noreturn]] void PmSensor::startAsyncSampling() {
Serial.println("Started async task for PM sensor sampling.");
while (true) {
this->wakeUp();
//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);
}
}
/**
* Put the sensor to standby mode
*/
void PmSensor::enableStandbyMode() {
if (sds011.set_sleep(true)) { this->state = SensorState::ASLEEP; }
Serial.println("PM sensor went to sleep mode.");
}
/**
* Activate the sensor
*/
void PmSensor::wakeUp() {
if (sds011.set_sleep(false)) { this->state = SensorState::AWAKE; }
Serial.println("PM sensor woke up.");
}
/**
* 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.");
}
/**
* 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) {
vTaskDelay(1000 / portTICK_PERIOD_MS);
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;
[[noreturn]] 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

27
flake.lock generated
View file

@ -1,27 +0,0 @@
{
"nodes": {
"nixpkgs": {
"locked": {
"lastModified": 1728241625,
"narHash": "sha256-yumd4fBc/hi8a9QgA9IT8vlQuLZ2oqhkJXHPKxH/tRw=",
"owner": "nixos",
"repo": "nixpkgs",
"rev": "c31898adf5a8ed202ce5bea9f347b1c6871f32d1",
"type": "github"
},
"original": {
"owner": "nixos",
"ref": "nixos-unstable",
"repo": "nixpkgs",
"type": "github"
}
},
"root": {
"inputs": {
"nixpkgs": "nixpkgs"
}
}
},
"root": "root",
"version": 7
}

View file

@ -1,25 +0,0 @@
{
description = "A Nix-flake-based PlatformIO development environment";
inputs.nixpkgs.url = "github:nixos/nixpkgs/nixos-unstable";
outputs = { self, nixpkgs }:
let
supportedSystems = [ "x86_64-linux" "aarch64-linux" "x86_64-darwin" "aarch64-darwin" ];
forEachSupportedSystem = f: nixpkgs.lib.genAttrs supportedSystems (system: f {
pkgs = import nixpkgs { inherit system; };
});
in
{
devShells = forEachSupportedSystem ({ pkgs }: {
default = pkgs.mkShell {
packages = with pkgs; [
platformio-core
openocd
python3
platformio
];
};
});
};
}