Fork of the espurna firmware for `mhsw` switches
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

173 lines
5.2 KiB

  1. // -----------------------------------------------------------------------------
  2. // SDS011 particulates sensor
  3. // Based on: https://github.com/ricki-z/SDS011
  4. //
  5. // Uses SoftwareSerial library
  6. // Copyright (C) 2018 by Lucas Pleß <hello at lucas-pless dot com>
  7. // -----------------------------------------------------------------------------
  8. #if SENSOR_SUPPORT && SDS011_SUPPORT
  9. #pragma once
  10. #include "Arduino.h"
  11. #include "BaseSensor.h"
  12. #include <SoftwareSerial.h>
  13. class SDS011Sensor : public BaseSensor {
  14. public:
  15. // ---------------------------------------------------------------------
  16. // Public
  17. // ---------------------------------------------------------------------
  18. SDS011Sensor(): BaseSensor() {
  19. _count = 2;
  20. _sensor_id = SENSOR_SDS011_ID;
  21. }
  22. ~SDS011Sensor() {
  23. if (_serial) delete _serial;
  24. }
  25. // ---------------------------------------------------------------------
  26. void setRX(unsigned char pin_rx) {
  27. if (_pin_rx == pin_rx) return;
  28. _pin_rx = pin_rx;
  29. _dirty = true;
  30. }
  31. void setTX(unsigned char pin_tx) {
  32. if (_pin_tx == pin_tx) return;
  33. _pin_tx = pin_tx;
  34. _dirty = true;
  35. }
  36. // ---------------------------------------------------------------------
  37. unsigned char getRX() {
  38. return _pin_rx;
  39. }
  40. unsigned char getTX() {
  41. return _pin_tx;
  42. }
  43. // ---------------------------------------------------------------------
  44. // Sensor API
  45. // ---------------------------------------------------------------------
  46. // Initialization method, must be idempotent
  47. void begin() {
  48. if (!_dirty) return;
  49. if (_serial) delete _serial;
  50. _serial = new SoftwareSerial(_pin_rx, _pin_tx);
  51. _serial->begin(9600);
  52. _ready = true;
  53. _dirty = false;
  54. }
  55. // Descriptive name of the sensor
  56. String description() {
  57. char buffer[28];
  58. snprintf(buffer, sizeof(buffer), "SDS011 @ SwSerial(%u,%u)", _pin_rx, _pin_tx);
  59. return String(buffer);
  60. }
  61. // Descriptive name of the slot # index
  62. String slot(unsigned char index) {
  63. return description();
  64. };
  65. // Address of the sensor (it could be the GPIO or I2C address)
  66. String address(unsigned char index) {
  67. char buffer[6];
  68. snprintf(buffer, sizeof(buffer), "%u:%u", _pin_rx, _pin_tx);
  69. return String(buffer);
  70. }
  71. // Type for slot # index
  72. unsigned char type(unsigned char index) {
  73. if (index == 0) return MAGNITUDE_PM2dot5;
  74. if (index == 1) return MAGNITUDE_PM10;
  75. return MAGNITUDE_NONE;
  76. }
  77. void pre() {
  78. _read();
  79. }
  80. // Current value for slot # index
  81. double value(unsigned char index) {
  82. if (index == 0) return _p2dot5;
  83. if (index == 1) return _p10;
  84. return 0;
  85. }
  86. protected:
  87. // ---------------------------------------------------------------------
  88. // Protected
  89. // ---------------------------------------------------------------------
  90. void _read() {
  91. byte buffer;
  92. int value;
  93. int len = 0;
  94. int pm10_serial = 0;
  95. int pm25_serial = 0;
  96. int checksum_is;
  97. int checksum_ok = 0;
  98. while ((_serial->available() > 0) && (_serial->available() >= (10-len))) {
  99. buffer = _serial->read();
  100. value = int(buffer);
  101. switch (len) {
  102. case (0): if (value != 170) { len = -1; }; break;
  103. case (1): if (value != 192) { len = -1; }; break;
  104. case (2): pm25_serial = value; checksum_is = value; break;
  105. case (3): pm25_serial += (value << 8); checksum_is += value; break;
  106. case (4): pm10_serial = value; checksum_is += value; break;
  107. case (5): pm10_serial += (value << 8); checksum_is += value; break;
  108. case (6): checksum_is += value; break;
  109. case (7): checksum_is += value; break;
  110. case (8): if (value == (checksum_is % 256)) { checksum_ok = 1; } else { len = -1; }; break;
  111. case (9): if (value != 171) { len = -1; }; break;
  112. }
  113. len++;
  114. if (len == 10) {
  115. if(checksum_ok == 1) {
  116. _p10 = (float)pm10_serial/10.0;
  117. _p2dot5 = (float)pm25_serial/10.0;
  118. len = 0; checksum_ok = 0; pm10_serial = 0.0; pm25_serial = 0.0; checksum_is = 0;
  119. _error = SENSOR_ERROR_OK;
  120. } else {
  121. _error = SENSOR_ERROR_CRC;
  122. }
  123. }
  124. yield();
  125. }
  126. }
  127. double _p2dot5 = 0;
  128. double _p10 = 0;
  129. unsigned int _pin_rx;
  130. unsigned int _pin_tx;
  131. SoftwareSerial * _serial = NULL;
  132. };
  133. #endif // SENSOR_SUPPORT && SDS011_SUPPORT