- /*
-
- EMON MODULE
-
- Copyright (C) 2016-2017 by Xose Pérez <xose dot perez at gmail dot com>
-
- */
-
- #if ENABLE_EMON
-
- #include <EmonLiteESP.h>
- #include "brzo_i2c.h"
- #include <EEPROM.h>
-
- // ADC121 Registers
- #define ADC121_REG_RESULT 0x00
- #define ADC121_REG_ALERT 0x01
- #define ADC121_REG_CONFIG 0x02
- #define ADC121_REG_LIMITL 0x03
- #define ADC121_REG_LIMITH 0x04
- #define ADC121_REG_HYST 0x05
- #define ADC121_REG_CONVL 0x06
- #define ADC121_REG_CONVH 0x07
-
- EmonLiteESP emon;
- double _current = 0;
- unsigned int _power = 0;
- double _energy = 0;
-
- // -----------------------------------------------------------------------------
- // Provider
- // -----------------------------------------------------------------------------
-
- unsigned int currentCallback() {
-
- #if EMON_PROVIDER == EMON_ANALOG_PROVIDER
- return analogRead(EMON_CURRENT_PIN);
- #endif
-
- #if EMON_PROVIDER == EMON_ADC121_PROVIDER
- uint8_t buffer[2];
- brzo_i2c_start_transaction(EMON_ADC121_ADDRESS, I2C_SCL_FREQUENCY);
- buffer[0] = ADC121_REG_RESULT;
- brzo_i2c_write(buffer, 1, false);
- brzo_i2c_read(buffer, 2, false);
- brzo_i2c_end_transaction();
- unsigned int value;
- value = (buffer[0] & 0x0F) << 8;
- value |= buffer[1];
- return value;
- #endif
-
- }
-
- // -----------------------------------------------------------------------------
- // EMON
- // -----------------------------------------------------------------------------
-
- void setCurrentRatio(float value) {
- emon.setCurrentRatio(value);
- }
-
- unsigned int getPower() {
- return _power;
- }
-
- double getEnergy() {
- return _energy;
- }
-
- double getCurrent() {
- return _current;
- }
-
- void retrieveEnergy() {
- unsigned long energy = EEPROM.read(EEPROM_POWER_COUNT + 1);
- energy = (energy << 8) + EEPROM.read(EEPROM_POWER_COUNT);
- if (energy == 0xFFFF) energy = 0;
- _energy = energy;
- }
-
- void saveEnergy() {
- unsigned int energy = (int) _energy;
- EEPROM.write(EEPROM_POWER_COUNT, energy & 0xFF);
- EEPROM.write(EEPROM_POWER_COUNT + 1, (energy >> 8) & 0xFF);
- EEPROM.commit();
- }
-
- void powerMonitorSetup() {
-
- // backwards compatibility
- String tmp;
- tmp = getSetting("pwMainsVoltage", EMON_MAINS_VOLTAGE);
- setSetting("emonMains", tmp);
- delSetting("pwMainsVoltage");
- tmp = getSetting("pwCurrentRatio", EMON_CURRENT_RATIO);
- setSetting("emonRatio", tmp);
- delSetting("pwCurrentRatio");
-
- emon.initCurrent(
- currentCallback,
- EMON_ADC_BITS,
- EMON_REFERENCE_VOLTAGE,
- getSetting("emonRatio", EMON_CURRENT_RATIO).toFloat()
- );
- emon.setPrecision(EMON_CURRENT_PRECISION);
-
- #if EMON_PROVIDER == EMON_ADC121_PROVIDER
- uint8_t buffer[2];
- buffer[0] = ADC121_REG_CONFIG;
- buffer[1] = 0x00;
- brzo_i2c_start_transaction(EMON_ADC121_ADDRESS, I2C_SCL_FREQUENCY);
- brzo_i2c_write(buffer, 2, false);
- brzo_i2c_end_transaction();
- #endif
-
- apiRegister("/api/power", "power", [](char * buffer, size_t len) {
- snprintf(buffer, len, "%d", _power);
- });
- apiRegister("/api/energy", "energy", [](char * buffer, size_t len) {
- snprintf(buffer, len, "%ld", (unsigned long) _energy);
- });
-
- retrieveEnergy();
-
- }
-
- void powerMonitorLoop() {
-
- static unsigned long next_measurement = millis();
- static bool warmup = true;
- static byte measurements = 0;
- static double max = 0;
- static double min = 0;
- static double sum = 0;
-
- if (!mqttConnected()) return;
-
- if (warmup) {
- warmup = false;
- emon.warmup();
- }
-
- if (millis() > next_measurement) {
-
- // Safety check: do not read current if relay is OFF
- // You could be monitoring another line with the current clamp...
- //if (!relayStatus(0)) {
- // _current = 0;
- //} else {
- _current = emon.getCurrent(EMON_SAMPLES);
- _current -= EMON_CURRENT_OFFSET;
- if (_current < 0) _current = 0;
- //}
-
- if (measurements == 0) {
- max = min = _current;
- } else {
- if (_current > max) max = _current;
- if (_current < min) min = _current;
- }
- sum += _current;
- ++measurements;
-
- float mainsVoltage = getSetting("emonMains", EMON_MAINS_VOLTAGE).toFloat();
-
- char current[6];
- dtostrf(_current, 5, 2, current);
- DEBUG_MSG("[ENERGY] Current: %sA\n", current);
- DEBUG_MSG("[ENERGY] Power: %dW\n", int(_current * mainsVoltage));
-
- // Update websocket clients
- char text[64];
- sprintf_P(text, PSTR("{\"emonVisible\": 1, \"powApparentPower\": %d}"), int(_current * mainsVoltage));
- wsSend(text);
-
- // Send MQTT messages averaged every EMON_MEASUREMENTS
- if (measurements == EMON_MEASUREMENTS) {
-
- _power = (int) ((sum - max - min) * mainsVoltage / (measurements - 2));
- double window = (double) EMON_INTERVAL * EMON_MEASUREMENTS / 1000.0 / 3600.0;
- _energy += _power * window;
- saveEnergy();
- sum = 0;
- measurements = 0;
-
- char power[6];
- snprintf(power, 6, "%d", _power);
- char energy[8];
- snprintf(energy, 8, "%ld", (unsigned long) _energy);
- mqttSend(getSetting("emonPowerTopic", EMON_POWER_TOPIC).c_str(), power);
- mqttSend(getSetting("emonEnergyTopic", EMON_ENERGY_TOPIC).c_str(), energy);
- #if ENABLE_DOMOTICZ
- {
- char buffer[20];
- snprintf(buffer, 20, "%s;%s", power, energy);
- domoticzSend("dczPowIdx", 0, buffer);
- }
- #endif
-
-
- }
-
- next_measurement += EMON_INTERVAL;
-
- }
-
- }
-
- #endif
|