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