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"); | ||||
| #endif | ||||
| 
 | ||||
| #if (HAS_SDS011) | ||||
| //    ESP_LOGI(TAG, "init fine-dust-sensor");
 | ||||
|     if ( sds011_init() ) | ||||
|         strcat_P(features, " SDS"); | ||||
| #endif | ||||
| 
 | ||||
| #if (VENDORFILTER) | ||||
|   strcat_P(features, " FILTER"); | ||||
| #endif | ||||
|  | ||||
| @ -6,6 +6,12 @@ | ||||
| static const char TAG[] = __FILE__; | ||||
| 
 | ||||
| #include "sdcard.h" | ||||
| #if (HAS_SDS011) | ||||
| #include <sds011read.h> | ||||
| // the results of the sensor:
 | ||||
| extern float pm25;               | ||||
| extern float pm10; | ||||
| #endif | ||||
| 
 | ||||
| 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)); | ||||
|   fileSDCard.print(tempBuffer); | ||||
|   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) { | ||||
|     // force writing to SD-card
 | ||||
| @ -58,8 +70,12 @@ void createFile(void) { | ||||
|       ESP_LOGD(TAG, "SD: file does not exist: opening"); | ||||
|       fileSDCard = SD.open(bufferFilename, FILE_WRITE); | ||||
|       if (fileSDCard) { | ||||
|         ESP_LOGD(TAG, "SD: name opended: <%s>", bufferFilename); | ||||
|         fileSDCard.println(SDCARD_FILE_HEADER); | ||||
|         ESP_LOGD(TAG, "SD: name opened: <%s>", bufferFilename); | ||||
|         fileSDCard.print( SDCARD_FILE_HEADER ); | ||||
| #if (HAS_SDS011) | ||||
|         fileSDCard.print( SDCARD_FILE_HEADER_SDS011 ); | ||||
| #endif | ||||
|         fileSDCard.println(); | ||||
|         useSDCard = true; | ||||
|         break; | ||||
|       } | ||||
| @ -68,4 +84,4 @@ void createFile(void) { | ||||
|   return; | ||||
| } | ||||
| 
 | ||||
| #endif // (HAS_SDCARD)
 | ||||
| #endif // (HAS_SDCARD)
 | ||||
|  | ||||
							
								
								
									
										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