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.

162 lines
4.9 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. // Middle byte of Device Serial ID. May be diffirent on your chip (see debug i2c.scan)
  14. #define HDC1080_CHIP_HDC1080 0x2C
  15. #define HDC1080_CMD_TMP 0x00
  16. #define HDC1080_CMD_HUM 0x01
  17. PROGMEM const char hdc1080_chip_hdc1080_name[] = "HDC1080";
  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 name[10];
  38. strncpy_P(name, hdc1080_chip_hdc1080_name, sizeof(name));
  39. char buffer[25];
  40. snprintf(buffer, sizeof(buffer), "%s @ I2C (0x%02X)", name, _address);
  41. return String(buffer);
  42. }
  43. // Descriptive name of the slot # index
  44. String description(unsigned char index) {
  45. return description();
  46. };
  47. // Type for slot # index
  48. unsigned char type(unsigned char index) {
  49. if (index == 0) return MAGNITUDE_TEMPERATURE;
  50. if (index == 1) return MAGNITUDE_HUMIDITY;
  51. return MAGNITUDE_NONE;
  52. }
  53. // Pre-read hook (usually to populate registers with up-to-date data)
  54. void pre() {
  55. _error = SENSOR_ERROR_UNKNOWN_ID;
  56. if (_chip == 0) return;
  57. _error = SENSOR_ERROR_OK;
  58. double value;
  59. value = _read(HDC1080_CMD_TMP);
  60. if (_error != SENSOR_ERROR_OK) return;
  61. _temperature = (165 * value / 65536) - 40;
  62. value = _read(HDC1080_CMD_HUM);
  63. if (_error != SENSOR_ERROR_OK) return;
  64. value = (value / 65536)*100;
  65. _humidity = constrain(value, 0, 100);
  66. }
  67. // Current value for slot # index
  68. double value(unsigned char index) {
  69. if (index == 0) return _temperature;
  70. if (index == 1) return _humidity;
  71. return 0;
  72. }
  73. protected:
  74. // ---------------------------------------------------------------------
  75. // Protected
  76. // ---------------------------------------------------------------------
  77. void _init() {
  78. // I2C auto-discover
  79. unsigned char addresses[] = {0x40};
  80. _address = _begin_i2c(_address, sizeof(addresses), addresses);
  81. if (_address == 0) return;
  82. // Check device
  83. i2c_write_uint8(_address, 0xFC, 0xC9);
  84. _chip = i2c_read_uint8(_address);
  85. if (_chip != HDC1080_CHIP_HDC1080) {
  86. _count = 0;
  87. i2cReleaseLock(_address);
  88. _previous_address = 0;
  89. _error = SENSOR_ERROR_UNKNOWN_ID;
  90. // Setting _address to 0 forces auto-discover
  91. // This might be necessary at this stage if there is a
  92. // different sensor in the hardcoded address
  93. _address = 0;
  94. } else {
  95. _count = 2;
  96. }
  97. _ready = true;
  98. }
  99. unsigned int _read(uint8_t command) {
  100. // Request measurement
  101. i2c_write_uint8(_address, command);
  102. // When not using clock stretching (*_NOHOLD commands) delay here
  103. // is needed to wait for the measurement.
  104. // According to datasheet the max. conversion time is ~22ms
  105. nice_delay(50);
  106. // Clear the last to bits of LSB to 00.
  107. // According to datasheet LSB of Temp and RH is always xxxxxx00
  108. unsigned int value = i2c_read_uint16(_address) & 0xFFFC;
  109. // We should be checking there are no pending bytes in the buffer
  110. // and raise a CRC error if there are
  111. _error = SENSOR_ERROR_OK;
  112. return value;
  113. }
  114. unsigned char _chip;
  115. double _temperature = 0;
  116. double _humidity = 0;
  117. };
  118. #endif // SENSOR_SUPPORT && HDC1080_SUPPORT