Add frequency to CSE7761 driver

This commit is contained in:
Theo Arends 2021-03-21 17:51:57 +01:00
parent 9efeceafd9
commit 6c66b2d11f
2 changed files with 105 additions and 93 deletions

View File

@ -36,15 +36,16 @@
#define D_CMND_POWERCAL "PowerCal" #define D_CMND_POWERCAL "PowerCal"
#define D_CMND_VOLTAGECAL "VoltageCal" #define D_CMND_VOLTAGECAL "VoltageCal"
#define D_CMND_CURRENTCAL "CurrentCal" #define D_CMND_CURRENTCAL "CurrentCal"
#define D_CMND_FREQUENCYCAL "FrequencyCal"
#define D_CMND_TARIFF "Tariff" #define D_CMND_TARIFF "Tariff"
#define D_CMND_MODULEADDRESS "ModuleAddress" #define D_CMND_MODULEADDRESS "ModuleAddress"
enum EnergyCommands { enum EnergyCommands {
CMND_POWERCAL, CMND_VOLTAGECAL, CMND_CURRENTCAL, CMND_POWERCAL, CMND_VOLTAGECAL, CMND_CURRENTCAL, CMND_FREQUENCYCAL,
CMND_POWERSET, CMND_VOLTAGESET, CMND_CURRENTSET, CMND_FREQUENCYSET, CMND_MODULEADDRESS }; CMND_POWERSET, CMND_VOLTAGESET, CMND_CURRENTSET, CMND_FREQUENCYSET, CMND_MODULEADDRESS };
const char kEnergyCommands[] PROGMEM = "|" // No prefix const char kEnergyCommands[] PROGMEM = "|" // No prefix
D_CMND_POWERCAL "|" D_CMND_VOLTAGECAL "|" D_CMND_CURRENTCAL "|" D_CMND_POWERCAL "|" D_CMND_VOLTAGECAL "|" D_CMND_CURRENTCAL "|" D_CMND_FREQUENCYCAL "|"
D_CMND_POWERSET "|" D_CMND_VOLTAGESET "|" D_CMND_CURRENTSET "|" D_CMND_FREQUENCYSET "|" D_CMND_MODULEADDRESS "|" D_CMND_POWERSET "|" D_CMND_VOLTAGESET "|" D_CMND_CURRENTSET "|" D_CMND_FREQUENCYSET "|" D_CMND_MODULEADDRESS "|"
#ifdef USE_ENERGY_MARGIN_DETECTION #ifdef USE_ENERGY_MARGIN_DETECTION
D_CMND_POWERDELTA "|" D_CMND_POWERLOW "|" D_CMND_POWERHIGH "|" D_CMND_VOLTAGELOW "|" D_CMND_VOLTAGEHIGH "|" D_CMND_CURRENTLOW "|" D_CMND_CURRENTHIGH "|" D_CMND_POWERDELTA "|" D_CMND_POWERLOW "|" D_CMND_POWERHIGH "|" D_CMND_VOLTAGELOW "|" D_CMND_VOLTAGEHIGH "|" D_CMND_CURRENTLOW "|" D_CMND_CURRENTHIGH "|"
@ -57,7 +58,7 @@ const char kEnergyCommands[] PROGMEM = "|" // No prefix
D_CMND_ENERGYRESET "|" D_CMND_TARIFF ; D_CMND_ENERGYRESET "|" D_CMND_TARIFF ;
void (* const EnergyCommand[])(void) PROGMEM = { void (* const EnergyCommand[])(void) PROGMEM = {
&CmndPowerCal, &CmndVoltageCal, &CmndCurrentCal, &CmndPowerCal, &CmndVoltageCal, &CmndCurrentCal, &CmndFrequencyCal,
&CmndPowerSet, &CmndVoltageSet, &CmndCurrentSet, &CmndFrequencySet, &CmndModuleAddress, &CmndPowerSet, &CmndVoltageSet, &CmndCurrentSet, &CmndFrequencySet, &CmndModuleAddress,
#ifdef USE_ENERGY_MARGIN_DETECTION #ifdef USE_ENERGY_MARGIN_DETECTION
&CmndPowerDelta, &CmndPowerLow, &CmndPowerHigh, &CmndVoltageLow, &CmndVoltageHigh, &CmndCurrentLow, &CmndCurrentHigh, &CmndPowerDelta, &CmndPowerLow, &CmndPowerHigh, &CmndVoltageLow, &CmndVoltageHigh, &CmndCurrentLow, &CmndCurrentHigh,
@ -547,14 +548,12 @@ void EnergyEverySecond(void)
* Commands * Commands
\*********************************************************************************************/ \*********************************************************************************************/
void EnergyCommandCalResponse(uint32_t nvalue) void EnergyCommandCalResponse(uint32_t nvalue) {
{
snprintf_P(XdrvMailbox.command, CMDSZ, PSTR("%sCal"), XdrvMailbox.command); snprintf_P(XdrvMailbox.command, CMDSZ, PSTR("%sCal"), XdrvMailbox.command);
ResponseCmndNumber(nvalue); ResponseCmndNumber(nvalue);
} }
void CmndEnergyReset(void) void CmndEnergyReset(void) {
{
uint32_t values[2] = { 0 }; uint32_t values[2] = { 0 };
uint32_t params = ParseParameters(2, values); uint32_t params = ParseParameters(2, values);
values[0] *= 100; values[0] *= 100;
@ -641,8 +640,7 @@ void CmndEnergyReset(void)
Settings.flag2.energy_resolution, &return2_kWhtotal); Settings.flag2.energy_resolution, &return2_kWhtotal);
} }
void CmndTariff(void) void CmndTariff(void) {
{
// Tariff1 22:00,23:00 - Tariff1 start hour for Standard Time and Daylight Savings Time // Tariff1 22:00,23:00 - Tariff1 start hour for Standard Time and Daylight Savings Time
// Tariff2 6:00,7:00 - Tariff2 start hour for Standard Time and Daylight Savings Time // Tariff2 6:00,7:00 - Tariff2 start hour for Standard Time and Daylight Savings Time
// Tariffx 1320, 1380 = minutes and also 22:00, 23:00 // Tariffx 1320, 1380 = minutes and also 22:00, 23:00
@ -686,11 +684,9 @@ void CmndTariff(void)
GetStateText(Settings.flag3.energy_weekend)); // CMND_TARIFF GetStateText(Settings.flag3.energy_weekend)); // CMND_TARIFF
} }
void CmndPowerCal(void) void CmndPowerCal(void) {
{
Energy.command_code = CMND_POWERCAL; Energy.command_code = CMND_POWERCAL;
if (XnrgCall(FUNC_COMMAND)) { // microseconds if (XnrgCall(FUNC_COMMAND)) { // microseconds
// if ((XdrvMailbox.payload > 999) && (XdrvMailbox.payload < 32001)) {
if (XdrvMailbox.payload > 999) { if (XdrvMailbox.payload > 999) {
Settings.energy_power_calibration = XdrvMailbox.payload; Settings.energy_power_calibration = XdrvMailbox.payload;
} }
@ -698,11 +694,9 @@ void CmndPowerCal(void)
} }
} }
void CmndVoltageCal(void) void CmndVoltageCal(void) {
{
Energy.command_code = CMND_VOLTAGECAL; Energy.command_code = CMND_VOLTAGECAL;
if (XnrgCall(FUNC_COMMAND)) { // microseconds if (XnrgCall(FUNC_COMMAND)) { // microseconds
// if ((XdrvMailbox.payload > 999) && (XdrvMailbox.payload < 32001)) {
if (XdrvMailbox.payload > 999) { if (XdrvMailbox.payload > 999) {
Settings.energy_voltage_calibration = XdrvMailbox.payload; Settings.energy_voltage_calibration = XdrvMailbox.payload;
} }
@ -710,11 +704,9 @@ void CmndVoltageCal(void)
} }
} }
void CmndCurrentCal(void) void CmndCurrentCal(void) {
{
Energy.command_code = CMND_CURRENTCAL; Energy.command_code = CMND_CURRENTCAL;
if (XnrgCall(FUNC_COMMAND)) { // microseconds if (XnrgCall(FUNC_COMMAND)) { // microseconds
// if ((XdrvMailbox.payload > 999) && (XdrvMailbox.payload < 32001)) {
if (XdrvMailbox.payload > 999) { if (XdrvMailbox.payload > 999) {
Settings.energy_current_calibration = XdrvMailbox.payload; Settings.energy_current_calibration = XdrvMailbox.payload;
} }
@ -722,40 +714,45 @@ void CmndCurrentCal(void)
} }
} }
void CmndPowerSet(void) void CmndFrequencyCal(void) {
{ Energy.command_code = CMND_FREQUENCYCAL;
if (XnrgCall(FUNC_COMMAND)) { // microseconds
if (XdrvMailbox.payload > 999) {
Settings.energy_frequency_calibration = XdrvMailbox.payload;
}
ResponseCmndNumber(Settings.energy_frequency_calibration);
}
}
void CmndPowerSet(void) {
Energy.command_code = CMND_POWERSET; Energy.command_code = CMND_POWERSET;
if (XnrgCall(FUNC_COMMAND)) { // Watt if (XnrgCall(FUNC_COMMAND)) { // Watt
EnergyCommandCalResponse(Settings.energy_power_calibration); EnergyCommandCalResponse(Settings.energy_power_calibration);
} }
} }
void CmndVoltageSet(void) void CmndVoltageSet(void) {
{
Energy.command_code = CMND_VOLTAGESET; Energy.command_code = CMND_VOLTAGESET;
if (XnrgCall(FUNC_COMMAND)) { // Volt if (XnrgCall(FUNC_COMMAND)) { // Volt
EnergyCommandCalResponse(Settings.energy_voltage_calibration); EnergyCommandCalResponse(Settings.energy_voltage_calibration);
} }
} }
void CmndCurrentSet(void) void CmndCurrentSet(void) {
{
Energy.command_code = CMND_CURRENTSET; Energy.command_code = CMND_CURRENTSET;
if (XnrgCall(FUNC_COMMAND)) { // milliAmpere if (XnrgCall(FUNC_COMMAND)) { // milliAmpere
EnergyCommandCalResponse(Settings.energy_current_calibration); EnergyCommandCalResponse(Settings.energy_current_calibration);
} }
} }
void CmndFrequencySet(void) void CmndFrequencySet(void) {
{
Energy.command_code = CMND_FREQUENCYSET; Energy.command_code = CMND_FREQUENCYSET;
if (XnrgCall(FUNC_COMMAND)) { // Hz if (XnrgCall(FUNC_COMMAND)) { // Hz
EnergyCommandCalResponse(Settings.energy_frequency_calibration); EnergyCommandCalResponse(Settings.energy_frequency_calibration);
} }
} }
void CmndModuleAddress(void) void CmndModuleAddress(void) {
{
if ((XdrvMailbox.payload > 0) && (XdrvMailbox.payload < 4) && (1 == Energy.phase_count)) { if ((XdrvMailbox.payload > 0) && (XdrvMailbox.payload < 4) && (1 == Energy.phase_count)) {
Energy.command_code = CMND_MODULEADDRESS; Energy.command_code = CMND_MODULEADDRESS;
if (XnrgCall(FUNC_COMMAND)) { // Module address if (XnrgCall(FUNC_COMMAND)) { // Module address
@ -765,8 +762,7 @@ void CmndModuleAddress(void)
} }
#ifdef USE_ENERGY_MARGIN_DETECTION #ifdef USE_ENERGY_MARGIN_DETECTION
void CmndPowerDelta(void) void CmndPowerDelta(void) {
{
if ((XdrvMailbox.index > 0) && (XdrvMailbox.index <= 3)) { if ((XdrvMailbox.index > 0) && (XdrvMailbox.index <= 3)) {
if ((XdrvMailbox.payload >= 0) && (XdrvMailbox.payload < 32000)) { if ((XdrvMailbox.payload >= 0) && (XdrvMailbox.payload < 32000)) {
Settings.energy_power_delta[XdrvMailbox.index -1] = XdrvMailbox.payload; Settings.energy_power_delta[XdrvMailbox.index -1] = XdrvMailbox.payload;
@ -775,48 +771,42 @@ void CmndPowerDelta(void)
} }
} }
void CmndPowerLow(void) void CmndPowerLow(void) {
{
if ((XdrvMailbox.payload >= 0) && (XdrvMailbox.payload < 3601)) { if ((XdrvMailbox.payload >= 0) && (XdrvMailbox.payload < 3601)) {
Settings.energy_min_power = XdrvMailbox.payload; Settings.energy_min_power = XdrvMailbox.payload;
} }
ResponseCmndNumber(Settings.energy_min_power); ResponseCmndNumber(Settings.energy_min_power);
} }
void CmndPowerHigh(void) void CmndPowerHigh(void) {
{
if ((XdrvMailbox.payload >= 0) && (XdrvMailbox.payload < 3601)) { if ((XdrvMailbox.payload >= 0) && (XdrvMailbox.payload < 3601)) {
Settings.energy_max_power = XdrvMailbox.payload; Settings.energy_max_power = XdrvMailbox.payload;
} }
ResponseCmndNumber(Settings.energy_max_power); ResponseCmndNumber(Settings.energy_max_power);
} }
void CmndVoltageLow(void) void CmndVoltageLow(void) {
{
if ((XdrvMailbox.payload >= 0) && (XdrvMailbox.payload < 501)) { if ((XdrvMailbox.payload >= 0) && (XdrvMailbox.payload < 501)) {
Settings.energy_min_voltage = XdrvMailbox.payload; Settings.energy_min_voltage = XdrvMailbox.payload;
} }
ResponseCmndNumber(Settings.energy_min_voltage); ResponseCmndNumber(Settings.energy_min_voltage);
} }
void CmndVoltageHigh(void) void CmndVoltageHigh(void) {
{
if ((XdrvMailbox.payload >= 0) && (XdrvMailbox.payload < 501)) { if ((XdrvMailbox.payload >= 0) && (XdrvMailbox.payload < 501)) {
Settings.energy_max_voltage = XdrvMailbox.payload; Settings.energy_max_voltage = XdrvMailbox.payload;
} }
ResponseCmndNumber(Settings.energy_max_voltage); ResponseCmndNumber(Settings.energy_max_voltage);
} }
void CmndCurrentLow(void) void CmndCurrentLow(void) {
{
if ((XdrvMailbox.payload >= 0) && (XdrvMailbox.payload < 16001)) { if ((XdrvMailbox.payload >= 0) && (XdrvMailbox.payload < 16001)) {
Settings.energy_min_current = XdrvMailbox.payload; Settings.energy_min_current = XdrvMailbox.payload;
} }
ResponseCmndNumber(Settings.energy_min_current); ResponseCmndNumber(Settings.energy_min_current);
} }
void CmndCurrentHigh(void) void CmndCurrentHigh(void) {
{
if ((XdrvMailbox.payload >= 0) && (XdrvMailbox.payload < 16001)) { if ((XdrvMailbox.payload >= 0) && (XdrvMailbox.payload < 16001)) {
Settings.energy_max_current = XdrvMailbox.payload; Settings.energy_max_current = XdrvMailbox.payload;
} }
@ -824,56 +814,49 @@ void CmndCurrentHigh(void)
} }
#ifdef USE_ENERGY_POWER_LIMIT #ifdef USE_ENERGY_POWER_LIMIT
void CmndMaxPower(void) void CmndMaxPower(void) {
{
if ((XdrvMailbox.payload >= 0) && (XdrvMailbox.payload < 3601)) { if ((XdrvMailbox.payload >= 0) && (XdrvMailbox.payload < 3601)) {
Settings.energy_max_power_limit = XdrvMailbox.payload; Settings.energy_max_power_limit = XdrvMailbox.payload;
} }
ResponseCmndNumber(Settings.energy_max_power_limit); ResponseCmndNumber(Settings.energy_max_power_limit);
} }
void CmndMaxPowerHold(void) void CmndMaxPowerHold(void) {
{
if ((XdrvMailbox.payload >= 0) && (XdrvMailbox.payload < 3601)) { if ((XdrvMailbox.payload >= 0) && (XdrvMailbox.payload < 3601)) {
Settings.energy_max_power_limit_hold = (1 == XdrvMailbox.payload) ? MAX_POWER_HOLD : XdrvMailbox.payload; Settings.energy_max_power_limit_hold = (1 == XdrvMailbox.payload) ? MAX_POWER_HOLD : XdrvMailbox.payload;
} }
ResponseCmndNumber(Settings.energy_max_power_limit_hold); ResponseCmndNumber(Settings.energy_max_power_limit_hold);
} }
void CmndMaxPowerWindow(void) void CmndMaxPowerWindow(void) {
{
if ((XdrvMailbox.payload >= 0) && (XdrvMailbox.payload < 3601)) { if ((XdrvMailbox.payload >= 0) && (XdrvMailbox.payload < 3601)) {
Settings.energy_max_power_limit_window = (1 == XdrvMailbox.payload) ? MAX_POWER_WINDOW : XdrvMailbox.payload; Settings.energy_max_power_limit_window = (1 == XdrvMailbox.payload) ? MAX_POWER_WINDOW : XdrvMailbox.payload;
} }
ResponseCmndNumber(Settings.energy_max_power_limit_window); ResponseCmndNumber(Settings.energy_max_power_limit_window);
} }
void CmndSafePower(void) void CmndSafePower(void) {
{
if ((XdrvMailbox.payload >= 0) && (XdrvMailbox.payload < 3601)) { if ((XdrvMailbox.payload >= 0) && (XdrvMailbox.payload < 3601)) {
Settings.energy_max_power_safe_limit = XdrvMailbox.payload; Settings.energy_max_power_safe_limit = XdrvMailbox.payload;
} }
ResponseCmndNumber(Settings.energy_max_power_safe_limit); ResponseCmndNumber(Settings.energy_max_power_safe_limit);
} }
void CmndSafePowerHold(void) void CmndSafePowerHold(void) {
{
if ((XdrvMailbox.payload >= 0) && (XdrvMailbox.payload < 3601)) { if ((XdrvMailbox.payload >= 0) && (XdrvMailbox.payload < 3601)) {
Settings.energy_max_power_safe_limit_hold = (1 == XdrvMailbox.payload) ? SAFE_POWER_HOLD : XdrvMailbox.payload; Settings.energy_max_power_safe_limit_hold = (1 == XdrvMailbox.payload) ? SAFE_POWER_HOLD : XdrvMailbox.payload;
} }
ResponseCmndNumber(Settings.energy_max_power_safe_limit_hold); ResponseCmndNumber(Settings.energy_max_power_safe_limit_hold);
} }
void CmndSafePowerWindow(void) void CmndSafePowerWindow(void) {
{
if ((XdrvMailbox.payload >= 0) && (XdrvMailbox.payload < 1440)) { if ((XdrvMailbox.payload >= 0) && (XdrvMailbox.payload < 1440)) {
Settings.energy_max_power_safe_limit_window = (1 == XdrvMailbox.payload) ? SAFE_POWER_WINDOW : XdrvMailbox.payload; Settings.energy_max_power_safe_limit_window = (1 == XdrvMailbox.payload) ? SAFE_POWER_WINDOW : XdrvMailbox.payload;
} }
ResponseCmndNumber(Settings.energy_max_power_safe_limit_window); ResponseCmndNumber(Settings.energy_max_power_safe_limit_window);
} }
void CmndMaxEnergy(void) void CmndMaxEnergy(void) {
{
if ((XdrvMailbox.payload >= 0) && (XdrvMailbox.payload < 3601)) { if ((XdrvMailbox.payload >= 0) && (XdrvMailbox.payload < 3601)) {
Settings.energy_max_energy = XdrvMailbox.payload; Settings.energy_max_energy = XdrvMailbox.payload;
Energy.max_energy_state = 3; Energy.max_energy_state = 3;
@ -881,8 +864,7 @@ void CmndMaxEnergy(void)
ResponseCmndNumber(Settings.energy_max_energy); ResponseCmndNumber(Settings.energy_max_energy);
} }
void CmndMaxEnergyStart(void) void CmndMaxEnergyStart(void) {
{
if ((XdrvMailbox.payload >= 0) && (XdrvMailbox.payload < 24)) { if ((XdrvMailbox.payload >= 0) && (XdrvMailbox.payload < 24)) {
Settings.energy_max_energy_start = XdrvMailbox.payload; Settings.energy_max_energy_start = XdrvMailbox.payload;
} }

View File

@ -34,29 +34,31 @@
#define CSE7761_UREF 42563 // RmsUc #define CSE7761_UREF 42563 // RmsUc
#define CSE7761_IREF 52241 // RmsIAC #define CSE7761_IREF 52241 // RmsIAC
#define CSE7761_PREF 44513 // PowerPAC #define CSE7761_PREF 44513 // PowerPAC
#define CSE7761_FREF 3579545 // System clock (3.579545MHz) as used in frequency calculation
#define CSE7761_REG_SYSCON 0x00 // System Control Register #define CSE7761_REG_SYSCON 0x00 // (2) System Control Register (0x0A04)
#define CSE7761_REG_EMUCON 0x01 // Metering control register #define CSE7761_REG_EMUCON 0x01 // (2) Metering control register (0x0000)
#define CSE7761_REG_EMUCON2 0x13 // Metering control register 2 #define CSE7761_REG_EMUCON2 0x13 // (2) Metering control register 2 (0x0001)
#define CSE7761_REG_UFREQ 0x23 // Voltage Frequency Register #define CSE7761_REG_UFREQ 0x23 // (2) Voltage Frequency (0x0000)
#define CSE7761_REG_RMSIA 0x24 // The effective value of channel A current #define CSE7761_REG_RMSIA 0x24 // (3) The effective value of channel A current (0x000000)
#define CSE7761_REG_RMSIB 0x25 // The effective value of channel B current #define CSE7761_REG_RMSIB 0x25 // (3) The effective value of channel B current (0x000000)
#define CSE7761_REG_RMSU 0x26 // Voltage RMS #define CSE7761_REG_RMSU 0x26 // (3) Voltage RMS (0x000000)
#define CSE7761_REG_POWERPA 0x2C // Channel A active power, update rate 27.2Hz #define CSE7761_REG_POWERFACTOR 0x27 // (3) Power factor register, select by command: channel A Power factor or channel B power factor (0x7FFFFF)
#define CSE7761_REG_POWERPB 0x2D // Channel B active power, update rate 27.2Hz #define CSE7761_REG_POWERPA 0x2C // (4) Channel A active power, update rate 27.2Hz (0x00000000)
#define CSE7761_REG_SYSSTATUS 0x43 // System status register #define CSE7761_REG_POWERPB 0x2D // (4) Channel B active power, update rate 27.2Hz (0x00000000)
#define CSE7761_REG_SYSSTATUS 0x43 // (1) System status register
#define CSE7761_REG_COEFFOFFSET 0x6E // Coefficient checksum offset (0xFFFF) #define CSE7761_REG_COEFFOFFSET 0x6E // (2) Coefficient checksum offset (0xFFFF)
#define CSE7761_REG_COEFFCHKSUM 0x6F // Coefficient checksum #define CSE7761_REG_COEFFCHKSUM 0x6F // (2) Coefficient checksum
#define CSE7761_REG_RMSIAC 0x70 // Channel A effective current conversion coefficient #define CSE7761_REG_RMSIAC 0x70 // (2) Channel A effective current conversion coefficient
#define CSE7761_REG_RMSIBC 0x71 // Channel B effective current conversion coefficient #define CSE7761_REG_RMSIBC 0x71 // (2) Channel B effective current conversion coefficient
#define CSE7761_REG_RMSUC 0x72 // Effective voltage conversion coefficient #define CSE7761_REG_RMSUC 0x72 // (2) Effective voltage conversion coefficient
#define CSE7761_REG_POWERPAC 0x73 // Channel A active power conversion coefficient #define CSE7761_REG_POWERPAC 0x73 // (2) Channel A active power conversion coefficient
#define CSE7761_REG_POWERPBC 0x74 // Channel B active power conversion coefficient #define CSE7761_REG_POWERPBC 0x74 // (2) Channel B active power conversion coefficient
#define CSE7761_REG_POWERSC 0x75 // Apparent power conversion coefficient #define CSE7761_REG_POWERSC 0x75 // (2) Apparent power conversion coefficient
#define CSE7761_REG_ENERGYAC 0x76 // Channel A energy conversion coefficient #define CSE7761_REG_ENERGYAC 0x76 // (2) Channel A energy conversion coefficient
#define CSE7761_REG_ENERGYBC 0x77 // Channel B energy conversion coefficient #define CSE7761_REG_ENERGYBC 0x77 // (2) Channel B energy conversion coefficient
#define CSE7761_SPECIAL_COMMAND 0xEA // Start special command #define CSE7761_SPECIAL_COMMAND 0xEA // Start special command
#define CSE7761_CMD_RESET 0x96 // Reset command, after receiving the command, the chip resets #define CSE7761_CMD_RESET 0x96 // Reset command, after receiving the command, the chip resets
@ -76,6 +78,7 @@ enum CSE7761 { RmsIAC, RmsIBC, RmsUC, PowerPAC, PowerPBC, PowerSC, EnergyAC, Ene
TasmotaSerial *Cse7761Serial = nullptr; TasmotaSerial *Cse7761Serial = nullptr;
struct { struct {
uint32_t frequency = 0;
uint32_t voltage_rms = 0; uint32_t voltage_rms = 0;
uint32_t current_rms[2] = { 0 }; uint32_t current_rms[2] = { 0 };
uint32_t energy[2] = { 0 }; uint32_t energy[2] = { 0 };
@ -114,7 +117,7 @@ void Cse7761Write(uint32_t reg, uint32_t data) {
AddLog(LOG_LEVEL_DEBUG_MORE, PSTR("C61: Tx %*_H"), len, buffer); AddLog(LOG_LEVEL_DEBUG_MORE, PSTR("C61: Tx %*_H"), len, buffer);
} }
uint32_t Cse7761ReadOnce(uint32_t log_level, uint32_t reg, uint32_t size) { bool Cse7761ReadOnce(uint32_t log_level, uint32_t reg, uint32_t size, uint32_t* value) {
while (Cse7761Serial->available()) { Cse7761Serial->read(); } while (Cse7761Serial->available()) { Cse7761Serial->read(); }
Cse7761Write(reg, 0); Cse7761Write(reg, 0);
@ -133,12 +136,12 @@ uint32_t Cse7761ReadOnce(uint32_t log_level, uint32_t reg, uint32_t size) {
if (!rcvd) { if (!rcvd) {
AddLog(LOG_LEVEL_DEBUG_MORE, PSTR("C61: Rx none")); AddLog(LOG_LEVEL_DEBUG_MORE, PSTR("C61: Rx none"));
return 0; return false;
} }
AddLog(LOG_LEVEL_DEBUG_MORE, PSTR("C61: Rx %*_H"), rcvd, buffer); AddLog(LOG_LEVEL_DEBUG_MORE, PSTR("C61: Rx %*_H"), rcvd, buffer);
if (rcvd > 5) { if (rcvd > 5) {
AddLog(LOG_LEVEL_DEBUG_MORE, PSTR("C61: Rx overflow")); AddLog(LOG_LEVEL_DEBUG_MORE, PSTR("C61: Rx overflow"));
return 0; return false;
} }
rcvd--; rcvd--;
@ -151,25 +154,27 @@ uint32_t Cse7761ReadOnce(uint32_t log_level, uint32_t reg, uint32_t size) {
crc = ~crc; crc = ~crc;
if (crc != buffer[rcvd]) { if (crc != buffer[rcvd]) {
AddLog(log_level, PSTR("C61: Rx %*_H, CRC error %02X"), rcvd +1, buffer, crc); AddLog(log_level, PSTR("C61: Rx %*_H, CRC error %02X"), rcvd +1, buffer, crc);
return 1; return false;
} }
return result; *value = result;
return true;
} }
uint32_t Cse7761Read(uint32_t reg, uint32_t size) { uint32_t Cse7761Read(uint32_t reg, uint32_t size) {
uint32_t value = 0; bool result = false; // Start loop
uint32_t retry = 3; uint32_t retry = 3; // Retry up to three times
while ((value < 2) && (retry)) { uint32_t value = 0; // Default no value
while (!result && retry) {
retry--; retry--;
value = Cse7761ReadOnce((retry) ? LOG_LEVEL_DEBUG_MORE : LOG_LEVEL_DEBUG, reg, size); result = Cse7761ReadOnce((retry) ? LOG_LEVEL_DEBUG_MORE : LOG_LEVEL_DEBUG, reg, size, &value);
} }
return value; return value;
} }
uint32_t Cse7761ReadFallback(uint32_t reg, uint32_t prev, uint32_t size) { uint32_t Cse7761ReadFallback(uint32_t reg, uint32_t prev, uint32_t size) {
uint32_t value = Cse7761Read(reg, size); uint32_t value = Cse7761Read(reg, size);
if (1 == value) { // CRC Error so use previous value read if (!value) { // Error so use previous value read
value = prev; value = prev;
} }
return value; return value;
@ -202,10 +207,15 @@ bool Cse7761ChipInit(void) {
// CSE7761Data.coefficient[PowerPBC] = 0xADD7; // CSE7761Data.coefficient[PowerPBC] = 0xADD7;
} }
if (HLW_PREF_PULSE == Settings.energy_power_calibration) { if (HLW_PREF_PULSE == Settings.energy_power_calibration) {
Settings.energy_frequency_calibration = CSE7761_FREF;
Settings.energy_voltage_calibration = Cse7761Ref(RmsUC); Settings.energy_voltage_calibration = Cse7761Ref(RmsUC);
Settings.energy_current_calibration = Cse7761Ref(RmsIAC); Settings.energy_current_calibration = Cse7761Ref(RmsIAC);
Settings.energy_power_calibration = Cse7761Ref(PowerPAC); Settings.energy_power_calibration = Cse7761Ref(PowerPAC);
} }
// Just to fix intermediate users
if (Settings.energy_frequency_calibration < CSE7761_FREF / 2) {
Settings.energy_frequency_calibration = CSE7761_FREF;
}
Cse7761Write(CSE7761_SPECIAL_COMMAND, CSE7761_CMD_ENABLE_WRITE); Cse7761Write(CSE7761_SPECIAL_COMMAND, CSE7761_CMD_ENABLE_WRITE);
@ -320,7 +330,7 @@ bool Cse7761ChipInit(void) {
=1, turn on the power factor output function (Sonoff Dual R3 Pow) =1, turn on the power factor output function (Sonoff Dual R3 Pow)
=0, turn off the power factor output function =0, turn off the power factor output function
5 WaveEN Waveform data, instantaneous data output enable signal 5 WaveEN Waveform data, instantaneous data output enable signal
=1, turn on the waveform data output function =1, turn on the waveform data output function (Tasmota add frequency)
=0, turn off the waveform data output function (Sonoff Dual R3 Pow) =0, turn off the waveform data output function (Sonoff Dual R3 Pow)
4 SAGEN Voltage drop detection enable signal, WaveEN=1 must be configured first 4 SAGEN Voltage drop detection enable signal, WaveEN=1 must be configured first
=1, turn on the voltage drop detection function =1, turn on the voltage drop detection function
@ -329,14 +339,15 @@ bool Cse7761ChipInit(void) {
=1, turn on the overvoltage, overcurrent, and overload detection functions =1, turn on the overvoltage, overcurrent, and overload detection functions
=0, turn off the overvoltage, overcurrent, and overload detection functions (Sonoff Dual R3 Pow) =0, turn off the overvoltage, overcurrent, and overload detection functions (Sonoff Dual R3 Pow)
2 ZxEN Zero-crossing detection, phase angle, voltage frequency measurement enable signal 2 ZxEN Zero-crossing detection, phase angle, voltage frequency measurement enable signal
=1, turn on the zero-crossing detection, phase angle, and voltage frequency measurement functions =1, turn on the zero-crossing detection, phase angle, and voltage frequency measurement functions (Tasmota add frequency)
=0, disable zero-crossing detection, phase angle, voltage frequency measurement functions (Sonoff Dual R3 Pow) =0, disable zero-crossing detection, phase angle, voltage frequency measurement functions (Sonoff Dual R3 Pow)
1 PeakEN Peak detect enable signal 1 PeakEN Peak detect enable signal
=1, turn on the peak detection function =1, turn on the peak detection function
=0, turn off the peak detection function (Sonoff Dual R3 Pow) =0, turn off the peak detection function (Sonoff Dual R3 Pow)
0 NC Default is 1 0 NC Default is 1
*/ */
Cse7761Write(CSE7761_REG_EMUCON2 | 0x80, 0x0FC1); // Cse7761Write(CSE7761_REG_EMUCON2 | 0x80, 0x0FC1); // Sonoff Dual R3 Pow
Cse7761Write(CSE7761_REG_EMUCON2 | 0x80, 0x0FE5); // Tasmota add Frequency
} else { } else {
AddLog(LOG_LEVEL_DEBUG, PSTR("C61: Write failed")); AddLog(LOG_LEVEL_DEBUG, PSTR("C61: Write failed"));
return false; return false;
@ -354,6 +365,12 @@ void Cse7761GetData(void) {
#endif #endif
CSE7761Data.voltage_rms = (value >= 0x800000) ? 0 : value; CSE7761Data.voltage_rms = (value >= 0x800000) ? 0 : value;
value = Cse7761ReadFallback(CSE7761_REG_UFREQ, CSE7761Data.frequency, 2);
#ifdef CSE7761_SIMULATE
value = 8948; // 49.99Hz
#endif
CSE7761Data.frequency = (value >= 0x8000) ? 0 : value;
value = Cse7761ReadFallback(CSE7761_REG_RMSIA, CSE7761Data.current_rms[0], 3); value = Cse7761ReadFallback(CSE7761_REG_RMSIA, CSE7761Data.current_rms[0], 3);
#ifdef CSE7761_SIMULATE #ifdef CSE7761_SIMULATE
value = 455; value = 455;
@ -376,8 +393,8 @@ void Cse7761GetData(void) {
#endif #endif
CSE7761Data.active_power[1] = (0 == CSE7761Data.current_rms[1]) ? 0 : (value & 0x80000000) ? (~value) + 1 : value; CSE7761Data.active_power[1] = (0 == CSE7761Data.current_rms[1]) ? 0 : (value & 0x80000000) ? (~value) + 1 : value;
AddLog(LOG_LEVEL_DEBUG_MORE, PSTR("C61: U%d, I%d/%d, P%d/%d"), AddLog(LOG_LEVEL_DEBUG_MORE, PSTR("C61: F%d, U%d, I%d/%d, P%d/%d"),
CSE7761Data.voltage_rms, CSE7761Data.frequency, CSE7761Data.voltage_rms,
CSE7761Data.current_rms[0], CSE7761Data.current_rms[1], CSE7761Data.current_rms[0], CSE7761Data.current_rms[1],
CSE7761Data.active_power[0], CSE7761Data.active_power[1]); CSE7761Data.active_power[0], CSE7761Data.active_power[1]);
@ -385,6 +402,7 @@ void Cse7761GetData(void) {
// Voltage = RmsU * RmsUC * 10 / 0x400000 // Voltage = RmsU * RmsUC * 10 / 0x400000
// Energy.voltage[0] = (float)(((uint64_t)CSE7761Data.voltage_rms * CSE7761Data.coefficient[RmsUC] * 10) >> 22) / 1000; // V // Energy.voltage[0] = (float)(((uint64_t)CSE7761Data.voltage_rms * CSE7761Data.coefficient[RmsUC] * 10) >> 22) / 1000; // V
Energy.voltage[0] = ((float)CSE7761Data.voltage_rms / Settings.energy_voltage_calibration); // V Energy.voltage[0] = ((float)CSE7761Data.voltage_rms / Settings.energy_voltage_calibration); // V
Energy.frequency[0] = (CSE7761Data.frequency) ? ((float)Settings.energy_frequency_calibration / 8 / CSE7761Data.frequency) : 0; // Hz
for (uint32_t channel = 0; channel < 2; channel++) { for (uint32_t channel = 0; channel < 2; channel++) {
Energy.data_valid[channel] = 0; Energy.data_valid[channel] = 0;
@ -470,6 +488,7 @@ void Cse7761DrvInit(void) {
CSE7761Data.init = 4; // Init setup steps CSE7761Data.init = 4; // Init setup steps
Energy.phase_count = 2; // Handle two channels as two phases Energy.phase_count = 2; // Handle two channels as two phases
Energy.voltage_common = true; // Use common voltage Energy.voltage_common = true; // Use common voltage
Energy.frequency_common = true; // Use common frequency
TasmotaGlobal.energy_driver = XNRG_19; TasmotaGlobal.energy_driver = XNRG_19;
} }
} }
@ -492,6 +511,10 @@ bool Cse7761Command(void) {
if (1 == XdrvMailbox.payload) { XdrvMailbox.payload = Cse7761Ref(RmsIAC); } if (1 == XdrvMailbox.payload) { XdrvMailbox.payload = Cse7761Ref(RmsIAC); }
// Service in xdrv_03_energy.ino // Service in xdrv_03_energy.ino
} }
else if (CMND_FREQUENCYCAL == Energy.command_code) {
if (1 == XdrvMailbox.payload) { XdrvMailbox.payload = CSE7761_FREF; }
// Service in xdrv_03_energy.ino
}
else if (CMND_POWERSET == Energy.command_code) { else if (CMND_POWERSET == Energy.command_code) {
if (XdrvMailbox.data_len && CSE7761Data.active_power[channel]) { if (XdrvMailbox.data_len && CSE7761Data.active_power[channel]) {
if ((value > 100) && (value < 200000)) { // Between 1W and 2000W if ((value > 100) && (value < 200000)) { // Between 1W and 2000W
@ -513,6 +536,13 @@ bool Cse7761Command(void) {
} }
} }
} }
else if (CMND_FREQUENCYSET == Energy.command_code) {
if (XdrvMailbox.data_len && CSE7761Data.frequency) {
if ((value > 4500) && (value < 6500)) { // Between 45.00Hz and 65.00Hz
Settings.energy_frequency_calibration = (CSE7761Data.frequency * 8 * value) / 100;
}
}
}
else serviced = false; // Unknown command else serviced = false; // Unknown command
return serviced; return serviced;