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.

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