Using the suggestion, I have managed to get bit values into HA and I’ll tidy up the aesthetics later. Now I have a new challenge…
The UART read is producing this hex output:
01:B3:01:00:07:00:02:43:04:99:00:C0:00:4F:00:00:00:03:00:00:00:00:00:18:00:00:0F:89:00:00:00:00:00:00:00:00:60
The first 3 bytes (position 0, 1, 2) are static and can be dismissed. The bytes I think I am splitting into bits are bytes 3, 4 and 5 - 00:07:00 - but the bits dont match up.
When accurate, there should only be 3 1’s and everything else should be 0’s. Here is what I’m getting though (I have bytes 3 and 5 disabled in the code):
I’m confused about a couple of things;
- This statement in the protocol document - "The byte contains: 1 start bit, 8 data bits (least significant bit is sent first), no parity bit, 1 stop bit, 10 bits in total. Each character or byte is sent in order (left to right): Least Significant Bit (LSB)…Most Significant Bit (MSB). According to everything I am reading, left to right would result in MSB to LSB. Right to left would be LSB to MSB. It wouldn’t surprise me to find more errors in this document though.
- in the code below (I had already split out the bit and byte processing into different files yesterday) I can’t figure out if I should be numbering high to low or low to high or if I should be numbering 0x0 to 0x7 or 0x1 to 0x8 for bit positions.
I figure something funky is happening as a result but with the bytes either side of 4 being 00, I still think I should only be seeing 3 1’s, even if the position of them is offset.
Any ideas?
include code for bit processing:
// *****************************************************************
// * ESPHome Custom Component Modbus sniffer for *
// * Ampinvt MPPT Solar Controller *
// * Original code credits: *
// * https://github.com/htvekov/ *
// * https://github.com/assembly12/ *
// *****************************************************************
#include "esphome.h"
class ampinvtbitsensor : public PollingComponent, public Sensor, public UARTDevice {
public:
ampinvtbitsensor(UARTComponent *parent) : PollingComponent(600), UARTDevice(parent) {}
//37 bytes total - 25 bytes used, 12 bytes unused
Sensor *ampinvt_op_status = new Sensor(); // 1 bit ~ byte 3 (0=Normal, 1=Abnormal - Battery Automatic Recognition Error)
Sensor *ampinvt_battery_status = new Sensor(); // 1 bit ~ byte 3 (0=Normal, 1=Over Discharge Protection)
Sensor *ampinvt_fan_status = new Sensor(); // 1 bit ~ byte 3 (0=Normal, 1=Fan Failure)
Sensor *ampinvt_overheat_status = new Sensor(); // 1 bit ~ byte 3 (0=Normal, 1=Over Temperature Protection)
Sensor *ampinvt_dcoutput_status = new Sensor(); // 1 bit ~ byte 3 (0=Normal, 1=DC Output SHort / Over Current Protection)
Sensor *ampinvt_inttemp1_status = new Sensor(); // 1 bit ~ byte 3 (0=Close, 1=Fault)
Sensor *ampinvt_inttemp2_status = new Sensor(); // 1 bit ~ byte 3 (0=Close, 1=Fault)
Sensor *ampinvt_exttemp_status = new Sensor(); // 1 bit ~ byte 3 (0=Close, 1=Fault)
Sensor *ampinvt_chg_status = new Sensor(); // 1 bit ~ byte 4 (0=Not Charging, 1=Charging)
Sensor *ampinvt_equalchg_status = new Sensor(); // 1 bit ~ byte 4 (1=True)
Sensor *ampinvt_track_status = new Sensor(); // 1 bit ~ byte 4 (1=True)
Sensor *ampinvt_floatchg_status = new Sensor(); // 1 bit ~ byte 4 (1=True)
Sensor *ampinvt_chgcurrentlimit_status = new Sensor(); // 1 bit ~ byte 4 (1=True)
Sensor *ampinvt_chgderating_status = new Sensor(); // 1 bit ~ byte 4 (1=True)
Sensor *ampinvt_remoteprohibchg_status = new Sensor(); // 1 bit ~ byte 4 (1=True)
Sensor *ampinvt_pvovervolt_status = new Sensor(); // 1 bit ~ byte 4 (1=True)
Sensor *ampinvt_chgoutputrelay_status = new Sensor(); // 1 bit ~ byte 5 (0=Close, 1=Open)
Sensor *ampinvt_loadoutput_status = new Sensor(); // 1 bit ~ byte 5 (0=Close, 1=Open)
Sensor *ampinvt_fanrelay_status = new Sensor(); // 1 bit ~ byte 5 (0=Close, 1=Open)
Sensor *ampinvt_overchgprotect_status = new Sensor(); // 1 bit ~ byte 5 (0=Normal, 1=Overcharge Protection)
Sensor *ampinvt_overvoltprotect_status = new Sensor(); // 1 bit ~ byte 5 (0=Normal, 1=Overvoltage Protection)
void setup() override {
}
std::vector<int> bytes;
void update() {
while(available() > 0) {
bytes.push_back(read());
if(bytes.size() < 37){
continue;
}
else {
}
if(bytes.size() == 37) {
// uint8_t op_status_byte = (uint8_t)(bytes[3]);
// #define BIT_OPERATING_STATUS 0x8 // 00000001
// #define BIT_BATTERY_STATUS 0x7 // 00000010
// #define BIT_FAN_STATUS 0x6 // 00000100
// #define BIT_TEMPERATURE_STATUS 0x5 // 00001000
// #define BIT_DCOUTPUT_STATUS 0x4 // 00010000
// #define BIT_INTTEMP1_STATUS 0x3 // 00100000
// #define BIT_INTTEMP2_STATUS 0x2 // 01000000
// #define BIT_EXTTEMP_STATUS 0x1 // 10000000
// id(ampinvt_op_status).publish_state((bool)(op_status_byte & BIT_OPERATING_STATUS));
// id(ampinvt_battery_status).publish_state((bool)(op_status_byte & BIT_BATTERY_STATUS));
// id(ampinvt_fan_status).publish_state((bool)(op_status_byte & BIT_FAN_STATUS));
// id(ampinvt_overheat_status).publish_state((bool)(op_status_byte & BIT_TEMPERATURE_STATUS));
// id(ampinvt_dcoutput_status).publish_state((bool)(op_status_byte & BIT_DCOUTPUT_STATUS));
// id(ampinvt_inttemp1_status).publish_state((bool)(op_status_byte & BIT_INTTEMP1_STATUS));
// id(ampinvt_inttemp2_status).publish_state((bool)(op_status_byte & BIT_INTTEMP2_STATUS));
// id(ampinvt_exttemp_status).publish_state((bool)(op_status_byte & BIT_EXTTEMP_STATUS));
uint8_t chg_status_byte = (uint8_t)(bytes[4]);
#define BIT_CHARGING_STATUS 0x1 // 00000001
#define BIT_EQUALCHG_STATUS 0x2 // 00000010
#define BIT_TRACK_STATUS 0x3 // 00000100
#define BIT_FLOATCHG_STATUS 0x4 // 00001000
#define BIT_CHGCURRENTLIMIT_STATUS 0x5 // 00010000
#define BIT_CHGDERATING_STATUS 0x6 // 00100000
#define BIT_REMOTEPROHIBCHG_STATUS 0x7 // 01000000
#define BIT_PVOVERVOLT_STATUS 0x8 // 10000000
id(ampinvt_chg_status).publish_state((bool)(chg_status_byte & BIT_CHARGING_STATUS));
id(ampinvt_equalchg_status).publish_state((bool)(chg_status_byte & BIT_EQUALCHG_STATUS));
id(ampinvt_track_status).publish_state((bool)(chg_status_byte & BIT_TRACK_STATUS));
id(ampinvt_floatchg_status).publish_state((bool)(chg_status_byte & BIT_FLOATCHG_STATUS));
id(ampinvt_chgcurrentlimit_status).publish_state((bool)(chg_status_byte & BIT_CHGCURRENTLIMIT_STATUS));
id(ampinvt_chgderating_status).publish_state((bool)(chg_status_byte & BIT_CHGDERATING_STATUS));
id(ampinvt_remoteprohibchg_status).publish_state((bool)(chg_status_byte & BIT_REMOTEPROHIBCHG_STATUS));
id(ampinvt_pvovervolt_status).publish_state((bool)(chg_status_byte & BIT_PVOVERVOLT_STATUS));
// uint8_t ctl_status_byte = (uint8_t)(bytes[5]);
// #define BIT_CHGOUTRLY_STATUS 0x8 // 00000001
// #define BIT_LOADOUTPUT_STATUS 0x7 // 00000010
// #define BIT_FANRLY_STATUS 0x6 // 00000100
// #define BIT_SPARE1_STATUS 0x5 // 00001000
// #define BIT_OVERCHGPROTECT_STATUS 0x4 // 00010000
// #define BIT_OVERVOLTPROTECT_STATUS 0x3 // 00100000
// #define BIT_SPARE2_STATUS 0x2 // 01000000
// #define BIT_SPARE3_STATUS 0x1 // 10000000
// id(ampinvt_chgoutputrelay_status).publish_state((bool)(ctl_status_byte & BIT_CHGOUTRLY_STATUS));
// id(ampinvt_loadoutput_status).publish_state((bool)(ctl_status_byte & BIT_LOADOUTPUT_STATUS));
// id(ampinvt_fanrelay_status).publish_state((bool)(ctl_status_byte & BIT_FANRLY_STATUS));
// id(ampinvt_overchgprotect_status).publish_state((bool)(ctl_status_byte & BIT_OVERCHGPROTECT_STATUS));
// id(ampinvt_overvoltprotect_status).publish_state((bool)(ctl_status_byte & BIT_OVERVOLTPROTECT_STATUS));
bytes.clear();
}
}
}
};