diff --git a/tasmota/include/tasmota_template.h b/tasmota/include/tasmota_template.h index b1a9ee913..0494b340b 100644 --- a/tasmota/include/tasmota_template.h +++ b/tasmota/include/tasmota_template.h @@ -509,6 +509,7 @@ const char kSensorNamesFixed[] PROGMEM = #define MAX_DINGTIAN_SHIFT 4 #define MAX_MAGIC_SWITCH_MODES 2 #define MAX_BL0942_RX 8 // Baudrates 1/5 (4800), 2/6 (9600), 3/7 (19200), 4/8 (38400), Support Positive values only 1..4, Support also negative values 5..8 +#define MAX_CSE7761 2 // Model 1/2 (DUALR3), 2/2 (POWCT) const uint16_t kGpioNiceList[] PROGMEM = { GPIO_NONE, // Not used @@ -886,7 +887,7 @@ const uint16_t kGpioNiceList[] PROGMEM = { #endif // USE_ADE7953 #ifdef USE_CSE7761 AGPIO(GPIO_CSE7761_TX), // CSE7761 Serial interface (Dual R3) - AGPIO(GPIO_CSE7761_RX), // CSE7761 Serial interface (Dual R3) + AGPIO(GPIO_CSE7761_RX) + MAX_CSE7761, // CSE7761 Serial interface (1 = Dual R3, 2 = POWCT) #endif #ifdef USE_CSE7766 AGPIO(GPIO_CSE7766_TX), // CSE7766 Serial interface (S31 and Pow R2) diff --git a/tasmota/tasmota_xnrg_energy/xnrg_19_cse7761.ino b/tasmota/tasmota_xnrg_energy/xnrg_19_cse7761.ino index 2fc4ea1fb..1ae32783d 100644 --- a/tasmota/tasmota_xnrg_energy/xnrg_19_cse7761.ino +++ b/tasmota/tasmota_xnrg_energy/xnrg_19_cse7761.ino @@ -20,7 +20,7 @@ #ifdef USE_ENERGY_SENSOR #ifdef USE_CSE7761 /*********************************************************************************************\ - * CSE7761 - Energy (Sonoff Dual R3 Pow) + * CSE7761 - Energy (Sonoff Dual R3 Pow and Pox CT) * * Without zero-cross detection * {"NAME":"Sonoff Dual R3","GPIO":[32,0,0,0,0,0,0,0,0,576,225,0,0,0,0,0,0,0,0,0,0,7296,7328,224,0,0,0,0,160,161,0,0,0,0,0,0],"FLAG":0,"BASE":1} @@ -88,6 +88,8 @@ enum CSE7761 { RmsIAC, RmsIBC, RmsUC, PowerPAC, PowerPBC, PowerSC, EnergyAC, Ene TasmotaSerial *Cse7761Serial = nullptr; +enum CSE7761Model { CSE7761_MODEL_DUALR3, CSE7761_MODEL_POWCT }; // Model index number starting from 0 + struct { uint32_t frequency = 0; uint32_t voltage_rms = 0; @@ -98,6 +100,7 @@ struct { uint8_t energy_update[2] = { 0 }; uint8_t init = 4; uint8_t ready = 0; + uint8_t model; } CSE7761Data; /********************************************************************************************/ @@ -442,16 +445,18 @@ void Cse7761GetData(void) { #endif CSE7761Data.active_power[0] = (0 == CSE7761Data.current_rms[0]) ? 0 : (value & 0x80000000) ? (~value) + 1 : value; - value = Cse7761ReadFallback(CSE7761_REG_RMSIB, CSE7761Data.current_rms[1], 3); + if (2 == Energy->phase_count) { + value = Cse7761ReadFallback(CSE7761_REG_RMSIB, CSE7761Data.current_rms[1], 3); #ifdef CSE7761_SIMULATE - value = 29760; // 0.185A + value = 29760; // 0.185A #endif - CSE7761Data.current_rms[1] = ((value >= 0x800000) || (value < 1600)) ? 0 : value; // No load threshold of 10mA - value = Cse7761ReadFallback(CSE7761_REG_POWERPB, CSE7761Data.active_power[1], 4); + CSE7761Data.current_rms[1] = ((value >= 0x800000) || (value < 1600)) ? 0 : value; // No load threshold of 10mA + value = Cse7761ReadFallback(CSE7761_REG_POWERPB, CSE7761Data.active_power[1], 4); #ifdef CSE7761_SIMULATE - value = 2126641; // 44.05W + value = 2126641; // 44.05W #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: F%d, U%d, I%d/%d, P%d/%d"), CSE7761Data.frequency, CSE7761Data.voltage_rms, @@ -459,16 +464,20 @@ void Cse7761GetData(void) { CSE7761Data.active_power[0], CSE7761Data.active_power[1]); if (Energy->power_on) { // Powered on - // 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)CSE7761Data.voltage_rms / EnergyGetCalibration(ENERGY_VOLTAGE_CALIBRATION)); // V - Energy->voltage[1] = Energy->voltage[0]; + for (uint32_t channel = 0; channel < Energy->phase_count; channel++) { + if (0 == channel) { + // 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)CSE7761Data.voltage_rms / EnergyGetCalibration(ENERGY_VOLTAGE_CALIBRATION)); // V #ifdef CSE7761_FREQUENCY - Energy->frequency[0] = (CSE7761Data.frequency) ? ((float)EnergyGetCalibration(ENERGY_FREQUENCY_CALIBRATION) / 8 / CSE7761Data.frequency) : 0; // Hz - Energy->frequency[1] = Energy->frequency[0]; + Energy->frequency[0] = (CSE7761Data.frequency) ? ((float)EnergyGetCalibration(ENERGY_FREQUENCY_CALIBRATION) / 8 / CSE7761Data.frequency) : 0; // Hz #endif - - for (uint32_t channel = 0; channel < 2; channel++) { + } else { + Energy->voltage[1] = Energy->voltage[0]; +#ifdef CSE7761_FREQUENCY + Energy->frequency[1] = Energy->frequency[0]; +#endif + } Energy->data_valid[channel] = 0; uint32_t power_calibration = EnergyGetCalibration(ENERGY_POWER_CALIBRATION, channel); // Active power = PowerPA * PowerPAC * 1000 / 0x80000000 @@ -563,7 +572,7 @@ void Cse7761EverySecond(void) { } else { if (2 == CSE7761Data.ready) { - for (uint32_t channel = 0; channel < 2; channel++) { + for (uint32_t channel = 0; channel < Energy->phase_count; channel++) { if (CSE7761Data.energy_update[channel]) { Energy->kWhtoday_delta[channel] += ((CSE7761Data.energy[channel] * 1000) / CSE7761Data.energy_update[channel]) / 36; CSE7761Data.energy[channel] = 0; @@ -577,7 +586,7 @@ void Cse7761EverySecond(void) { void Cse7761SnsInit(void) { // Software serial init needs to be done here as earlier (serial) interrupts may lead to Exceptions - Cse7761Serial = new TasmotaSerial(Pin(GPIO_CSE7761_RX), Pin(GPIO_CSE7761_TX), 1); + Cse7761Serial = new TasmotaSerial(Pin(GPIO_CSE7761_RX, GPIO_ANY), Pin(GPIO_CSE7761_TX), 1); if (Cse7761Serial->begin(38400, SERIAL_8E1)) { if (Cse7761Serial->hardwareSerial()) { SetSerial(38400, TS_SERIAL_8E1); @@ -599,10 +608,15 @@ void Cse7761SnsInit(void) { } void Cse7761DrvInit(void) { - if (PinUsed(GPIO_CSE7761_RX) && PinUsed(GPIO_CSE7761_TX)) { + if (PinUsed(GPIO_CSE7761_RX, GPIO_ANY) && PinUsed(GPIO_CSE7761_TX)) { + CSE7761Data.model = GetPin(Pin(GPIO_CSE7761_RX, GPIO_ANY)) - AGPIO(GPIO_CSE7761_RX); CSE7761Data.ready = 0; - CSE7761Data.init = 4; // Init setup steps - Energy->phase_count = 2; // Handle two channels as two phases + CSE7761Data.init = 4; // Init setup steps + +// Energy->phase_count = 1; // Handle one channel (default set by xdrv_03_energy.ino) + if (CSE7761_MODEL_DUALR3 == CSE7761Data.model) { + Energy->phase_count = 2; // Handle two channels as two phases + } Energy->voltage_common = true; // Use common voltage #ifdef CSE7761_FREQUENCY Energy->frequency_common = true; // Use common frequency @@ -615,7 +629,10 @@ void Cse7761DrvInit(void) { bool Cse7761Command(void) { bool serviced = true; - uint32_t channel = (2 == XdrvMailbox.index) ? 1 : 0; + uint32_t channel = 0; + if (Energy->phase_count > 1) { + channel = (2 == XdrvMailbox.index) ? 1 : 0; + } uint32_t value = (uint32_t)(CharToFloat(XdrvMailbox.data) * 100); // 1.23 = 123 if (CMND_POWERCAL == Energy->command_code) {