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.

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