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.

130 lines
3.0 KiB

  1. /*
  2. EMON MODULE
  3. Copyright (C) 2016-2017 by Xose Pérez <xose dot perez at gmail dot com>
  4. */
  5. #if ENABLE_EMON
  6. #include <EmonLiteESP.h>
  7. EmonLiteESP emon;
  8. double _current = 0;
  9. unsigned int _power = 0;
  10. // -----------------------------------------------------------------------------
  11. // EMON
  12. // -----------------------------------------------------------------------------
  13. void setCurrentRatio(float value) {
  14. emon.setCurrentRatio(value);
  15. }
  16. unsigned int getPower() {
  17. return _power;
  18. }
  19. double getCurrent() {
  20. return _current;
  21. }
  22. unsigned int currentCallback() {
  23. return analogRead(EMON_CURRENT_PIN);
  24. }
  25. void powerMonitorSetup() {
  26. // backwards compatibility
  27. String tmp;
  28. tmp = getSetting("pwMainsVoltage", EMON_MAINS_VOLTAGE);
  29. setSetting("emonMains", tmp);
  30. delSetting("pwMainsVoltage");
  31. tmp = getSetting("pwCurrentRatio", EMON_CURRENT_RATIO);
  32. setSetting("emonRatio", tmp);
  33. delSetting("pwCurrentRatio");
  34. emon.initCurrent(
  35. currentCallback,
  36. EMON_ADC_BITS,
  37. EMON_REFERENCE_VOLTAGE,
  38. getSetting("emonRatio", EMON_CURRENT_RATIO).toFloat()
  39. );
  40. emon.setPrecision(EMON_CURRENT_PRECISION);
  41. apiRegister("/api/power", "power", [](char * buffer, size_t len) {
  42. snprintf(buffer, len, "%d", _power);
  43. });
  44. }
  45. void powerMonitorLoop() {
  46. static unsigned long next_measurement = millis();
  47. static bool warmup = true;
  48. static byte measurements = 0;
  49. static double max = 0;
  50. static double min = 0;
  51. static double sum = 0;
  52. if (!mqttConnected()) return;
  53. if (warmup) {
  54. warmup = false;
  55. emon.warmup();
  56. }
  57. if (millis() > next_measurement) {
  58. // Safety check: do not read current if relay is OFF
  59. if (!relayStatus(0)) {
  60. _current = 0;
  61. } else {
  62. _current = emon.getCurrent(EMON_SAMPLES);
  63. _current -= EMON_CURRENT_OFFSET;
  64. if (_current < 0) _current = 0;
  65. }
  66. if (measurements == 0) {
  67. max = min = _current;
  68. } else {
  69. if (_current > max) max = _current;
  70. if (_current < min) min = _current;
  71. }
  72. sum += _current;
  73. ++measurements;
  74. float mainsVoltage = getSetting("emonMains", EMON_MAINS_VOLTAGE).toFloat();
  75. //DEBUG_MSG("[ENERGY] Power now: %dW\n", int(_current * mainsVoltage));
  76. // Update websocket clients
  77. char text[20];
  78. sprintf_P(text, PSTR("{\"emonPower\": %d}"), int(_current * mainsVoltage));
  79. wsSend(text);
  80. // Send MQTT messages averaged every EMON_MEASUREMENTS
  81. if (measurements == EMON_MEASUREMENTS) {
  82. _power = (int) ((sum - max - min) * mainsVoltage / (measurements - 2));
  83. sum = 0;
  84. measurements = 0;
  85. char power[6];
  86. snprintf(power, "%d", 6, _power);
  87. mqttSend(getSetting("emonPowerTopic", EMON_POWER_TOPIC).c_str(), power);
  88. #if ENABLE_DOMOTICZ
  89. domoticzSend("dczPowIdx", power);
  90. #endif
  91. }
  92. next_measurement += EMON_INTERVAL;
  93. }
  94. }
  95. #endif