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.

129 lines
3.7 KiB

  1. // -----------------------------------------------------------------------------
  2. // Energy monitor sensor
  3. // -----------------------------------------------------------------------------
  4. #pragma once
  5. #include "Arduino.h"
  6. #include "BaseSensor.h"
  7. #include "EmonSensor.h"
  8. #if I2C_USE_BRZO
  9. #include <brzo_i2c.h>
  10. #else
  11. #include <Wire.h>
  12. #endif
  13. // ADC121 Registers
  14. #define ADC121_REG_RESULT 0x00
  15. #define ADC121_REG_ALERT 0x01
  16. #define ADC121_REG_CONFIG 0x02
  17. #define ADC121_REG_LIMITL 0x03
  18. #define ADC121_REG_LIMITH 0x04
  19. #define ADC121_REG_HYST 0x05
  20. #define ADC121_REG_CONVL 0x06
  21. #define ADC121_REG_CONVH 0x07
  22. class EmonADC121Sensor : public EmonSensor {
  23. public:
  24. EmonADC121Sensor(unsigned char address, double voltage, unsigned char bits, double ref, double ratio): EmonSensor(voltage, bits, ref, ratio) {
  25. // Cache
  26. _address = address;
  27. // Init sensor
  28. #if I2C_USE_BRZO
  29. uint8_t buffer[2];
  30. buffer[0] = ADC121_REG_CONFIG;
  31. buffer[1] = 0x00;
  32. brzo_i2c_start_transaction(_address, I2C_SCL_FREQUENCY);
  33. brzo_i2c_write(buffer, 2, false);
  34. brzo_i2c_end_transaction();
  35. #else
  36. Wire.beginTransmission(_address);
  37. Wire.write(ADC121_REG_CONFIG);
  38. Wire.write(0x00);
  39. Wire.endTransmission();
  40. #endif
  41. // warmup
  42. read(EMON_ADC121_WARMUP_VALUE, EMON_ADC121_WARMUP_MODE, _address);
  43. }
  44. // Descriptive name of the sensor
  45. String name() {
  46. char buffer[20];
  47. snprintf(buffer, sizeof(buffer), "EMON @ ADC121 @ I2C (0x%02X)", _address);
  48. return String(buffer);
  49. }
  50. // Descriptive name of the slot # index
  51. String slot(unsigned char index) {
  52. return name();
  53. }
  54. // Type for slot # index
  55. magnitude_t type(unsigned char index) {
  56. _error = SENSOR_ERROR_OK;
  57. if (index == 0) return MAGNITUDE_CURRENT;
  58. if (index == 1) return MAGNITUDE_POWER_APPARENT;
  59. _error = SENSOR_ERROR_OUT_OF_RANGE;
  60. return MAGNITUDE_NONE;
  61. }
  62. // Current value for slot # index
  63. double value(unsigned char index) {
  64. _error = SENSOR_ERROR_OK;
  65. // Cache the value
  66. static unsigned long last = 0;
  67. static double current = 0;
  68. if ((last == 0) || (millis() - last > 1000)) {
  69. current = read(EMON_ADC121_READ_VALUE, EMON_ADC121_READ_MODE, _address);
  70. last = millis();
  71. }
  72. if (index == 0) return current;
  73. if (index == 1) return current * _voltage;
  74. _error = SENSOR_ERROR_OUT_OF_RANGE;
  75. return 0;
  76. }
  77. protected:
  78. unsigned int readADC(unsigned char port) {
  79. unsigned int value;
  80. #if I2C_USE_BRZO
  81. uint8_t buffer[2];
  82. buffer[0] = ADC121_REG_RESULT;
  83. brzo_i2c_start_transaction(_address, I2C_SCL_FREQUENCY);
  84. brzo_i2c_write(buffer, 1, false);
  85. brzo_i2c_read(buffer, 2, false);
  86. brzo_i2c_end_transaction();
  87. value = (buffer[0] & 0x0F) << 8;
  88. value |= buffer[1];
  89. #else
  90. Wire.beginTransmission(port);
  91. Wire.write(ADC121_REG_RESULT);
  92. Wire.endTransmission();
  93. Wire.requestFrom(port, (unsigned char) 2);
  94. value = (Wire.read() & 0x0F) << 8;
  95. value = value + Wire.read();
  96. #endif
  97. return value;
  98. }
  99. unsigned char _address;
  100. };