@ -1,10 +1,9 @@
/*
/*
ESPurna
POW MODULE
POW MODULE
Support for Sonoff POW HLW8012 - based power monitor
Support for Sonoff POW HLW8012 - based power monitor
Copyright ( C ) 2016 by Xose Pérez < xose dot perez at gmail dot com >
Copyright ( C ) 2016 - 2017 by Xose Pérez < xose dot perez at gmail dot com >
*/
*/
@ -12,6 +11,8 @@ Copyright (C) 2016 by Xose Pérez <xose dot perez at gmail dot com>
# include <HLW8012.h>
# include <HLW8012.h>
# define POW_USE_INTERRUPTS 1
HLW8012 hlw8012 ;
HLW8012 hlw8012 ;
// -----------------------------------------------------------------------------
// -----------------------------------------------------------------------------
@ -29,17 +30,19 @@ void hlw8012_cf_interrupt() {
}
}
void powAttachInterrupts ( ) {
void powAttachInterrupts ( ) {
//attachInterrupt(POW_CF1_PIN, hlw8012_cf1_interrupt, CHANGE);
attachInterrupt ( POW_CF1_PIN , hlw8012_cf1_interrupt , CHANGE ) ;
attachInterrupt ( POW_CF_PIN , hlw8012_cf_interrupt , CHANGE ) ;
attachInterrupt ( POW_CF_PIN , hlw8012_cf_interrupt , CHANGE ) ;
DEBUG_MSG ( " [POW] Enabled \n " ) ;
DEBUG_MSG ( " [POW] Enabled \n " ) ;
}
}
void powDettachInterrupts ( ) {
void powDettachInterrupts ( ) {
//detachInterrupt(POW_CF1_PIN);
detachInterrupt ( POW_CF1_PIN ) ;
detachInterrupt ( POW_CF_PIN ) ;
detachInterrupt ( POW_CF_PIN ) ;
DEBUG_MSG ( " [POW] Disabled \n " ) ;
DEBUG_MSG ( " [POW] Disabled \n " ) ;
}
}
// -----------------------------------------------------------------------------
void powSaveCalibration ( ) {
void powSaveCalibration ( ) {
setSetting ( " powPowerMult " , hlw8012 . getPowerMultiplier ( ) ) ;
setSetting ( " powPowerMult " , hlw8012 . getPowerMultiplier ( ) ) ;
setSetting ( " powCurrentMult " , hlw8012 . getCurrentMultiplier ( ) ) ;
setSetting ( " powCurrentMult " , hlw8012 . getCurrentMultiplier ( ) ) ;
@ -77,6 +80,13 @@ void powSetExpectedVoltage(unsigned int voltage) {
}
}
}
}
void powReset ( ) {
hlw8012 . resetMultipliers ( ) ;
powSaveCalibration ( ) ;
}
// -----------------------------------------------------------------------------
unsigned int getActivePower ( ) {
unsigned int getActivePower ( ) {
return hlw8012 . getActivePower ( ) ;
return hlw8012 . getActivePower ( ) ;
}
}
@ -85,6 +95,10 @@ unsigned int getApparentPower() {
return hlw8012 . getApparentPower ( ) ;
return hlw8012 . getApparentPower ( ) ;
}
}
unsigned int getReactivePower ( ) {
return hlw8012 . getReactivePower ( ) ;
}
double getCurrent ( ) {
double getCurrent ( ) {
return hlw8012 . getCurrent ( ) ;
return hlw8012 . getCurrent ( ) ;
}
}
@ -97,6 +111,8 @@ unsigned int getPowerFactor() {
return ( int ) ( 100 * hlw8012 . getPowerFactor ( ) ) ;
return ( int ) ( 100 * hlw8012 . getPowerFactor ( ) ) ;
}
}
// -----------------------------------------------------------------------------
void powSetup ( ) {
void powSetup ( ) {
// Initialize HLW8012
// Initialize HLW8012
@ -105,7 +121,11 @@ void powSetup() {
// * currentWhen is the value in sel_pin to select current sampling
// * currentWhen is the value in sel_pin to select current sampling
// * set use_interrupts to true to use interrupts to monitor pulse widths
// * set use_interrupts to true to use interrupts to monitor pulse widths
// * leave pulse_timeout to the default value, recommended when using interrupts
// * leave pulse_timeout to the default value, recommended when using interrupts
hlw8012 . begin ( POW_CF_PIN , POW_CF1_PIN , POW_SEL_PIN , POW_SEL_CURRENT , false , 1000000 ) ;
# if POW_USE_INTERRUPTS
hlw8012 . begin ( POW_CF_PIN , POW_CF1_PIN , POW_SEL_PIN , POW_SEL_CURRENT , true ) ;
# else
hlw8012 . begin ( POW_CF_PIN , POW_CF1_PIN , POW_SEL_PIN , POW_SEL_CURRENT , false , 1000000 ) ;
# endif
// These values are used to calculate current, voltage and power factors as per datasheet formula
// These values are used to calculate current, voltage and power factors as per datasheet formula
// These are the nominal values for the Sonoff POW resistors:
// These are the nominal values for the Sonoff POW resistors:
@ -114,25 +134,13 @@ void powSetup() {
// * The VOLTAGE_RESISTOR_DOWNSTREAM is the 1kOhm resistor in the voltage divider that feeds the V2P pin in the HLW8012
// * The VOLTAGE_RESISTOR_DOWNSTREAM is the 1kOhm resistor in the voltage divider that feeds the V2P pin in the HLW8012
hlw8012 . setResistors ( POW_CURRENT_R , POW_VOLTAGE_R_UP , POW_VOLTAGE_R_DOWN ) ;
hlw8012 . setResistors ( POW_CURRENT_R , POW_VOLTAGE_R_UP , POW_VOLTAGE_R_DOWN ) ;
// Retrieve calibration values
powRetrieveCalibration ( ) ;
powRetrieveCalibration ( ) ;
/*
static WiFiEventHandler e1 = WiFi . onStationModeDisconnected ( [ ] ( const WiFiEventStationModeDisconnected & event ) {
powDettachInterrupts ( ) ;
} ) ;
static WiFiEventHandler e2 = WiFi . onSoftAPModeStationDisconnected ( [ ] ( const WiFiEventSoftAPModeStationDisconnected & event ) {
powDettachInterrupts ( ) ;
} ) ;
static WiFiEventHandler e3 = WiFi . onStationModeConnected ( [ ] ( const WiFiEventStationModeConnected & event ) {
powAttachInterrupts ( ) ;
} ) ;
static WiFiEventHandler e4 = WiFi . onSoftAPModeStationConnected ( [ ] ( const WiFiEventSoftAPModeStationConnected & event ) {
// Attach interrupts
# if POW_USE_INTERRUPTS
powAttachInterrupts ( ) ;
powAttachInterrupts ( ) ;
} ) ;
*/
# endif
}
}
@ -141,20 +149,67 @@ void powLoop() {
static unsigned long last_update = 0 ;
static unsigned long last_update = 0 ;
static unsigned char report_count = POW_REPORT_EVERY ;
static unsigned char report_count = POW_REPORT_EVERY ;
static unsigned long power_sum = 0 ;
static double current_sum = 0 ;
static unsigned long voltage_sum = 0 ;
if ( ( millis ( ) - last_update > POW_UPDATE_INTERVAL ) | | ( last_update = = 0 ) ) {
if ( ( millis ( ) - last_update > POW_UPDATE_INTERVAL ) | | ( last_update = = 0 ) ) {
last_update = millis ( ) ;
last_update = millis ( ) ;
unsigned int power = getActivePower ( ) ;
unsigned int power = getActivePower ( ) ;
char buffer [ 100 ] ;
sprintf_P ( buffer , PSTR ( " { \" powVisible \" : 1, \" powActivePower \" : %d} " ) , power ) ;
wsSend ( buffer ) ;
unsigned int voltage = getVoltage ( ) ;
double current = getCurrent ( ) ;
unsigned int apparent = getApparentPower ( ) ;
unsigned int factor = getPowerFactor ( ) ;
unsigned int reactive = getReactivePower ( ) ;
power_sum + = power ;
current_sum + = current ;
voltage_sum + = voltage ;
DynamicJsonBuffer jsonBuffer ;
JsonObject & root = jsonBuffer . createObject ( ) ;
root [ " powVisible " ] = 1 ;
root [ " powActivePower " ] = power ;
root [ " powCurrent " ] = current ;
root [ " powVoltage " ] = voltage ;
root [ " powApparentPower " ] = apparent ;
root [ " powReactivePower " ] = reactive ;
root [ " powPowerFactor " ] = factor ;
String output ;
root . printTo ( output ) ;
wsSend ( output . c_str ( ) ) ;
if ( - - report_count = = 0 ) {
if ( - - report_count = = 0 ) {
power = power_sum / POW_REPORT_EVERY ;
current = current_sum / POW_REPORT_EVERY ;
voltage = voltage_sum / POW_REPORT_EVERY ;
apparent = current * voltage ;
reactive = ( apparent > power ) ? sqrt ( apparent * apparent - power * power ) : 0 ;
factor = ( apparent > 0 ) ? 100 * power / apparent : 100 ;
if ( factor > 100 ) factor = 100 ;
mqttSend ( getSetting ( " powPowerTopic " , POW_POWER_TOPIC ) . c_str ( ) , String ( power ) . c_str ( ) ) ;
mqttSend ( getSetting ( " powPowerTopic " , POW_POWER_TOPIC ) . c_str ( ) , String ( power ) . c_str ( ) ) ;
mqttSend ( getSetting ( " powCurrentTopic " , POW_CURRENT_TOPIC ) . c_str ( ) , String ( current ) . c_str ( ) ) ;
mqttSend ( getSetting ( " powVoltageTopic " , POW_VOLTAGE_TOPIC ) . c_str ( ) , String ( voltage ) . c_str ( ) ) ;
mqttSend ( getSetting ( " powAPowerTopic " , POW_APOWER_TOPIC ) . c_str ( ) , String ( apparent ) . c_str ( ) ) ;
mqttSend ( getSetting ( " powRPowerTopic " , POW_RPOWER_TOPIC ) . c_str ( ) , String ( reactive ) . c_str ( ) ) ;
mqttSend ( getSetting ( " powPFactorTopic " , POW_PFACTOR_TOPIC ) . c_str ( ) , String ( factor ) . c_str ( ) ) ;
power_sum = current_sum = voltage_sum = 0 ;
report_count = POW_REPORT_EVERY ;
report_count = POW_REPORT_EVERY ;
}
}
// Toggle between current and voltage monitoring
# if POW_USE_INTERRUPTS == 0
hlw8012 . toggleMode ( ) ;
# endif
}
}
}
}