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.

160 lines
5.1 KiB

  1. // -----------------------------------------------------------------------------
  2. // HDC1080 / 831R Sensor over I2C
  3. // Based on SI7021 / HTU21D Sensor over I2C
  4. // Copyright (C) 2017-2019 by Xose Pérez <xose dot perez at gmail dot com>
  5. // Copyright (C) 2020 by Alexander Kolesnikov <vtochq at gmail dot com>
  6. // -----------------------------------------------------------------------------
  7. #if SENSOR_SUPPORT && HDC1080_SUPPORT
  8. #pragma once
  9. #include <Arduino.h>
  10. #include "I2CSensor.h"
  11. #include "../utils.h"
  12. #define HDC1080_SCL_FREQUENCY 200
  13. // ref. http://www.ti.com/lit/ds/symlink/hdc1080.pdf
  14. // Device ID. Should be the same for every device.
  15. #define HDC1080_DEVICE_ID 0x1050
  16. #define HDC1080_CMD_TMP 0x00
  17. #define HDC1080_CMD_HUM 0x01
  18. class HDC1080Sensor : public I2CSensor<> {
  19. public:
  20. // ---------------------------------------------------------------------
  21. // Public
  22. // ---------------------------------------------------------------------
  23. HDC1080Sensor() {
  24. _sensor_id = SENSOR_HDC1080_ID;
  25. }
  26. // ---------------------------------------------------------------------
  27. // Sensor API
  28. // ---------------------------------------------------------------------
  29. // Initialization method, must be idempotent
  30. void begin() {
  31. if (!_dirty) return;
  32. _init();
  33. _dirty = !_ready;
  34. }
  35. // Descriptive name of the sensor
  36. String description() {
  37. char buffer[25];
  38. snprintf_P(buffer, sizeof(buffer), PSTR("HDC1080 @ I2C (0x%02X)"), _address);
  39. return String(buffer);
  40. }
  41. // Descriptive name of the slot # index
  42. String description(unsigned char index) {
  43. return description();
  44. };
  45. // Type for slot # index
  46. unsigned char type(unsigned char index) {
  47. if (index == 0) return MAGNITUDE_TEMPERATURE;
  48. if (index == 1) return MAGNITUDE_HUMIDITY;
  49. return MAGNITUDE_NONE;
  50. }
  51. // Pre-read hook (usually to populate registers with up-to-date data)
  52. void pre() {
  53. _error = SENSOR_ERROR_OK;
  54. double value;
  55. value = _read(HDC1080_CMD_TMP);
  56. if (_error != SENSOR_ERROR_OK) return;
  57. _temperature = (165 * value / 65536) - 40;
  58. value = _read(HDC1080_CMD_HUM);
  59. if (_error != SENSOR_ERROR_OK) return;
  60. value = (value / 65536)*100;
  61. _humidity = constrain(value, 0, 100);
  62. }
  63. // Current value for slot # index
  64. double value(unsigned char index) {
  65. if (index == 0) return _temperature;
  66. if (index == 1) return _humidity;
  67. return 0;
  68. }
  69. protected:
  70. // ---------------------------------------------------------------------
  71. // Protected
  72. // ---------------------------------------------------------------------
  73. void _init() {
  74. // I2C auto-discover
  75. unsigned char addresses[] = {0x40};
  76. _address = _begin_i2c(_address, sizeof(addresses), addresses);
  77. if (_address == 0) return;
  78. // Check device ID before doing anything else
  79. // ref. https://github.com/xoseperez/espurna/issues/2270#issuecomment-639239944
  80. // > Also there are clones of HDC1080 and they may have different Device ID
  81. // > values. You need to check it by reading and debug output this bytes.
  82. i2c_write_uint8(_address, 0xFF);
  83. _device_id = i2c_read_uint16(_address);
  84. if (_device_id == HDC1080_DEVICE_ID) {
  85. _ready = true;
  86. _count = 2;
  87. return;
  88. }
  89. DEBUG_MSG_P(PSTR("[HDC1080] ERROR: Expected Device ID %04X, received %04X\n"), HDC1080_DEVICE_ID, _device_id);
  90. _count = 0;
  91. i2cReleaseLock(_address);
  92. _previous_address = 0;
  93. _error = SENSOR_ERROR_UNKNOWN_ID;
  94. // Setting _address to 0 forces auto-discover
  95. // This might be necessary at this stage if there is a
  96. // different sensor in the hardcoded address
  97. _address = 0;
  98. _ready = false;
  99. }
  100. unsigned int _read(uint8_t command) {
  101. // Request measurement
  102. i2c_write_uint8(_address, command);
  103. // When not using clock stretching (*_NOHOLD commands) delay here
  104. // is needed to wait for the measurement.
  105. // According to datasheet the max. conversion time is ~22ms
  106. nice_delay(50);
  107. // Clear the last to bits of LSB to 00.
  108. // According to datasheet LSB of Temp and RH is always xxxxxx00
  109. unsigned int value = i2c_read_uint16(_address) & 0xFFFC;
  110. // We should be checking there are no pending bytes in the buffer
  111. // and raise a CRC error if there are
  112. _error = SENSOR_ERROR_OK;
  113. return value;
  114. }
  115. uint16_t _device_id = 0;
  116. double _temperature = 0;
  117. double _humidity = 0;
  118. };
  119. #endif // SENSOR_SUPPORT && HDC1080_SUPPORT