Refactor BL09xx driver

This commit is contained in:
Theo Arends 2021-10-03 16:32:58 +02:00
parent 20038aac18
commit 388b3d5f54

View File

@ -51,20 +51,6 @@
#define BL0942_UREF 15187
#define BL0942_IREF 251213
#define BL09XX_PULSES_NOT_INITIALIZED -1
#define BL0939_BUFFER_SIZE 35
#define BL0940_BUFFER_SIZE 35
#define BL0942_BUFFER_SIZE 23
#define BL0939_MODEL 39
#define BL0940_MODEL 40
#define BL0942_MODEL 42
#define BL0939_ADDRESS 0x05
#define BL0940_ADDRESS 0x00
#define BL0942_ADDRESS 0x08
#define BL09XX_WRITE_COMMAND 0xA0 // 0xA8 according to documentation
#define BL09XX_REG_I_FAST_RMS_CTRL 0x10
#define BL09XX_REG_MODE 0x18
@ -81,13 +67,26 @@
TasmotaSerial *Bl09XXSerial = nullptr;
enum Bl09xxModel { BL0939_MODEL, BL0940_MODEL, BL0942_MODEL, BL09XX_MODEL }; // Model index number starting from 0
const uint32_t bl09xx_pref[] = { BL0939_PREF, BL0940_PREF, BL0942_PREF }; // Power reference constant
const uint32_t bl09xx_uref[] = { BL0939_UREF, BL0940_UREF, BL0942_UREF }; // Voltage reference constant
const uint32_t bl09xx_iref[] = { BL0939_IREF, BL0940_IREF, BL0942_IREF }; // Current reference constant
const uint8_t bl09xx_type[] = { 39, 40, 42 }; // Device name BL09xx
const uint8_t bl09xx_phase_count[] = { 2, 1, 1 }; // Supported phase/channel count
const uint8_t bl09xx_address[] = { 0x05, 0x00, 0x08 }; // Device address
const uint8_t bl09xx_buffer_size[] = { 35, 35, 23 }; // Serial receive buffer size
const uint8_t bl09xx_init[5][4] = {
{ BL09XX_REG_SOFT_RESET, 0x5A, 0x5A, 0x5A }, // Reset to default
{ BL09XX_REG_USR_WRPROT, 0x55, 0x00, 0x00 }, // Enable User Operation Write
{ BL09XX_REG_MODE, 0x00, 0x10, 0x00 }, // 0x0100 = CF_UNABLE energy pulse, AC_FREQ_SEL 50Hz, RMS_UPDATE_SEL 800mS
{ BL09XX_REG_TPS_CTRL, 0xFF, 0x47, 0x00 }, // 0x47FF = Over-current and leakage alarm on, Automatic temperature measurement, Interval 100mS
{ BL09XX_REG_I_FAST_RMS_CTRL, 0x1C, 0x18, 0x00 } // 0x181C = Half cycle, Fast RMS threshold 6172
};
struct BL09XX {
long voltage = 0;
long current[2] = { 0, };
long power[2] = { 0, };
long power_cycle_first = 0;
long cf_pulses[2] = { 0, };
long cf_pulses_last_time[2] = { BL09XX_PULSES_NOT_INITIALIZED, BL09XX_PULSES_NOT_INITIALIZED};
uint32_t voltage = 0;
uint32_t current[2] = { 0, };
uint32_t power[2] = { 0, };
float temperature;
uint16_t tps1 = 0;
uint8_t *rx_buffer = nullptr;
@ -99,15 +98,6 @@ struct BL09XX {
bool received = false;
} Bl09XX;
const uint8_t bl09xx_init[5][4] = {
{ BL09XX_REG_SOFT_RESET, 0x5A, 0x5A, 0x5A }, // Reset to default
{ BL09XX_REG_USR_WRPROT, 0x55, 0x00, 0x00 }, // Enable User Operation Write
{ BL09XX_REG_MODE, 0x00, 0x10, 0x00 }, // 0x0100 = CF_UNABLE energy pulse, AC_FREQ_SEL 50Hz, RMS_UPDATE_SEL 800mS
{ BL09XX_REG_TPS_CTRL, 0xFF, 0x47, 0x00 }, // 0x47FF = Over-current and leakage alarm on, Automatic temperature measurement, Interval 100mS
{ BL09XX_REG_I_FAST_RMS_CTRL, 0x1C, 0x18, 0x00 } // 0x181C = Half cycle, Fast RMS threshold 6172
};
bool Bl09XXDecode3940(void) {
// 0 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34
// Sample from BL0940 (single channel)
@ -137,25 +127,19 @@ bool Bl09XXDecode3940(void) {
Bl09XX.temperature = ConvertTemp(t);
Bl09XX.voltage = Bl09XX.rx_buffer[12] << 16 | Bl09XX.rx_buffer[11] << 8 | Bl09XX.rx_buffer[10]; // V_RMS unsigned
int32_t tmp;
Bl09XX.current[0] = Bl09XX.rx_buffer[6] << 16 | Bl09XX.rx_buffer[5] << 8 | Bl09XX.rx_buffer[4]; // IA_RMS unsigned
tmp = Bl09XX.rx_buffer[18] << 24 | Bl09XX.rx_buffer[17] << 16 | Bl09XX.rx_buffer[16] << 8; // WATT_A signed
int32_t tmp = Bl09XX.rx_buffer[18] << 24 | Bl09XX.rx_buffer[17] << 16 | Bl09XX.rx_buffer[16] << 8; // WATT_A signed
Bl09XX.power[0] = abs(tmp >> 8); // WATT_A unsigned
tmp = Bl09XX.rx_buffer[24] << 24 | Bl09XX.rx_buffer[23] << 16 | Bl09XX.rx_buffer[22] << 8; // CFA_CNT signed
Bl09XX.cf_pulses[0] = abs(tmp >> 8); // CFA_CNT unsigned
if (Energy.phase_count > 1) {
Bl09XX.current[1] = Bl09XX.rx_buffer[9] << 16 | Bl09XX.rx_buffer[8] << 8 | Bl09XX.rx_buffer[7]; // IB_RMS unsigned
tmp = Bl09XX.rx_buffer[21] << 24 | Bl09XX.rx_buffer[20] << 16 | Bl09XX.rx_buffer[19] << 8; // WATT_B signed
Bl09XX.power[1] = abs(tmp >> 8); // WATT_B unsigned
tmp = Bl09XX.rx_buffer[27] << 24 | Bl09XX.rx_buffer[26] << 16 | Bl09XX.rx_buffer[25] << 8; // CFB_CNT signed
Bl09XX.cf_pulses[1] = abs(tmp >> 8); // CFB_CNT unsigned
}
#ifdef DEBUG_BL09XX
AddLog(LOG_LEVEL_DEBUG_MORE, PSTR("BL9: U %d, I %d/%d, P %d/%d, C %d/%d, T %d"),
Bl09XX.voltage, Bl09XX.current[0], Bl09XX.current[1], Bl09XX.power[0], Bl09XX.power[1], Bl09XX.cf_pulses[0], Bl09XX.cf_pulses[1], Bl09XX.tps1);
AddLog(LOG_LEVEL_DEBUG_MORE, PSTR("BL9: U %d, I %d/%d, P %d/%d, T %d"),
Bl09XX.voltage, Bl09XX.current[0], Bl09XX.current[1], Bl09XX.power[0], Bl09XX.power[1], Bl09XX.tps1);
#endif
return true;
@ -186,17 +170,13 @@ bool Bl09XXDecode42(void) {
}
Bl09XX.voltage = Bl09XX.rx_buffer[6] << 16 | Bl09XX.rx_buffer[5] << 8 | Bl09XX.rx_buffer[4]; // V_RMS unsigned
int32_t tmp;
Bl09XX.current[0] = Bl09XX.rx_buffer[3] << 16 | Bl09XX.rx_buffer[2] << 8 | Bl09XX.rx_buffer[1]; // IA_RMS unsigned
tmp = Bl09XX.rx_buffer[12] << 24 | Bl09XX.rx_buffer[11] << 16 | Bl09XX.rx_buffer[10] << 8; // WATT_A signed
int32_t tmp = Bl09XX.rx_buffer[12] << 24 | Bl09XX.rx_buffer[11] << 16 | Bl09XX.rx_buffer[10] << 8; // WATT_A signed
Bl09XX.power[0] = abs(tmp >> 8); // WATT_A unsigned
tmp = Bl09XX.rx_buffer[15] << 24 | Bl09XX.rx_buffer[14] << 16 | Bl09XX.rx_buffer[13] << 8; // CFA_CNT signed
Bl09XX.cf_pulses[0] = abs(tmp >> 8); // CFA_CNT unsigned
#ifdef DEBUG_BL09XX
AddLog(LOG_LEVEL_DEBUG_MORE, PSTR("BL9: U %d, I %d, P %d, C %d"),
Bl09XX.voltage, Bl09XX.current[0], Bl09XX.power[0], Bl09XX.cf_pulses[0]);
AddLog(LOG_LEVEL_DEBUG_MORE, PSTR("BL9: U %d, I %d, P %d"),
Bl09XX.voltage, Bl09XX.current[0], Bl09XX.power[0]);
#endif
return true;
@ -222,12 +202,12 @@ void Bl09XXUpdateEnergy() {
}
}
} else { // Powered off
// Bl09XX.power_cycle_first = 0;
Energy.voltage[0] = 0;
Energy.active_power[0] = Energy.active_power[1] = 0;
Energy.current[0] = Energy.current[1] = 0;
}
}
void Bl09XXSerialInput(void) {
while (Bl09XXSerial->available()) {
yield();
@ -249,12 +229,12 @@ void Bl09XXSerialInput(void) {
if (checksum == Bl09XX.rx_buffer[Bl09XX.buffer_size -1]) {
Energy.data_valid[0] = 0;
bool ok;
if (BL0942_MODEL == Bl09XX.model)
if (BL0942_MODEL == Bl09XX.model) {
ok = Bl09XXDecode42();
else
} else {
ok = Bl09XXDecode3940();
if (ok)
Bl09XXUpdateEnergy();
}
if (ok) { Bl09XXUpdateEnergy(); }
Bl09XX.received = false;
return;
} else {
@ -304,24 +284,9 @@ void Bl09XXInit(void) {
ClaimSerial();
}
if (HLW_UREF_PULSE == Settings->energy_voltage_calibration) {
switch (Bl09XX.model) {
case BL0939_MODEL:
Settings->energy_voltage_calibration = BL0939_UREF;
Settings->energy_current_calibration = BL0939_IREF;
Settings->energy_power_calibration = BL0939_PREF;
break;
case BL0940_MODEL:
Settings->energy_voltage_calibration = BL0940_UREF;
Settings->energy_current_calibration = BL0940_IREF;
Settings->energy_power_calibration = BL0940_PREF;
break;
case BL0942_MODEL:
default:
Settings->energy_voltage_calibration = BL0942_UREF;
Settings->energy_current_calibration = BL0942_IREF;
Settings->energy_power_calibration = BL0942_PREF;
break;
}
Settings->energy_voltage_calibration = bl09xx_uref[Bl09XX.model];
Settings->energy_current_calibration = bl09xx_iref[Bl09XX.model];
Settings->energy_power_calibration = bl09xx_pref[Bl09XX.model];
}
if ((BL0940_MODEL == Bl09XX.model) && (Settings->energy_current_calibration < (BL0940_IREF / 20))) {
Settings->energy_current_calibration *= 100;
@ -329,7 +294,7 @@ void Bl09XXInit(void) {
if (BL0942_MODEL != Bl09XX.model) {
#ifdef DEBUG_BL09XX
AddLog(LOG_LEVEL_DEBUG, PSTR("BL9: Send Init string for model BL09%02d"), Bl09XX.model);
AddLog(LOG_LEVEL_DEBUG, PSTR("BL9: Send Init string"));
#endif
Energy.use_overtemp = true; // Use global temperature for overtemp detection
for (uint32_t i = 0; i < 5; i++) {
@ -352,32 +317,32 @@ void Bl09XXInit(void) {
}
void Bl09XXPreInit(void) {
if (PinUsed(GPIO_BL0939_RX) && PinUsed(GPIO_TXD)) {
if (PinUsed(GPIO_TXD)) {
Bl09XX.model = BL09XX_MODEL;
if (PinUsed(GPIO_BL0939_RX)) {
Bl09XX.model = BL0939_MODEL;
Bl09XX.address = BL0939_ADDRESS;
Bl09XX.buffer_size = BL0939_BUFFER_SIZE;
Bl09XX.rx_pin = Pin(GPIO_BL0939_RX);
} else if (PinUsed(GPIO_BL0940_RX) && PinUsed(GPIO_TXD)) {
}
else if (PinUsed(GPIO_BL0940_RX)) {
Bl09XX.model = BL0940_MODEL;
Bl09XX.address = BL0940_ADDRESS;
Bl09XX.buffer_size = BL0940_BUFFER_SIZE;
Bl09XX.rx_pin = Pin(GPIO_BL0940_RX);
}
else if (PinUsed(GPIO_BL0942_RX) && PinUsed(GPIO_TXD)) {
else if (PinUsed(GPIO_BL0942_RX)) {
Bl09XX.model = BL0942_MODEL;
Bl09XX.address = BL0942_ADDRESS;
Bl09XX.buffer_size = BL0942_BUFFER_SIZE;
Bl09XX.rx_pin = Pin(GPIO_BL0942_RX);
}
if (Bl09XX.model) {
if (Bl09XX.model != BL09XX_MODEL) {
Bl09XX.address = bl09xx_address[Bl09XX.model];
Bl09XX.buffer_size = bl09xx_buffer_size[Bl09XX.model];
Bl09XX.rx_buffer = (uint8_t*)(malloc(Bl09XX.buffer_size));
if (Bl09XX.rx_buffer != nullptr) {
Energy.voltage_common = true; // Use common voltage
Energy.frequency_common = true; // Use common frequency
Energy.use_overtemp = true; // Use global temperature for overtemp detection
Energy.phase_count = (BL0939_MODEL == Bl09XX.model) ? 2 : 1; // Handle two channels as two phases
Energy.phase_count = bl09xx_phase_count[Bl09XX.model]; // Handle two channels as two phases
TasmotaGlobal.energy_driver = XNRG_14;
AddLog(LOG_LEVEL_DEBUG,PSTR("BL9: Enabling BL09%02d"), Bl09XX.model);
AddLog(LOG_LEVEL_DEBUG,PSTR("BL9: Enabling BL09%02d"), bl09xx_type[Bl09XX.model]);
}
}
}
}