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.

152 lines
4.4 KiB

  1. // -----------------------------------------------------------------------------
  2. // ADS121-based Energy Monitor Sensor over I2C
  3. // Copyright (C) 2017-2019 by Xose Pérez <xose dot perez at gmail dot com>
  4. // -----------------------------------------------------------------------------
  5. #if SENSOR_SUPPORT && EMON_ADC121_SUPPORT
  6. #pragma once
  7. #include <Arduino.h>
  8. #include "../utils.h"
  9. #include "EmonSensor.h"
  10. // ADC121 Registers
  11. #define ADC121_REG_RESULT 0x00
  12. #define ADC121_REG_ALERT 0x01
  13. #define ADC121_REG_CONFIG 0x02
  14. #define ADC121_REG_LIMITL 0x03
  15. #define ADC121_REG_LIMITH 0x04
  16. #define ADC121_REG_HYST 0x05
  17. #define ADC121_REG_CONVL 0x06
  18. #define ADC121_REG_CONVH 0x07
  19. #define ADC121_RESOLUTION 12
  20. #define ADC121_CHANNELS 1
  21. class EmonADC121Sensor : public EmonSensor {
  22. public:
  23. // ---------------------------------------------------------------------
  24. // Public
  25. // ---------------------------------------------------------------------
  26. EmonADC121Sensor(): EmonSensor() {
  27. _channels = ADC121_CHANNELS;
  28. _sensor_id = SENSOR_EMON_ADC121_ID;
  29. init();
  30. }
  31. // ---------------------------------------------------------------------
  32. // Sensor API
  33. // ---------------------------------------------------------------------
  34. // Initialization method, must be idempotent
  35. void begin() {
  36. if (!_dirty) return;
  37. _dirty = false;
  38. // Discover
  39. unsigned char addresses[] = {0x50, 0x51, 0x52, 0x54, 0x55, 0x56, 0x58, 0x59, 0x5A};
  40. _address = _begin_i2c(_address, sizeof(addresses), addresses);
  41. if (_address == 0) return;
  42. // Init sensor
  43. _init();
  44. // Just one channel
  45. _count = _magnitudes;
  46. // Bit depth
  47. _resolution = ADC121_RESOLUTION;
  48. // Call the parent class method
  49. EmonSensor::begin();
  50. // warmup channel 0 (the only one)
  51. read(0);
  52. }
  53. // Descriptive name of the sensor
  54. String description() {
  55. char buffer[30];
  56. snprintf(buffer, sizeof(buffer), "EMON @ ADC121 @ I2C (0x%02X)", _address);
  57. return String(buffer);
  58. }
  59. // Pre-read hook (usually to populate registers with up-to-date data)
  60. void pre() {
  61. if (_address == 0) {
  62. _error = SENSOR_ERROR_UNKNOWN_ID;
  63. return;
  64. }
  65. _current[0] = read(0);
  66. #if EMON_REPORT_ENERGY
  67. static unsigned long last = 0;
  68. if (last > 0) {
  69. _energy[0] += (_current[0] * _voltage * (millis() - last) / 1000);
  70. }
  71. last = millis();
  72. #endif
  73. _error = SENSOR_ERROR_OK;
  74. }
  75. // Type for slot # index
  76. unsigned char type(unsigned char index) {
  77. unsigned char i=0;
  78. #if EMON_REPORT_CURRENT
  79. if (index == i++) return MAGNITUDE_CURRENT;
  80. #endif
  81. #if EMON_REPORT_POWER
  82. if (index == i++) return MAGNITUDE_POWER_APPARENT;
  83. #endif
  84. #if EMON_REPORT_ENERGY
  85. if (index == i) return MAGNITUDE_ENERGY;
  86. #endif
  87. return MAGNITUDE_NONE;
  88. }
  89. // Current value for slot # index
  90. double value(unsigned char index) {
  91. unsigned char channel = index / _magnitudes;
  92. unsigned char i=0;
  93. #if EMON_REPORT_CURRENT
  94. if (index == i++) return _current[channel];
  95. #endif
  96. #if EMON_REPORT_POWER
  97. if (index == i++) return _current[channel] * _voltage;
  98. #endif
  99. #if EMON_REPORT_ENERGY
  100. if (index == i) return _energy[channel];
  101. #endif
  102. return 0;
  103. }
  104. protected:
  105. // ---------------------------------------------------------------------
  106. // Protected
  107. // ---------------------------------------------------------------------
  108. void _init() {
  109. i2c_write_uint8(_address, ADC121_REG_CONFIG, 0);
  110. }
  111. unsigned int readADC(unsigned char channel) {
  112. UNUSED(channel);
  113. unsigned int value = i2c_read_uint16(_address, ADC121_REG_RESULT) & 0x0FFF;
  114. return value;
  115. }
  116. };
  117. #endif // SENSOR_SUPPORT && EMON_ADC121_SUPPORT