commit
4f762ef498
15
include/sds011read.h
Normal file
15
include/sds011read.h
Normal file
@ -0,0 +1,15 @@
|
|||||||
|
#ifndef _SDS011READ_H
|
||||||
|
#define _SDS011READ_H
|
||||||
|
|
||||||
|
#include <SDS011.h>
|
||||||
|
|
||||||
|
// used pins on the ESP-side:
|
||||||
|
#define ESP_PIN_TX 19 // connect to RX on the SDS011
|
||||||
|
#define ESP_PIN_RX 23 // connect to TX on the SDS011
|
||||||
|
|
||||||
|
#define SDCARD_FILE_HEADER_SDS011 ", PM10,PM25"
|
||||||
|
|
||||||
|
bool sds011_init();
|
||||||
|
void sds011_loop();
|
||||||
|
|
||||||
|
#endif // _SDS011READ_H
|
191
lib/SDS011/src/SDS011.cpp
Normal file
191
lib/SDS011/src/SDS011.cpp
Normal file
@ -0,0 +1,191 @@
|
|||||||
|
// SDS011 dust sensor PM2.5 and PM10
|
||||||
|
// ---------------------
|
||||||
|
//
|
||||||
|
// By R. Zschiegner (rz@madavi.de)
|
||||||
|
// April 2016
|
||||||
|
//
|
||||||
|
// Documentation:
|
||||||
|
// - The iNovaFitness SDS011 datasheet
|
||||||
|
//
|
||||||
|
// modified by AQ - 2018-11-18
|
||||||
|
//
|
||||||
|
|
||||||
|
#include "SDS011.h"
|
||||||
|
|
||||||
|
static const byte SDS_SLEEP[] = {
|
||||||
|
0xAA, // head
|
||||||
|
0xB4, // command id
|
||||||
|
0x06, // data byte 1
|
||||||
|
0x01, // data byte 2 (set mode)
|
||||||
|
0x00, // data byte 3 (sleep)
|
||||||
|
0x00, // data byte 4
|
||||||
|
0x00, // data byte 5
|
||||||
|
0x00, // data byte 6
|
||||||
|
0x00, // data byte 7
|
||||||
|
0x00, // data byte 8
|
||||||
|
0x00, // data byte 9
|
||||||
|
0x00, // data byte 10
|
||||||
|
0x00, // data byte 11
|
||||||
|
0x00, // data byte 12
|
||||||
|
0x00, // data byte 13
|
||||||
|
0xFF, // data byte 14 (device id byte 1)
|
||||||
|
0xFF, // data byte 15 (device id byte 2)
|
||||||
|
0x05, // checksum
|
||||||
|
0xAB // tail
|
||||||
|
};
|
||||||
|
|
||||||
|
static const byte SDS_START[] = {
|
||||||
|
0xAA, 0xB4, 0x06, 0x01, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xFF, 0xFF, 0x06, 0xAB};
|
||||||
|
|
||||||
|
static const byte SDS_CONT_MODE[] = {
|
||||||
|
0xAA, 0xB4, 0x08, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xFF, 0xFF, 0x07, 0xAB};
|
||||||
|
|
||||||
|
static const byte SDS_VERSION[] = {
|
||||||
|
0xAA, 0xB4, 0x07, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xFF, 0xFF, 0x05, 0xAB};
|
||||||
|
|
||||||
|
const uint8_t SDS_cmd_len = 19;
|
||||||
|
|
||||||
|
SDS011::SDS011(void) {
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
// --------------------------------------------------------
|
||||||
|
// SDS011:read
|
||||||
|
// --------------------------------------------------------
|
||||||
|
int SDS011::read(float *p25, float *p10) {
|
||||||
|
byte buffer;
|
||||||
|
int value;
|
||||||
|
int len = 0;
|
||||||
|
int pm10_serial = 0;
|
||||||
|
int pm25_serial = 0;
|
||||||
|
int checksum_is;
|
||||||
|
int checksum_ok = 0;
|
||||||
|
int error = 1;
|
||||||
|
|
||||||
|
while ((sds_data->available() > 0) && (sds_data->available() >= (10-len))) {
|
||||||
|
buffer = sds_data->read();
|
||||||
|
value = int(buffer);
|
||||||
|
switch (len) {
|
||||||
|
case (0): if (value != 170) { len = -1; }; break;
|
||||||
|
case (1): if (value != 192) { len = -1; }; break;
|
||||||
|
case (2): pm25_serial = value; checksum_is = value; break;
|
||||||
|
case (3): pm25_serial += (value << 8); checksum_is += value; break;
|
||||||
|
case (4): pm10_serial = value; checksum_is += value; break;
|
||||||
|
case (5): pm10_serial += (value << 8); checksum_is += value; break;
|
||||||
|
case (6): checksum_is += value; break;
|
||||||
|
case (7): checksum_is += value; break;
|
||||||
|
case (8): if (value == (checksum_is % 256)) { checksum_ok = 1; } else { len = -1; }; break;
|
||||||
|
case (9): if (value != 171) { len = -1; }; break;
|
||||||
|
}
|
||||||
|
len++;
|
||||||
|
if (len == 10 && checksum_ok == 1) {
|
||||||
|
*p10 = (float)pm10_serial/10.0;
|
||||||
|
*p25 = (float)pm25_serial/10.0;
|
||||||
|
len = 0; checksum_ok = 0; pm10_serial = 0.0; pm25_serial = 0.0; checksum_is = 0;
|
||||||
|
error = 0;
|
||||||
|
}
|
||||||
|
yield();
|
||||||
|
}
|
||||||
|
return error;
|
||||||
|
}
|
||||||
|
|
||||||
|
// --------------------------------------------------------
|
||||||
|
// SDS011:sleep
|
||||||
|
// --------------------------------------------------------
|
||||||
|
void SDS011::sleep() {
|
||||||
|
SDS_cmd(SDS_STOP_CMD);
|
||||||
|
}
|
||||||
|
|
||||||
|
// --------------------------------------------------------
|
||||||
|
// SDS011:wakeup
|
||||||
|
// --------------------------------------------------------
|
||||||
|
void SDS011::wakeup() {
|
||||||
|
SDS_cmd(SDS_START_CMD);
|
||||||
|
}
|
||||||
|
|
||||||
|
// --------------------------------------------------------
|
||||||
|
// SDS011:continous mode
|
||||||
|
// --------------------------------------------------------
|
||||||
|
void SDS011::contmode(int noOfMinutes)
|
||||||
|
{
|
||||||
|
byte buffer[SDS_cmd_len];
|
||||||
|
memcpy(buffer, SDS_CONT_MODE, SDS_cmd_len);
|
||||||
|
buffer[4] = (byte) noOfMinutes;
|
||||||
|
buffer[17] = calcChecksum( buffer );
|
||||||
|
for (uint8_t i = 0; i < SDS_cmd_len; i++) {
|
||||||
|
sds_data->write(buffer[i]);
|
||||||
|
}
|
||||||
|
sds_data->flush();
|
||||||
|
while (sds_data->available() > 0) {
|
||||||
|
sds_data->read();
|
||||||
|
}
|
||||||
|
// SDS_cmd(SDS_CONTINUOUS_MODE_CMD);
|
||||||
|
}
|
||||||
|
|
||||||
|
/*****************************************************************
|
||||||
|
* send SDS011 command (start, stop, continuous mode, version *
|
||||||
|
*****************************************************************/
|
||||||
|
void SDS011::SDS_cmd(const uint8_t cmd)
|
||||||
|
{
|
||||||
|
byte buf[SDS_cmd_len];
|
||||||
|
switch (cmd) {
|
||||||
|
case SDS_START_CMD:
|
||||||
|
memcpy(buf, SDS_START, SDS_cmd_len);
|
||||||
|
break;
|
||||||
|
case SDS_STOP_CMD:
|
||||||
|
memcpy(buf, SDS_SLEEP, SDS_cmd_len);
|
||||||
|
break;
|
||||||
|
case SDS_CONTINUOUS_MODE_CMD:
|
||||||
|
memcpy(buf, SDS_CONT_MODE, SDS_cmd_len);
|
||||||
|
break;
|
||||||
|
case SDS_VERSION_DATE_CMD:
|
||||||
|
memcpy(buf, SDS_VERSION, SDS_cmd_len);
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
for (uint8_t i = 0; i < SDS_cmd_len; i++) {
|
||||||
|
sds_data->write(buf[i]);
|
||||||
|
}
|
||||||
|
sds_data->flush();
|
||||||
|
while (sds_data->available() > 0) {
|
||||||
|
sds_data->read();
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
// --------------------------------------------------------
|
||||||
|
// SDS011: calculate checksum
|
||||||
|
// --------------------------------------------------------
|
||||||
|
uint8_t SDS011::calcChecksum( byte *buffer )
|
||||||
|
{
|
||||||
|
uint8_t value = 0;
|
||||||
|
|
||||||
|
for (uint8_t i = 2; i < 17; i++ )
|
||||||
|
{
|
||||||
|
value += buffer[i];
|
||||||
|
value &= 0xff;
|
||||||
|
}
|
||||||
|
return value;
|
||||||
|
}
|
||||||
|
|
||||||
|
void SDS011::begin(uint8_t pin_rx, uint8_t pin_tx) {
|
||||||
|
_pin_rx = pin_rx;
|
||||||
|
_pin_tx = pin_tx;
|
||||||
|
|
||||||
|
SoftwareSerial *softSerial = new SoftwareSerial(_pin_rx, _pin_tx);
|
||||||
|
softSerial->begin(9600);
|
||||||
|
|
||||||
|
sds_data = softSerial;
|
||||||
|
}
|
||||||
|
|
||||||
|
void SDS011::begin(HardwareSerial* serial) {
|
||||||
|
Serial.println("SDS011::begin");
|
||||||
|
// serial->begin(9600); // why do I have to remove this line?
|
||||||
|
sds_data = serial;
|
||||||
|
}
|
||||||
|
|
||||||
|
void SDS011::begin(SoftwareSerial* serial) {
|
||||||
|
serial->begin(9600);
|
||||||
|
sds_data = serial;
|
||||||
|
}
|
40
lib/SDS011/src/SDS011.h
Normal file
40
lib/SDS011/src/SDS011.h
Normal file
@ -0,0 +1,40 @@
|
|||||||
|
// SDS011 dust sensor PM2.5 and PM10
|
||||||
|
// ---------------------------------
|
||||||
|
//
|
||||||
|
// By R. Zschiegner (rz@madavi.de)
|
||||||
|
// April 2016
|
||||||
|
//
|
||||||
|
// Documentation:
|
||||||
|
// - The iNovaFitness SDS011 datasheet
|
||||||
|
//
|
||||||
|
|
||||||
|
#if ARDUINO >= 100
|
||||||
|
#include "Arduino.h"
|
||||||
|
#else
|
||||||
|
#include "WProgram.h"
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#include <SoftwareSerial.h>
|
||||||
|
|
||||||
|
// Definition SDS011 sensor 'commands'
|
||||||
|
#define SDS_START_CMD 1
|
||||||
|
#define SDS_STOP_CMD 2
|
||||||
|
#define SDS_CONTINUOUS_MODE_CMD 3
|
||||||
|
#define SDS_VERSION_DATE_CMD 4
|
||||||
|
|
||||||
|
class SDS011 {
|
||||||
|
public:
|
||||||
|
SDS011(void);
|
||||||
|
void begin(uint8_t pin_rx, uint8_t pin_tx);
|
||||||
|
void begin(HardwareSerial* serial);
|
||||||
|
void begin(SoftwareSerial* serial);
|
||||||
|
int read(float *p25, float *p10);
|
||||||
|
void sleep();
|
||||||
|
void wakeup();
|
||||||
|
void contmode( int );
|
||||||
|
private:
|
||||||
|
void SDS_cmd(const uint8_t);
|
||||||
|
uint8_t calcChecksum( byte *);
|
||||||
|
uint8_t _pin_rx, _pin_tx;
|
||||||
|
Stream *sds_data;
|
||||||
|
};
|
@ -328,6 +328,12 @@ void setup() {
|
|||||||
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
|
||||||
|
@ -6,6 +6,12 @@
|
|||||||
static const char TAG[] = __FILE__;
|
static const char TAG[] = __FILE__;
|
||||||
|
|
||||||
#include "sdcard.h"
|
#include "sdcard.h"
|
||||||
|
#if (HAS_SDS011)
|
||||||
|
#include <sds011read.h>
|
||||||
|
// the results of the sensor:
|
||||||
|
extern float pm25;
|
||||||
|
extern float pm10;
|
||||||
|
#endif
|
||||||
|
|
||||||
static bool useSDCard;
|
static bool useSDCard;
|
||||||
|
|
||||||
@ -35,7 +41,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)
|
||||||
|
ESP_LOGD(TAG, "fine-dust-values: %5.1f,%4.1f", pm10, pm25);
|
||||||
|
sprintf(tempBuffer, ",%5.1f,%4.1f", pm10, 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 +70,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;
|
||||||
}
|
}
|
||||||
|
36
src/sds011read.cpp
Normal file
36
src/sds011read.cpp
Normal file
@ -0,0 +1,36 @@
|
|||||||
|
// routines for fetching data from the SDS011-sensor
|
||||||
|
|
||||||
|
// Local logging tag
|
||||||
|
static const char TAG[] = __FILE__;
|
||||||
|
|
||||||
|
#include <sds011read.h>
|
||||||
|
|
||||||
|
// 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:
|
||||||
|
float pm25;
|
||||||
|
float pm10;
|
||||||
|
|
||||||
|
// init
|
||||||
|
bool sds011_init()
|
||||||
|
{
|
||||||
|
pm25 = pm10 = 0.0;
|
||||||
|
sdsSerial.begin(9600, SERIAL_8N1, ESP_PIN_RX, ESP_PIN_TX);
|
||||||
|
sdsSensor.begin (&sdsSerial);
|
||||||
|
sdsSensor.contmode(0); // for safety: wakeup/sleep - if we want it we do it by ourselves
|
||||||
|
sdsSensor.wakeup(); // always wake up
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
// reading data:
|
||||||
|
void sds011_loop()
|
||||||
|
{
|
||||||
|
pm25 = pm10 = 0.0;
|
||||||
|
int sdsErrorCode = sdsSensor.read(&pm25, &pm10);
|
||||||
|
if (!sdsErrorCode)
|
||||||
|
{
|
||||||
|
ESP_LOGD(TAG, "SDS011 error: %d", sdsErrorCode);
|
||||||
|
}
|
||||||
|
return;
|
||||||
|
}
|
Loading…
Reference in New Issue
Block a user