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.
 
 
 
 
 
 

184 lines
4.8 KiB

/*
POWER EMON MODULE
Copyright (C) 2016-2017 by Xose Pérez <xose dot perez at gmail dot com>
*/
#if (POWER_PROVIDER == POWER_PROVIDER_EMON_ANALOG) || (POWER_PROVIDER == POWER_PROVIDER_EMON_ADC121)
// -----------------------------------------------------------------------------
// MODULE GLOBALS AND CACHE
// -----------------------------------------------------------------------------
#include <EmonLiteESP.h>
EmonLiteESP _emon;
#if POWER_PROVIDER == POWER_PROVIDER_EMON_ADC121
#if I2C_USE_BRZO
#include "brzo_i2c.h"
#else
#include "Wire.h"
#endif
// 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
#endif // POWER_PROVIDER == POWER_PROVIDER_EMON_ADC121
// -----------------------------------------------------------------------------
// HAL
// -----------------------------------------------------------------------------
unsigned int currentCallback() {
#if POWER_PROVIDER == POWER_PROVIDER_EMON_ANALOG
return analogRead(A0);
#endif // POWER_PROVIDER == POWER_PROVIDER_EMON_ANALOG
#if POWER_PROVIDER == POWER_PROVIDER_EMON_ADC121
unsigned int value;
#if I2C_USE_BRZO
uint8_t buffer[2];
brzo_i2c_start_transaction(ADC121_I2C_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();
value = (buffer[0] & 0x0F) << 8;
value |= buffer[1];
#else
Wire.beginTransmission(ADC121_I2C_ADDRESS);
Wire.write(ADC121_REG_RESULT);
Wire.endTransmission();
Wire.requestFrom(ADC121_I2C_ADDRESS, 2);
value = (Wire.read() & 0x0F) << 8;
value = value + Wire.read();
#endif
return value;
#endif // POWER_PROVIDER == POWER_PROVIDER_EMON_ADC121
}
// -----------------------------------------------------------------------------
// POWER API
// -----------------------------------------------------------------------------
double _powerCurrent() {
static unsigned long last = 0;
static double current = 0;
if (millis() - last > 1000) {
last = millis();
current = _emon.getCurrent(EMON_SAMPLES);
current -= EMON_CURRENT_OFFSET;
if (current < 0) current = 0;
}
return current;
}
double _powerVoltage() {
return _power_voltage;
}
double _powerActivePower() {
return 0;
}
double _powerApparentPower() {
return _powerCurrent() * _powerVoltage();
}
double _powerReactivePower() {
return 0;
}
double _powerPowerFactor() {
return 1;
}
void _powerEnabledProvider() {
// Nothing to do
}
void _powerCalibrateProvider(unsigned char magnitude, double value) {
if (value <= 0) return;
if (magnitude == POWER_MAGNITUDE_ACTIVE) {
double power = _powerApparentPower();
double ratio = getSetting("pwrRatioC", EMON_CURRENT_RATIO).toFloat();
ratio = ratio * (value / power);
_emon.setCurrentRatio(ratio);
setSetting("pwrRatioC", ratio);
saveSettings();
}
if (magnitude == POWER_MAGNITUDE_VOLTAGE) {
_power_voltage = value;
setSetting("pwrVoltage", value);
saveSettings();
}
}
void _powerResetCalibrationProvider() {
delSetting("pwrRatioC");
_powerConfigureProvider();
saveSettings();
}
void _powerConfigureProvider() {
_emon.setCurrentRatio(getSetting("pwrRatioC", EMON_CURRENT_RATIO).toFloat());
_power_voltage = getSetting("pwrVoltage", POWER_VOLTAGE).toFloat();
}
void _powerSetupProvider() {
_emon.initCurrent(currentCallback, EMON_ADC_BITS, EMON_REFERENCE_VOLTAGE, EMON_CURRENT_RATIO);
#if POWER_PROVIDER == POWER_PROVIDER_EMON_ADC121
#if I2C_USE_BRZO
uint8_t buffer[2];
buffer[0] = ADC121_REG_CONFIG;
buffer[1] = 0x00;
brzo_i2c_start_transaction(ADC121_I2C_ADDRESS, I2C_SCL_FREQUENCY);
brzo_i2c_write(buffer, 2, false);
brzo_i2c_end_transaction();
#else
Wire.beginTransmission(ADC121_I2C_ADDRESS);
Wire.write(ADC121_REG_CONFIG);
Wire.write(0x00);
Wire.endTransmission();
#endif
#endif
_emon.warmup();
}
void _powerLoopProvider(bool before) {
if (before) {
static unsigned long last = 0;
if (millis() - last > powerReadInterval()) {
last = millis();
_power_newdata = true;
}
}
}
#endif // (POWER_PROVIDER == POWER_PROVIDER_EMON_ANALOG) || (POWER_PROVIDER == POWER_PROVIDER_EMON_ADC121)