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.

188 lines
5.1 KiB

  1. // -----------------------------------------------------------------------------
  2. // T6613 CO2 sensor
  3. // https://www.amphenol-sensors.com/en/telaire/co2/525-co2-sensor-modules/321-t6613
  4. // Uses SoftwareSerial library
  5. // Copyright (C) 2017-2019 by Xose Pérez <xose dot perez at gmail dot com>
  6. // -----------------------------------------------------------------------------
  7. #if SENSOR_SUPPORT && T6613_SUPPORT
  8. #pragma once
  9. #include <SoftwareSerial.h>
  10. #include "BaseSensor.h"
  11. #define T6613_REQUEST_LEN 5
  12. #define T6613_RESPONSE_LEN 5
  13. #define T6613_TIMEOUT 1000
  14. #define T6613_GETPPM 0x020203
  15. class T6613Sensor : public BaseSensor {
  16. public:
  17. // ---------------------------------------------------------------------
  18. // Public
  19. // ---------------------------------------------------------------------
  20. T6613Sensor() {
  21. _count = 1;
  22. _sensor_id = SENSOR_T6613_ID;
  23. }
  24. ~T6613Sensor() {
  25. if (_serial) delete _serial;
  26. }
  27. // ---------------------------------------------------------------------
  28. void setRX(unsigned char pin_rx) {
  29. if (_pin_rx == pin_rx) return;
  30. _pin_rx = pin_rx;
  31. _dirty = true;
  32. }
  33. void setTX(unsigned char pin_tx) {
  34. if (_pin_tx == pin_tx) return;
  35. _pin_tx = pin_tx;
  36. _dirty = true;
  37. }
  38. // ---------------------------------------------------------------------
  39. unsigned char getRX() {
  40. return _pin_rx;
  41. }
  42. unsigned char getTX() {
  43. return _pin_tx;
  44. }
  45. // ---------------------------------------------------------------------
  46. // Sensor API
  47. // ---------------------------------------------------------------------
  48. // Initialization method, must be idempotent
  49. void begin() {
  50. if (!_dirty) return;
  51. if (_serial) delete _serial;
  52. _serial = new SoftwareSerial(_pin_rx, _pin_tx, false);
  53. _serial->enableIntTx(false);
  54. _serial->begin(19200);
  55. _ready = true;
  56. _dirty = false;
  57. }
  58. // Descriptive name of the sensor
  59. String description() {
  60. char buffer[28];
  61. snprintf(buffer, sizeof(buffer), "T6613 @ SwSerial(%u,%u)", _pin_rx, _pin_tx);
  62. return String(buffer);
  63. }
  64. // Descriptive name of the slot # index
  65. String description(unsigned char index) {
  66. return description();
  67. };
  68. // Address of the sensor (it could be the GPIO or I2C address)
  69. String address(unsigned char index) {
  70. char buffer[8];
  71. snprintf(buffer, sizeof(buffer), "%u:%u", _pin_rx, _pin_tx);
  72. return String(buffer);
  73. }
  74. // Type for slot # index
  75. unsigned char type(unsigned char index) {
  76. if (index == 0) return MAGNITUDE_CO2;
  77. return MAGNITUDE_NONE;
  78. }
  79. void pre() {
  80. _read();
  81. }
  82. // Current value for slot # index
  83. double value(unsigned char index) {
  84. if (index == 0) return _co2;
  85. return 0;
  86. }
  87. protected:
  88. // ---------------------------------------------------------------------
  89. // Protected
  90. // ---------------------------------------------------------------------
  91. void _write(unsigned char * command) {
  92. _serial->write(command, T6613_REQUEST_LEN);
  93. _serial->flush();
  94. }
  95. void _write(unsigned int command, unsigned char * response) {
  96. unsigned char buffer[T6613_REQUEST_LEN] = {0};
  97. buffer[0] = 0xFF;
  98. buffer[1] = 0xFE;
  99. buffer[2] = command >> 16;
  100. buffer[3] = (command >> 8) & 0xFF;
  101. buffer[4] = command & 0xFF;
  102. _write(buffer);
  103. if (response != NULL) {
  104. unsigned long start = millis();
  105. while (_serial->available() == 0) {
  106. if (millis() - start > T6613_TIMEOUT) {
  107. _error = SENSOR_ERROR_TIMEOUT;
  108. return;
  109. }
  110. yield();
  111. }
  112. _serial->readBytes(response, T6613_RESPONSE_LEN);
  113. }
  114. }
  115. void _write(unsigned int command) {
  116. _write(command, NULL);
  117. }
  118. void _read() {
  119. unsigned char buffer[T6613_RESPONSE_LEN] = {0};
  120. _write(T6613_GETPPM, buffer);
  121. // Check response
  122. if ((buffer[0] == 0xFF)
  123. && (buffer[1] == 0xFA)
  124. && (buffer[2] == 0x02)) {
  125. unsigned int value = buffer[3] * 256 + buffer[4];
  126. if (0 <= value && value <= 5000) {
  127. _co2 = value;
  128. _error = SENSOR_ERROR_OK;
  129. } else {
  130. _error = SENSOR_ERROR_OUT_OF_RANGE;
  131. }
  132. } else {
  133. _error = SENSOR_ERROR_CRC;
  134. }
  135. }
  136. double _co2 = 0;
  137. unsigned int _pin_rx;
  138. unsigned int _pin_tx;
  139. SoftwareSerial * _serial = NULL;
  140. };
  141. #endif // SENSOR_SUPPORT && T6613_SUPPORT