commit
1a76984a16
@ -58,7 +58,7 @@ Depending on board hardware following features are supported:
|
|||||||
- Silicon unique ID
|
- Silicon unique ID
|
||||||
- Battery voltage monitoring
|
- Battery voltage monitoring
|
||||||
- GPS (Generic serial NMEA, or Quectel L76 I2C)
|
- GPS (Generic serial NMEA, or Quectel L76 I2C)
|
||||||
- Environmental sensor (Bosch BMP180/BME280/BME680 I2C)
|
- Environmental sensors (Bosch BMP180/BME280/BME680 I2C; SDS011 serial)
|
||||||
- Real Time Clock (Maxim DS3231 I2C)
|
- Real Time Clock (Maxim DS3231 I2C)
|
||||||
- IF482 (serial) and DCF77 (gpio) time telegram generator
|
- IF482 (serial) and DCF77 (gpio) time telegram generator
|
||||||
- Switch external power / battery
|
- Switch external power / battery
|
||||||
@ -167,7 +167,7 @@ by pressing the button of the device.
|
|||||||
|
|
||||||
# Sensors and Peripherals
|
# Sensors and Peripherals
|
||||||
|
|
||||||
You can add up to 3 user defined sensors. Insert sensor's payload scheme in [*sensor.cpp*](src/sensor.cpp). Bosch BMP180 / BME280 / BME680 environment sensors are supported. Enable flag *lib_deps_sensors* for your board in [*platformio.ini*](src/platformio.ini) and configure BME in board's hal file before build. If you need Bosch's proprietary BSEC libraray (e.g. to get indoor air quality value from BME680) further enable *build_flags_sensors*, which comes on the price of reduced RAM and increased build size. RTC DS3231, generic serial NMEA GPS, I2C LoPy GPS are supported, and to be configured in board's hal file. See [*generic.h*](src/hal/generic.h) for all options and for proper configuration of BME280/BME680.
|
You can add up to 3 user defined sensors. Insert sensor's payload scheme in [*sensor.cpp*](src/sensor.cpp). Bosch BMP180 / BME280 / BME680 environment sensors are supported. Enable flag *lib_deps_sensors* for your board in [*platformio.ini*](src/platformio.ini) and configure BME in board's hal file before build. If you need Bosch's proprietary BSEC libraray (e.g. to get indoor air quality value from BME680) further enable *build_flags_sensors*, which comes on the price of reduced RAM and increased build size. Furthermore, SDS011, RTC DS3231, generic serial NMEA GPS, I2C LoPy GPS are supported, and to be configured in board's hal file. See [*generic.h*](src/hal/generic.h) for all options and for proper configuration of BME280/BME680.
|
||||||
|
|
||||||
Output of user sensor data can be switched by user remote control command 0x14 sent to Port 2.
|
Output of user sensor data can be switched by user remote control command 0x14 sent to Port 2.
|
||||||
|
|
||||||
@ -548,4 +548,4 @@ Thanks to
|
|||||||
- [terrillmoore](https://github.com/mcci-catena) for maintaining the LMIC for arduino LoRaWAN stack
|
- [terrillmoore](https://github.com/mcci-catena) for maintaining the LMIC for arduino LoRaWAN stack
|
||||||
- [sbamueller](https://github.com/sbamueller) for writing the tutorial in Make Magazine
|
- [sbamueller](https://github.com/sbamueller) for writing the tutorial in Make Magazine
|
||||||
- [Stefan](https://github.com/nerdyscout) for paxcounter opensensebox integration
|
- [Stefan](https://github.com/nerdyscout) for paxcounter opensensebox integration
|
||||||
- [August Quint](https://github.com/AugustQu) for adding SD card data logger support
|
- [August Quint](https://github.com/AugustQu) for adding SD card data logger and SDS011 support
|
||||||
|
@ -18,6 +18,15 @@
|
|||||||
#include "display.h"
|
#include "display.h"
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
#if (HAS_SDS011)
|
||||||
|
#include "sds011read.h"
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#if (HAS_SDCARD)
|
||||||
|
#include "sdcard.h"
|
||||||
|
#endif
|
||||||
|
|
||||||
|
|
||||||
extern Ticker housekeeper;
|
extern Ticker housekeeper;
|
||||||
|
|
||||||
void housekeeping(void);
|
void housekeeping(void);
|
||||||
|
@ -111,6 +111,11 @@ typedef struct {
|
|||||||
float gas; // raw gas sensor signal
|
float gas; // raw gas sensor signal
|
||||||
} bmeStatus_t;
|
} bmeStatus_t;
|
||||||
|
|
||||||
|
typedef struct {
|
||||||
|
float pm10;
|
||||||
|
float pm25;
|
||||||
|
} sdsStatus_t;
|
||||||
|
|
||||||
extern std::set<uint16_t, std::less<uint16_t>, Mallocator<uint16_t>> macs;
|
extern std::set<uint16_t, std::less<uint16_t>, Mallocator<uint16_t>> macs;
|
||||||
extern std::array<uint64_t, 0xff>::iterator it;
|
extern std::array<uint64_t, 0xff>::iterator it;
|
||||||
extern std::array<uint64_t, 0xff> beacons;
|
extern std::array<uint64_t, 0xff> beacons;
|
||||||
|
@ -3,6 +3,10 @@
|
|||||||
|
|
||||||
#include "paxcounter.conf"
|
#include "paxcounter.conf"
|
||||||
|
|
||||||
|
#if (HAS_SDS011)
|
||||||
|
#include "sds011read.h"
|
||||||
|
#endif
|
||||||
|
|
||||||
// MyDevices CayenneLPP 1.0 channels for Synamic sensor payload format
|
// MyDevices CayenneLPP 1.0 channels for Synamic sensor payload format
|
||||||
// all payload goes out on LoRa FPort 1
|
// all payload goes out on LoRa FPort 1
|
||||||
#if (PAYLOAD_ENCODER == 3)
|
#if (PAYLOAD_ENCODER == 3)
|
||||||
@ -19,6 +23,8 @@
|
|||||||
#define LPP_HUMIDITY_CHANNEL 29
|
#define LPP_HUMIDITY_CHANNEL 29
|
||||||
#define LPP_BAROMETER_CHANNEL 30
|
#define LPP_BAROMETER_CHANNEL 30
|
||||||
#define LPP_AIR_CHANNEL 31
|
#define LPP_AIR_CHANNEL 31
|
||||||
|
#define LPP_PARTMATTER10_CHANNEL 32 // particular matter for PM 10
|
||||||
|
#define LPP_PARTMATTER25_CHANNEL 33 // particular matter for PM 2.5
|
||||||
|
|
||||||
// MyDevices CayenneLPP 2.0 types for Packed Sensor Payload, not using channels,
|
// MyDevices CayenneLPP 2.0 types for Packed Sensor Payload, not using channels,
|
||||||
// but different FPorts
|
// but different FPorts
|
||||||
@ -55,6 +61,9 @@ public:
|
|||||||
void addButton(uint8_t value);
|
void addButton(uint8_t value);
|
||||||
void addSensor(uint8_t[]);
|
void addSensor(uint8_t[]);
|
||||||
void addTime(time_t value);
|
void addTime(time_t value);
|
||||||
|
void addSDS(sdsStatus_t value);
|
||||||
|
private:
|
||||||
|
void addChars( char* string, int len);
|
||||||
|
|
||||||
#if (PAYLOAD_ENCODER == 1) // format plain
|
#if (PAYLOAD_ENCODER == 1) // format plain
|
||||||
|
|
||||||
@ -95,4 +104,4 @@ private:
|
|||||||
|
|
||||||
extern PayloadConvert payload;
|
extern PayloadConvert payload;
|
||||||
|
|
||||||
#endif // _PAYLOAD_H_
|
#endif // _PAYLOAD_H_
|
||||||
|
@ -10,7 +10,7 @@
|
|||||||
#define SDCARD_FILE_NAME "paxcount.%02d"
|
#define SDCARD_FILE_NAME "paxcount.%02d"
|
||||||
#define SDCARD_FILE_HEADER "date, time, wifi, bluet"
|
#define SDCARD_FILE_HEADER "date, time, wifi, bluet"
|
||||||
|
|
||||||
bool sdcardInit( void );
|
bool sdcard_init( void );
|
||||||
void sdcardWriteData( uint16_t, uint16_t);
|
void sdcardWriteData( uint16_t, uint16_t);
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
15
include/sds011read.h
Normal file
15
include/sds011read.h
Normal file
@ -0,0 +1,15 @@
|
|||||||
|
#ifndef _SDS011READ_H
|
||||||
|
#define _SDS011READ_H
|
||||||
|
|
||||||
|
#include "globals.h"
|
||||||
|
#include <SDS011.h>
|
||||||
|
|
||||||
|
#define SDCARD_FILE_HEADER_SDS011 ", PM10,PM25"
|
||||||
|
|
||||||
|
bool sds011_init();
|
||||||
|
void sds011_loop();
|
||||||
|
void sds011_sleep(void);
|
||||||
|
void sds011_wakeup(void);
|
||||||
|
void sds011_store(sdsStatus_t *sds_store);
|
||||||
|
|
||||||
|
#endif // _SDS011READ_H
|
@ -73,6 +73,7 @@ lib_deps_sensors =
|
|||||||
Adafruit BME280 Library@>=2.0.0
|
Adafruit BME280 Library@>=2.0.0
|
||||||
Adafruit BMP085 Library@>=1.0.1
|
Adafruit BMP085 Library@>=1.0.1
|
||||||
BSEC Software Library@1.5.1474
|
BSEC Software Library@1.5.1474
|
||||||
|
https://github.com/ricki-z/SDS011.git
|
||||||
lib_deps_basic =
|
lib_deps_basic =
|
||||||
ArduinoJson@^5.13.1
|
ArduinoJson@^5.13.1
|
||||||
76@>=1.2.4 ; #76 Timezone by Jack Christensen
|
76@>=1.2.4 ; #76 Timezone by Jack Christensen
|
||||||
|
@ -9,6 +9,10 @@ static const char TAG[] = __FILE__;
|
|||||||
|
|
||||||
Ticker housekeeper;
|
Ticker housekeeper;
|
||||||
|
|
||||||
|
#if (HAS_SDS011)
|
||||||
|
extern boolean isSDS011Active;
|
||||||
|
#endif
|
||||||
|
|
||||||
void housekeeping() {
|
void housekeeping() {
|
||||||
xTaskNotifyFromISR(irqHandlerTask, CYCLIC_IRQ, eSetBits, NULL);
|
xTaskNotifyFromISR(irqHandlerTask, CYCLIC_IRQ, eSetBits, NULL);
|
||||||
}
|
}
|
||||||
@ -18,7 +22,6 @@ void doHousekeeping() {
|
|||||||
|
|
||||||
// update uptime counter
|
// update uptime counter
|
||||||
uptime();
|
uptime();
|
||||||
|
|
||||||
// check if update mode trigger switch was set
|
// check if update mode trigger switch was set
|
||||||
if (RTC_runmode == RUNMODE_UPDATE) {
|
if (RTC_runmode == RUNMODE_UPDATE) {
|
||||||
// check battery status if we can before doing ota
|
// check battery status if we can before doing ota
|
||||||
@ -112,6 +115,17 @@ void doHousekeeping() {
|
|||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
#if (HAS_SDS011)
|
||||||
|
if ( isSDS011Active ) {
|
||||||
|
ESP_LOGD(TAG, "SDS011: go to sleep");
|
||||||
|
sds011_loop();
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
ESP_LOGD(TAG, "SDS011: wakeup");
|
||||||
|
sds011_wakeup();
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
} // doHousekeeping()
|
} // doHousekeeping()
|
||||||
|
|
||||||
// uptime counter 64bit to prevent millis() rollover after 49 days
|
// uptime counter 64bit to prevent millis() rollover after 49 days
|
||||||
@ -143,4 +157,4 @@ void reset_counters() {
|
|||||||
#endif
|
#endif
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
|
@ -10,8 +10,7 @@ static const char TAG[] = __FILE__;
|
|||||||
TinyGPSPlus gps;
|
TinyGPSPlus gps;
|
||||||
TinyGPSCustom gpstime(gps, "GPZDA", 1); // field 1 = UTC time
|
TinyGPSCustom gpstime(gps, "GPZDA", 1); // field 1 = UTC time
|
||||||
static const String ZDA_Request = "$EIGPQ,ZDA*39\r\n";
|
static const String ZDA_Request = "$EIGPQ,ZDA*39\r\n";
|
||||||
|
static gpsStatus_t gps_status = {0};
|
||||||
gpsStatus_t gps_status = {0};
|
|
||||||
TaskHandle_t GpsTask;
|
TaskHandle_t GpsTask;
|
||||||
|
|
||||||
#ifdef GPS_SERIAL
|
#ifdef GPS_SERIAL
|
||||||
|
@ -48,8 +48,14 @@
|
|||||||
//#define HAS_BMP180
|
//#define HAS_BMP180
|
||||||
//#define BMP180_ADDR 0x77
|
//#define BMP180_ADDR 0x77
|
||||||
|
|
||||||
|
// SDS011 dust sensor settings
|
||||||
|
#define HAS_SDS011 1 // use SDS011
|
||||||
|
// used pins on the ESP-side:
|
||||||
|
#define SDS_TX 19 // connect to RX on the SDS011
|
||||||
|
#define SDS_RX 23 // connect to TX on the SDS011
|
||||||
|
|
||||||
// user defined sensors
|
// user defined sensors
|
||||||
//#define HAS_SENSORS 1 // comment out if device has user defined sensors
|
#define HAS_SENSORS 1 // comment out if device has user defined sensors
|
||||||
|
|
||||||
#define CFG_sx1276_radio 1 // select LoRa chip
|
#define CFG_sx1276_radio 1 // select LoRa chip
|
||||||
//#define CFG_sx1272_radio 1 // select LoRa chip
|
//#define CFG_sx1272_radio 1 // select LoRa chip
|
||||||
@ -100,4 +106,4 @@
|
|||||||
#define MCP_24AA02E64_I2C_ADDRESS 0x50 // I2C address for the 24AA02E64
|
#define MCP_24AA02E64_I2C_ADDRESS 0x50 // I2C address for the 24AA02E64
|
||||||
#define MCP_24AA02E64_MAC_ADDRESS 0xF8 // Memory adress of unique deveui 64 bits
|
#define MCP_24AA02E64_MAC_ADDRESS 0xF8 // Memory adress of unique deveui 64 bits
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
@ -12,6 +12,12 @@
|
|||||||
// This settings are for boards labeled v1.6 on pcb, NOT for v1.5 or older
|
// This settings are for boards labeled v1.6 on pcb, NOT for v1.5 or older
|
||||||
*/
|
*/
|
||||||
|
|
||||||
|
// SDS011 dust sensor settings
|
||||||
|
#define HAS_SDS011 1 // use SDS011
|
||||||
|
// used pins on the ESP-side:
|
||||||
|
#define SDS_TX 19 // connect to RX on the SDS011
|
||||||
|
#define SDS_RX 23 // connect to TX on the SDS011
|
||||||
|
|
||||||
#define HAS_LORA 1 // comment out if device shall not send data via LoRa
|
#define HAS_LORA 1 // comment out if device shall not send data via LoRa
|
||||||
#define CFG_sx1276_radio 1 // HPD13A LoRa SoC
|
#define CFG_sx1276_radio 1 // HPD13A LoRa SoC
|
||||||
|
|
||||||
@ -48,4 +54,4 @@
|
|||||||
#define LORA_IO1 (33)
|
#define LORA_IO1 (33)
|
||||||
#define LORA_IO2 (32)
|
#define LORA_IO2 (32)
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
@ -323,10 +323,16 @@ void setup() {
|
|||||||
#endif
|
#endif
|
||||||
|
|
||||||
#ifdef HAS_SDCARD
|
#ifdef HAS_SDCARD
|
||||||
if (sdcardInit())
|
if (sdcard_init())
|
||||||
strcat_P(features, " SD");
|
strcat_P(features, " SD");
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
#if (HAS_SDS011)
|
||||||
|
ESP_LOGI(TAG, "init fine-dust-sensor");
|
||||||
|
if ( sds011_init() )
|
||||||
|
strcat_P(features, " SDS");
|
||||||
|
#endif
|
||||||
|
|
||||||
#if (VENDORFILTER)
|
#if (VENDORFILTER)
|
||||||
strcat_P(features, " FILTER");
|
strcat_P(features, " FILTER");
|
||||||
#endif
|
#endif
|
||||||
|
@ -80,7 +80,7 @@ void PayloadConvert::addStatus(uint16_t voltage, uint64_t uptime, float cputemp,
|
|||||||
}
|
}
|
||||||
|
|
||||||
void PayloadConvert::addGPS(gpsStatus_t value) {
|
void PayloadConvert::addGPS(gpsStatus_t value) {
|
||||||
#if(HAS_GPS)
|
#if (HAS_GPS)
|
||||||
buffer[cursor++] = (byte)((value.latitude & 0xFF000000) >> 24);
|
buffer[cursor++] = (byte)((value.latitude & 0xFF000000) >> 24);
|
||||||
buffer[cursor++] = (byte)((value.latitude & 0x00FF0000) >> 16);
|
buffer[cursor++] = (byte)((value.latitude & 0x00FF0000) >> 16);
|
||||||
buffer[cursor++] = (byte)((value.latitude & 0x0000FF00) >> 8);
|
buffer[cursor++] = (byte)((value.latitude & 0x0000FF00) >> 8);
|
||||||
@ -100,7 +100,7 @@ void PayloadConvert::addGPS(gpsStatus_t value) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
void PayloadConvert::addSensor(uint8_t buf[]) {
|
void PayloadConvert::addSensor(uint8_t buf[]) {
|
||||||
#if(HAS_SENSORS)
|
#if (HAS_SENSORS)
|
||||||
uint8_t length = buf[0];
|
uint8_t length = buf[0];
|
||||||
memcpy(buffer, buf + 1, length);
|
memcpy(buffer, buf + 1, length);
|
||||||
cursor += length; // length of buffer
|
cursor += length; // length of buffer
|
||||||
@ -108,7 +108,7 @@ void PayloadConvert::addSensor(uint8_t buf[]) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
void PayloadConvert::addBME(bmeStatus_t value) {
|
void PayloadConvert::addBME(bmeStatus_t value) {
|
||||||
#if(HAS_BME)
|
#if (HAS_BME)
|
||||||
int16_t temperature = (int16_t)(value.temperature); // float -> int
|
int16_t temperature = (int16_t)(value.temperature); // float -> int
|
||||||
uint16_t humidity = (uint16_t)(value.humidity); // float -> int
|
uint16_t humidity = (uint16_t)(value.humidity); // float -> int
|
||||||
uint16_t pressure = (uint16_t)(value.pressure); // float -> int
|
uint16_t pressure = (uint16_t)(value.pressure); // float -> int
|
||||||
@ -124,6 +124,16 @@ void PayloadConvert::addBME(bmeStatus_t value) {
|
|||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void PayloadConvert::addSDS(sdsStatus_t sds) {
|
||||||
|
#if (HAS_SDS011)
|
||||||
|
char tempBuffer[10 + 1];
|
||||||
|
sprintf(tempBuffer, ",%5.1f", sds.pm10);
|
||||||
|
addChars(tempBuffer, strlen(tempBuffer));
|
||||||
|
sprintf(tempBuffer, ",%5.1f", sds.pm25);
|
||||||
|
addChars(tempBuffer, strlen(tempBuffer));
|
||||||
|
#endif // HAS_SDS011
|
||||||
|
}
|
||||||
|
|
||||||
void PayloadConvert::addButton(uint8_t value) {
|
void PayloadConvert::addButton(uint8_t value) {
|
||||||
#ifdef HAS_BUTTON
|
#ifdef HAS_BUTTON
|
||||||
buffer[cursor++] = value;
|
buffer[cursor++] = value;
|
||||||
@ -193,7 +203,7 @@ void PayloadConvert::addStatus(uint16_t voltage, uint64_t uptime, float cputemp,
|
|||||||
}
|
}
|
||||||
|
|
||||||
void PayloadConvert::addGPS(gpsStatus_t value) {
|
void PayloadConvert::addGPS(gpsStatus_t value) {
|
||||||
#if(HAS_GPS)
|
#if (HAS_GPS)
|
||||||
writeLatLng(value.latitude, value.longitude);
|
writeLatLng(value.latitude, value.longitude);
|
||||||
#if (!PAYLOAD_OPENSENSEBOX)
|
#if (!PAYLOAD_OPENSENSEBOX)
|
||||||
writeUint8(value.satellites);
|
writeUint8(value.satellites);
|
||||||
@ -204,7 +214,7 @@ void PayloadConvert::addGPS(gpsStatus_t value) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
void PayloadConvert::addSensor(uint8_t buf[]) {
|
void PayloadConvert::addSensor(uint8_t buf[]) {
|
||||||
#if(HAS_SENSORS)
|
#if (HAS_SENSORS)
|
||||||
uint8_t length = buf[0];
|
uint8_t length = buf[0];
|
||||||
memcpy(buffer, buf + 1, length);
|
memcpy(buffer, buf + 1, length);
|
||||||
cursor += length; // length of buffer
|
cursor += length; // length of buffer
|
||||||
@ -212,7 +222,7 @@ void PayloadConvert::addSensor(uint8_t buf[]) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
void PayloadConvert::addBME(bmeStatus_t value) {
|
void PayloadConvert::addBME(bmeStatus_t value) {
|
||||||
#if(HAS_BME)
|
#if (HAS_BME)
|
||||||
writeFloat(value.temperature);
|
writeFloat(value.temperature);
|
||||||
writePressure(value.pressure);
|
writePressure(value.pressure);
|
||||||
writeUFloat(value.humidity);
|
writeUFloat(value.humidity);
|
||||||
@ -220,6 +230,13 @@ void PayloadConvert::addBME(bmeStatus_t value) {
|
|||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void PayloadConvert::addSDS(sdsStatus_t sds) {
|
||||||
|
#if (HAS_SDS011)
|
||||||
|
writeUint16((uint16_t)(sds.pm10 * 10));
|
||||||
|
writeUint16((uint16_t)(sds.pm25 * 10));
|
||||||
|
#endif // HAS_SDS011
|
||||||
|
}
|
||||||
|
|
||||||
void PayloadConvert::addButton(uint8_t value) {
|
void PayloadConvert::addButton(uint8_t value) {
|
||||||
#ifdef HAS_BUTTON
|
#ifdef HAS_BUTTON
|
||||||
writeUint8(value);
|
writeUint8(value);
|
||||||
@ -242,9 +259,7 @@ void PayloadConvert::uintToBytes(uint64_t value, uint8_t byteSize) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void PayloadConvert::writeUptime(uint64_t uptime) {
|
void PayloadConvert::writeUptime(uint64_t uptime) { writeUint64(uptime); }
|
||||||
writeUint64(uptime);
|
|
||||||
}
|
|
||||||
|
|
||||||
void PayloadConvert::writeVersion(char *version) {
|
void PayloadConvert::writeVersion(char *version) {
|
||||||
memcpy(buffer + cursor, version, 10);
|
memcpy(buffer + cursor, version, 10);
|
||||||
@ -265,13 +280,9 @@ void PayloadConvert::writeUint16(uint16_t i) { uintToBytes(i, 2); }
|
|||||||
|
|
||||||
void PayloadConvert::writeUint8(uint8_t i) { uintToBytes(i, 1); }
|
void PayloadConvert::writeUint8(uint8_t i) { uintToBytes(i, 1); }
|
||||||
|
|
||||||
void PayloadConvert::writeUFloat(float value) {
|
void PayloadConvert::writeUFloat(float value) { writeUint16(value * 100); }
|
||||||
writeUint16(value * 100);
|
|
||||||
}
|
|
||||||
|
|
||||||
void PayloadConvert::writePressure(float value) {
|
void PayloadConvert::writePressure(float value) { writeUint16(value * 10); }
|
||||||
writeUint16(value * 10);
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Uses a 16bit two's complement with two decimals, so the range is
|
* Uses a 16bit two's complement with two decimals, so the range is
|
||||||
@ -312,10 +323,29 @@ void PayloadConvert::writeBitmap(bool a, bool b, bool c, bool d, bool e, bool f,
|
|||||||
|
|
||||||
#elif ((PAYLOAD_ENCODER == 3) || (PAYLOAD_ENCODER == 4))
|
#elif ((PAYLOAD_ENCODER == 3) || (PAYLOAD_ENCODER == 4))
|
||||||
|
|
||||||
void PayloadConvert::addByte(uint8_t value) {
|
void PayloadConvert::addByte(uint8_t value) {
|
||||||
/*
|
/*
|
||||||
not implemented
|
not implemented
|
||||||
*/ }
|
*/
|
||||||
|
}
|
||||||
|
|
||||||
|
void PayloadConvert::addSDS(sdsStatus_t sds) {
|
||||||
|
#if (HAS_SDS011)
|
||||||
|
// value of PM10
|
||||||
|
#if (PAYLOAD_ENCODER == 3) // Cayenne LPP dynamic
|
||||||
|
buffer[cursor++] = LPP_PARTMATTER10_CHANNEL; // for PM10
|
||||||
|
#endif
|
||||||
|
buffer[cursor++] = LPP_LUMINOSITY; // workaround since cayenne has no data type meter
|
||||||
|
buffer[cursor++] = highByte((uint16_t)(sds.pm10 * 10));
|
||||||
|
buffer[cursor++] = lowByte((uint16_t)(sds.pm10 * 10));
|
||||||
|
// value of PM2.5
|
||||||
|
#if (PAYLOAD_ENCODER == 3) // Cayenne LPP dynamic
|
||||||
|
buffer[cursor++] = LPP_PARTMATTER25_CHANNEL; // for PM2.5
|
||||||
|
#endif
|
||||||
|
buffer[cursor++] = LPP_LUMINOSITY; // workaround since cayenne has no data type meter
|
||||||
|
buffer[cursor++] = highByte((uint16_t)(sds.pm25 * 10));
|
||||||
|
buffer[cursor++] = lowByte((uint16_t)(sds.pm25 * 10));
|
||||||
|
#endif // HAS_SDS011
|
||||||
|
|
||||||
void PayloadConvert::addCount(uint16_t value, uint8_t snifftype) {
|
void PayloadConvert::addCount(uint16_t value, uint8_t snifftype) {
|
||||||
switch (snifftype) {
|
switch (snifftype) {
|
||||||
@ -393,7 +423,7 @@ void PayloadConvert::addStatus(uint16_t voltage, uint64_t uptime, float celsius,
|
|||||||
}
|
}
|
||||||
|
|
||||||
void PayloadConvert::addGPS(gpsStatus_t value) {
|
void PayloadConvert::addGPS(gpsStatus_t value) {
|
||||||
#if(HAS_GPS)
|
#if (HAS_GPS)
|
||||||
int32_t lat = value.latitude / 100;
|
int32_t lat = value.latitude / 100;
|
||||||
int32_t lon = value.longitude / 100;
|
int32_t lon = value.longitude / 100;
|
||||||
int32_t alt = value.altitude * 100;
|
int32_t alt = value.altitude * 100;
|
||||||
@ -414,18 +444,18 @@ void PayloadConvert::addGPS(gpsStatus_t value) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
void PayloadConvert::addSensor(uint8_t buf[]) {
|
void PayloadConvert::addSensor(uint8_t buf[]) {
|
||||||
#if(HAS_SENSORS)
|
#if (HAS_SENSORS)
|
||||||
// to come
|
// to come
|
||||||
/*
|
/*
|
||||||
uint8_t length = buf[0];
|
uint8_t length = buf[0];
|
||||||
memcpy(buffer, buf+1, length);
|
memcpy(buffer, buf+1, length);
|
||||||
cursor += length; // length of buffer
|
cursor += length; // length of buffer
|
||||||
*/
|
*/
|
||||||
#endif // HAS_SENSORS
|
#endif // HAS_SENSORS
|
||||||
}
|
}
|
||||||
|
|
||||||
void PayloadConvert::addBME(bmeStatus_t value) {
|
void PayloadConvert::addBME(bmeStatus_t value) {
|
||||||
#if(HAS_BME)
|
#if (HAS_BME)
|
||||||
|
|
||||||
// data value conversions to meet cayenne data type definition
|
// data value conversions to meet cayenne data type definition
|
||||||
// 0.1°C per bit => -3276,7 .. +3276,7 °C
|
// 0.1°C per bit => -3276,7 .. +3276,7 °C
|
||||||
@ -489,5 +519,9 @@ void PayloadConvert::addTime(time_t value) {
|
|||||||
buffer[cursor++] = (byte)((tx_period & 0x000000FF));
|
buffer[cursor++] = (byte)((tx_period & 0x000000FF));
|
||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
|
#endif // PAYLOAD_ENCODER
|
||||||
|
|
||||||
#endif
|
void PayloadConvert::addChars(char *string, int len) {
|
||||||
|
for (int i = 0; i < len; i++)
|
||||||
|
addByte(string[i]);
|
||||||
|
}
|
||||||
|
@ -13,11 +13,13 @@ static void createFile(void);
|
|||||||
|
|
||||||
File fileSDCard;
|
File fileSDCard;
|
||||||
|
|
||||||
bool sdcardInit() {
|
bool sdcard_init() {
|
||||||
ESP_LOGD(TAG, "looking for SD-card...");
|
ESP_LOGD(TAG, "looking for SD-card...");
|
||||||
useSDCard = SD.begin(SDCARD_CS, SDCARD_MOSI, SDCARD_MISO, SDCARD_SCLK);
|
useSDCard = SD.begin(SDCARD_CS, SDCARD_MOSI, SDCARD_MISO, SDCARD_SCLK);
|
||||||
if (useSDCard)
|
if (useSDCard)
|
||||||
createFile();
|
createFile();
|
||||||
|
else
|
||||||
|
ESP_LOGD(TAG, "SD-card not found");
|
||||||
return useSDCard;
|
return useSDCard;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -25,6 +27,9 @@ void sdcardWriteData(uint16_t noWifi, uint16_t noBle) {
|
|||||||
static int counterWrites = 0;
|
static int counterWrites = 0;
|
||||||
char tempBuffer[12 + 1];
|
char tempBuffer[12 + 1];
|
||||||
time_t t = now();
|
time_t t = now();
|
||||||
|
#if (HAS_SDS011)
|
||||||
|
sdsStatus_t sds;
|
||||||
|
#endif
|
||||||
|
|
||||||
if (!useSDCard)
|
if (!useSDCard)
|
||||||
return;
|
return;
|
||||||
@ -35,7 +40,13 @@ void sdcardWriteData(uint16_t noWifi, uint16_t noBle) {
|
|||||||
sprintf(tempBuffer, "%02d:%02d:%02d,", hour(t), minute(t), second(t));
|
sprintf(tempBuffer, "%02d:%02d:%02d,", hour(t), minute(t), second(t));
|
||||||
fileSDCard.print(tempBuffer);
|
fileSDCard.print(tempBuffer);
|
||||||
sprintf(tempBuffer, "%d,%d", noWifi, noBle);
|
sprintf(tempBuffer, "%d,%d", noWifi, noBle);
|
||||||
fileSDCard.println(tempBuffer);
|
fileSDCard.print(tempBuffer);
|
||||||
|
#if (HAS_SDS011)
|
||||||
|
sds011_store(&sds);
|
||||||
|
sprintf(tempBuffer, ",%5.1f,%4.1f", sds.pm10, sds.pm25);
|
||||||
|
fileSDCard.print(tempBuffer);
|
||||||
|
#endif
|
||||||
|
fileSDCard.println();
|
||||||
|
|
||||||
if (++counterWrites > 2) {
|
if (++counterWrites > 2) {
|
||||||
// force writing to SD-card
|
// force writing to SD-card
|
||||||
@ -58,8 +69,12 @@ void createFile(void) {
|
|||||||
ESP_LOGD(TAG, "SD: file does not exist: opening");
|
ESP_LOGD(TAG, "SD: file does not exist: opening");
|
||||||
fileSDCard = SD.open(bufferFilename, FILE_WRITE);
|
fileSDCard = SD.open(bufferFilename, FILE_WRITE);
|
||||||
if (fileSDCard) {
|
if (fileSDCard) {
|
||||||
ESP_LOGD(TAG, "SD: name opended: <%s>", bufferFilename);
|
ESP_LOGD(TAG, "SD: name opened: <%s>", bufferFilename);
|
||||||
fileSDCard.println(SDCARD_FILE_HEADER);
|
fileSDCard.print(SDCARD_FILE_HEADER);
|
||||||
|
#if (HAS_SDS011)
|
||||||
|
fileSDCard.print(SDCARD_FILE_HEADER_SDS011);
|
||||||
|
#endif
|
||||||
|
fileSDCard.println();
|
||||||
useSDCard = true;
|
useSDCard = true;
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
@ -68,4 +83,4 @@ void createFile(void) {
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
#endif // (HAS_SDCARD)
|
#endif // (HAS_SDCARD)
|
||||||
|
65
src/sds011read.cpp
Normal file
65
src/sds011read.cpp
Normal file
@ -0,0 +1,65 @@
|
|||||||
|
// routines for fetching data from the SDS011-sensor
|
||||||
|
|
||||||
|
#if (HAS_SDS011)
|
||||||
|
|
||||||
|
// Local logging tag
|
||||||
|
static const char TAG[] = __FILE__;
|
||||||
|
|
||||||
|
#include "sds011read.h"
|
||||||
|
|
||||||
|
#if (HAS_IF482)
|
||||||
|
#error cannot use IF482 together with SDS011 (both use UART#2)
|
||||||
|
#endif
|
||||||
|
// UART(2) is unused in this project
|
||||||
|
static HardwareSerial sdsSerial(2); // so we use it here
|
||||||
|
static SDS011 sdsSensor; // fine dust sensor
|
||||||
|
|
||||||
|
// the results of the sensor:
|
||||||
|
static float pm10, pm25;
|
||||||
|
boolean isSDS011Active;
|
||||||
|
|
||||||
|
// init
|
||||||
|
bool sds011_init() {
|
||||||
|
pm25 = pm10 = 0.0;
|
||||||
|
sdsSensor.begin(&sdsSerial, SDS_RX, SDS_TX);
|
||||||
|
sds011_sleep(); // we do sleep/wakup by ourselves
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
// reading data:
|
||||||
|
void sds011_loop() {
|
||||||
|
if (isSDS011Active) {
|
||||||
|
int sdsErrorCode = sdsSensor.read(&pm25, &pm10);
|
||||||
|
if (sdsErrorCode) {
|
||||||
|
pm25 = pm10 = 0.0;
|
||||||
|
ESP_LOGI(TAG, "SDS011 error: %d", sdsErrorCode);
|
||||||
|
} else {
|
||||||
|
ESP_LOGI(TAG, "fine-dust-values: %5.1f,%4.1f", pm10, pm25);
|
||||||
|
}
|
||||||
|
sds011_sleep();
|
||||||
|
}
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
// retrieving stored data:
|
||||||
|
void sds011_store(sdsStatus_t *sds_store) {
|
||||||
|
sds_store->pm10 = pm10;
|
||||||
|
sds_store->pm25 = pm25;
|
||||||
|
}
|
||||||
|
|
||||||
|
// putting the SDS-sensor to sleep
|
||||||
|
void sds011_sleep(void) {
|
||||||
|
sdsSensor.sleep();
|
||||||
|
isSDS011Active = false;
|
||||||
|
}
|
||||||
|
|
||||||
|
// start the SDS-sensor
|
||||||
|
// needs 30 seconds for warming up
|
||||||
|
void sds011_wakeup() {
|
||||||
|
if (!isSDS011Active) {
|
||||||
|
sdsSensor.wakeup();
|
||||||
|
isSDS011Active = true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#endif // HAS_SDS011
|
@ -63,9 +63,12 @@ void sendData() {
|
|||||||
|
|
||||||
uint8_t bitmask = cfg.payloadmask;
|
uint8_t bitmask = cfg.payloadmask;
|
||||||
uint8_t mask = 1;
|
uint8_t mask = 1;
|
||||||
#if (HAS_GPS)
|
#if (HAS_GPS)
|
||||||
gpsStatus_t gps_status;
|
gpsStatus_t gps_status;
|
||||||
#endif
|
#endif
|
||||||
|
#if (HAS_SDS011)
|
||||||
|
sdsStatus_t sds_status;
|
||||||
|
#endif
|
||||||
|
|
||||||
while (bitmask) {
|
while (bitmask) {
|
||||||
switch (bitmask & mask) {
|
switch (bitmask & mask) {
|
||||||
@ -94,6 +97,10 @@ void sendData() {
|
|||||||
payload.addCount(macs_wifi, MAC_SNIFF_WIFI);
|
payload.addCount(macs_wifi, MAC_SNIFF_WIFI);
|
||||||
if (cfg.blescan)
|
if (cfg.blescan)
|
||||||
payload.addCount(macs_ble, MAC_SNIFF_BLE);
|
payload.addCount(macs_ble, MAC_SNIFF_BLE);
|
||||||
|
#endif
|
||||||
|
#if (HAS_SDS011)
|
||||||
|
sds011_store(&sds_status);
|
||||||
|
payload.addSDS(sds_status);
|
||||||
#endif
|
#endif
|
||||||
SendPayload(COUNTERPORT, prio_normal);
|
SendPayload(COUNTERPORT, prio_normal);
|
||||||
// clear counter if not in cumulative counter mode
|
// clear counter if not in cumulative counter mode
|
||||||
@ -172,4 +179,4 @@ void flushQueues() {
|
|||||||
#ifdef HAS_SPI
|
#ifdef HAS_SPI
|
||||||
spi_queuereset();
|
spi_queuereset();
|
||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
|
@ -16,6 +16,9 @@ static const char TAG[] = __FILE__;
|
|||||||
const char timeSetSymbols[] = {'G', 'R', 'L', '?'};
|
const char timeSetSymbols[] = {'G', 'R', 'L', '?'};
|
||||||
|
|
||||||
#ifdef HAS_IF482
|
#ifdef HAS_IF482
|
||||||
|
#if (HAS_SDS011)
|
||||||
|
#error cannot use IF482 together with SDS011 (both use UART#2)
|
||||||
|
#endif
|
||||||
HardwareSerial IF482(2); // use UART #2 (#1 may be in use for serial GPS)
|
HardwareSerial IF482(2); // use UART #2 (#1 may be in use for serial GPS)
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
Loading…
Reference in New Issue
Block a user