From 5d4a5a96730e68233e0caaa1d833e3d138199ff7 Mon Sep 17 00:00:00 2001 From: James Date: Sat, 27 Apr 2024 11:44:19 +0100 Subject: [PATCH] fix --- ESPBMS.ino | 2 +- old/ESPBMS.ino | 592 ------------------------------------------------- 2 files changed, 1 insertion(+), 593 deletions(-) delete mode 100644 old/ESPBMS.ino diff --git a/ESPBMS.ino b/ESPBMS.ino index 5044fa3..ad84f4b 100644 --- a/ESPBMS.ino +++ b/ESPBMS.ino @@ -319,7 +319,7 @@ bool processBasicInfo(byte *data, unsigned int dataLen){ Serial.printf(">>>RC.%s.Voltage %f\r\n",currentName, (float)Volts / 1000); Serial.printf(">>>RC.%s.Amps %f\r\n",currentName, (float)Amps / 1000); - Serial.printf(">>>RC.%s.watts %f\r\n",currentName, (float)Watts); + Serial.printf(">>>RC.%s.Watts %f\r\n",currentName, (float)Watts); Serial.printf(">>>RC.%s.Capacity_Remain_Ah %f\r\n",currentName, (float)CapacityRemainAh / 1000); Serial.printf(">>>RC.%s.Capacity_Remain_Wh %f\r\n",currentName, ((float)(CapacityRemainAh) / 1000) * ((float)(Volts) / 1000)); Serial.printf(">>>RC.%s.Capacity_Remain_Percent %d\r\n",currentName, CapacityRemainPercent); diff --git a/old/ESPBMS.ino b/old/ESPBMS.ino deleted file mode 100644 index 1e5a6a8..0000000 --- a/old/ESPBMS.ino +++ /dev/null @@ -1,592 +0,0 @@ - -// ==== CONFIGURATION ==== -// BMS -#define BMS_MAX_CELLS 15 // defines size of data types -#define BMS_POLLING_INTERVAL 10*60*1000 // data output interval (shorter = connect more often = more battery consumption from BMS) in ms - -// BLE -#define BLE_SCAN_DURATION 1 // duration of scan in seconds -#define BLE_REQUEST_DELAY 500 // package request delay after connecting - make this large enough to have the connection established in ms -#define BLE_TIMEOUT 600*1000 // timeout of scan + gathering packets (too short will fail collecting all packets) in ms - -#define BLE_CALLBACK_DEBUG true // send debug messages via MQTT & serial in callbacks (handy for finding your BMS address, name, RSSI, etc) - -// ==== MAIN CODE ==== -#include "datatypes.h" // for brevity the BMS stuff is in this file -#include // for BLE - -#include // to read ESP battery voltage -#include // to get reset reason - - -// Init BMS -static BLEUUID serviceUUID("0000ff00-0000-1000-8000-00805f9b34fb"); //xiaoxiang bms service -static BLEUUID charUUID_rx("0000ff01-0000-1000-8000-00805f9b34fb"); //xiaoxiang bms rx id -static BLEUUID charUUID_tx("0000ff02-0000-1000-8000-00805f9b34fb"); //xiaoxiang bms tx id - -const byte cBasicInfo = 3; //datablock 3=basic info -const byte cCellInfo = 4; //datablock 4=individual cell info -packBasicInfoStruct packBasicInfo; -packCellInfoStruct packCellInfo; -unsigned long bms_last_update_time=0; -bool bms_status; -#define BLE_PACKETSRECEIVED_BEFORE_STANDBY 0b11 // packets to gather before disconnecting - -// Other stuff -float battery_voltage=0; // internal battery voltage -String debug_log_string=""; -hw_timer_t * wd_timer = NULL; - -void debug(String s){ - Serial.println(s); -} - -void setup(){ - Serial.begin(115200); -} - - -// === Main stuff ==== -void loop(){ - bleGatherPackets(); -} - -BLEScan* pBLEScan = nullptr; -BLEClient* pClient = nullptr; -BLEAdvertisedDevice* pRemoteDevice = nullptr; -BLERemoteService* pRemoteService = nullptr; -BLERemoteCharacteristic* pRemoteCharacteristic_rx = nullptr; -BLERemoteCharacteristic* pRemoteCharacteristic_tx = nullptr; - -boolean doScan = false; // becomes true when BLE is initialized and scanning is allowed -boolean doConnect = false; // becomes true when correct ID is found during scanning - -boolean ble_client_connected = false; // true when fully connected - -unsigned int ble_packets_requested = 0b00; // keeps track of requested packets -unsigned int ble_packets_received = 0b00; // keeps track of received packets - -void MyEndOfScanCallback(BLEScanResults pBLEScanResult){ - bms_status=false; // BMS not found - - if(BLE_CALLBACK_DEBUG){ - debug("BLE: scan finished"); - Serial.println("Scan finished."); - } -} - -class MyAdvertisedDeviceCallbacks : public BLEAdvertisedDeviceCallbacks{ - // called for each advertising BLE server - - void onResult(BLEAdvertisedDevice advertisedDevice){ - // found a device - - - if(BLE_CALLBACK_DEBUG){ - debug( - String("BLE: found ") + - String(advertisedDevice.getName().c_str()) + - String(" with address ") + - String(advertisedDevice.getAddress().toString().c_str()) + - String(" and RSSI ") + - String(advertisedDevice.getRSSI()) - ); - - Serial.print("BLE: found "); - Serial.println(advertisedDevice.toString().c_str()); - } - - // Check if device is advertising the specific service UUID - if (!advertisedDevice.isAdvertisingService(serviceUUID)) { - debug("Device does not advertise the specified service UUID."); - return; - } - - if(BLE_CALLBACK_DEBUG){ - debug("BLE: target device found"); - } - - pBLEScan->stop(); - - // delete old remote device, create new one - if(pRemoteDevice != nullptr){ - delete pRemoteDevice; - } - pRemoteDevice = new BLEAdvertisedDevice(advertisedDevice); - - doConnect = true; - } -}; - -class MyClientCallback : public BLEClientCallbacks{ - // called on connect/disconnect - void onConnect(BLEClient* pclient){ - - if(BLE_CALLBACK_DEBUG){ - debug(String("BLE: connecting to ") + String(pclient->getPeerAddress().toString().c_str())); - } - } - - void onDisconnect(BLEClient* pclient){ - ble_client_connected = false; - doConnect = false; - - if(BLE_CALLBACK_DEBUG){ - debug(String("BLE: disconnected from ") + String(pclient->getPeerAddress().toString().c_str())); - } - - } -}; - -static void MyNotifyCallback(BLERemoteCharacteristic *pBLERemoteCharacteristic, uint8_t *pData, size_t length, bool isNotify){ - //this is called when BLE server sents data via notification - //hexDump((char*)pData, length); - if(!bleCollectPacket((char *)pData, length)){ - debug("ERROR: packet could not be collected."); - } -} - -void handleBLE(){ - static unsigned long prev_millis_standby = 0; - - prev_millis_standby = millis(); - - while(true){ // loop until we hit a timeout or gathered all packets - - if((ble_packets_received == BLE_PACKETSRECEIVED_BEFORE_STANDBY) || (millis()>prev_millis_standby+BLE_TIMEOUT)){ - if(ble_packets_received == BLE_PACKETSRECEIVED_BEFORE_STANDBY){ - debug("BLE: all packets received"); - bms_status=true; // BMS was connected, data up-to-date - printBasicInfo(); - printCellInfo(); - }else{ - debug("BLE: connection timeout"); - bms_status=false; // BMS not (fully) connected - } - - break; // we're done with BLE, exit while loop - } - else if (doConnect){ - - // found the desired BLE server, now connect to it - if (connectToServer()){ - ble_client_connected = true; - ble_packets_received=0; - ble_packets_requested=0; - - }else{ - ble_client_connected = false; - debug("BLE: failed to connect"); - } - - doConnect = false; - } - - if (ble_client_connected){ - debug("BLE: requesting packet 0b01"); - delay(5000); - bmsRequestBasicInfo(); - debug("BLE: requesting packet 0b10"); - delay(5000); - bmsRequestCellInfo(); - }else if ((!doConnect)&&(doScan)){ - // we are not connected, so we can scan for devices - debug("BLE: not connected, starting scan"); - Serial.print("BLE is not connected, starting scan"); - - // Disconnect client - if((pClient != nullptr)&&(pClient->isConnected())){ - pClient->disconnect(); - } - - // stop scan (if running) and start a new one - pBLEScan->setActiveScan(true); - pBLEScan->setInterval(1 << 8); // 160 ms - pBLEScan->setWindow(1 << 7); // 80 ms - pBLEScan->start(BLE_SCAN_DURATION, MyEndOfScanCallback, false); // non-blocking, use a callback - - doScan=false; - - debug("BLE: scan started"); - } - } -} - -void bleGatherPackets(){ - bleStart(); - handleBLE(); - blePause(); - BLEDevice::deinit(false); -} - -void bleStart(){ - Serial.print("Starting BLE... "); - - BLEDevice::init(""); - //esp_bt_controller_mem_release(ESP_BT_MODE_CLASSIC_BT); // release some unused memory - - // Retrieve a BLE client - pClient = BLEDevice::createClient(); - pClient->setClientCallbacks(new MyClientCallback()); - - // Retrieve a BLE scanner - pBLEScan = BLEDevice::getScan(); - pBLEScan->setAdvertisedDeviceCallbacks(new MyAdvertisedDeviceCallbacks()); - - bleContinue(); - Serial.println("done"); -} - -void blePause(){ - // stop scanning and disconnect from all devices - doScan=false; - - // Disconnect client - if((pClient != nullptr)&&(pClient->isConnected())){ - pClient->disconnect(); - } - - delay(50); - - pBLEScan->stop(); - - ble_client_connected=false; - doConnect=false; - ble_packets_received=0; - ble_packets_requested=0; - -} - -void bleContinue(){ - // Prepare for scanning - ble_client_connected=false; - doConnect=false; - ble_packets_received=0; - - doScan=true; // start scanning for new devices -} - -bool connectToServer(){ - if(pRemoteDevice==nullptr){ - Serial.println("Invalid remote device, can't connect"); - return false; - } - - // Disconnect client - if((pClient != nullptr)&&(pClient->isConnected())){ - pClient->disconnect(); - } - - Serial.print("Forming a connection to "); - Serial.println(pRemoteDevice->getAddress().toString().c_str()); - - delay(100); - - // Connect to the remote BLE Server. - pClient->connect(pRemoteDevice); - if(!(pClient->isConnected())){ - debug(String("BLE: failed to connect")); - Serial.println("Failed to connect to server"); - pClient->disconnect(); - return false; - } - - Serial.println(" - Connected to server"); - - - delay(BLE_REQUEST_DELAY); // wait, otherwise writeValue doesn't work for some reason - // to do: fix this ugly hack - - debug(String("BLE: connected")); - - return true; -} - -bool sendCommand(uint8_t *data, uint32_t dataLen){ - if((pClient!=nullptr)&&(pClient->isConnected())){ - pRemoteCharacteristic_tx->writeValue(data, dataLen, false); - return true; - }else{ - return false; - } -} - -bool isPacketValid(byte *packet) //check if packet is valid -{ - if (packet == nullptr){ - return false; - } - - bmsPacketHeaderStruct *pHeader = (bmsPacketHeaderStruct *)packet; - int checksumPos = pHeader->dataLen + 2; // status + data len + data - - int offset = 2; // header 0xDD and command type are not in data length - - if (packet[0] != 0xDD){ - // start bit missing - return false; - } - - if (packet[offset + checksumPos + 2] != 0x77){ - // stop bit missing - return false; - } - - byte checksum = 0; - for (int i = 0; i < checksumPos; i++){ - checksum += packet[offset + i]; - } - checksum = ((checksum ^ 0xFF) + 1) & 0xFF; - - if (checksum != packet[offset + checksumPos + 1]){ - return false; - } - - return true; -} - -bool processBasicInfo(packBasicInfoStruct *output, byte *data, unsigned int dataLen) -{ - // Expected data len - if (dataLen != 0x1B) - { - //Serial.printf("bad data len %d!\r\n",dataLen); - //return false; - } - - output->Volts = ((uint32_t)two_ints_into16(data[0], data[1])) * 10; // Resolution 10 mV -> convert to milivolts eg 4895 > 48950mV - output->Amps = ((int32_t)two_ints_into16(data[2], data[3])) * 10; // Resolution 10 mA -> convert to miliamps - - output->Watts = output->Volts * output->Amps / 1000000; // W - - output->CapacityRemainAh = ((uint16_t)two_ints_into16(data[4], data[5])) * 10; - output->CapacityRemainPercent = ((uint8_t)data[19]); - - output->Temp1 = (((uint16_t)two_ints_into16(data[23], data[24])) - 2731); - output->Temp2 = (((uint16_t)two_ints_into16(data[25], data[26])) - 2731); - - output->BalanceCodeLow = (two_ints_into16(data[12], data[13])); - output->BalanceCodeHigh = (two_ints_into16(data[14], data[15])); - output->MosfetStatus = ((byte)data[20]); - - printBasicInfo(); - - return true; -} - -bool processCellInfo(packCellInfoStruct *output, byte *data, unsigned int dataLen) -{ - uint16_t _cellSum; - uint16_t _cellMin = 5000; - uint16_t _cellMax = 0; - uint16_t _cellAvg; - uint16_t _cellDiff; - - output->NumOfCells = dataLen / 2; // data contains 2 bytes per cell - - //go trough individual cells - for (byte i = 0; i < dataLen / 2; i++) - { - output->CellVolt[i] = ((uint16_t)two_ints_into16(data[i * 2], data[i * 2 + 1])); // Resolution 1 mV - _cellSum += output->CellVolt[i]; - if (output->CellVolt[i] > _cellMax) - { - _cellMax = output->CellVolt[i]; - } - if (output->CellVolt[i] < _cellMin) - { - _cellMin = output->CellVolt[i]; - } - } - - output->CellMin = _cellMin; - output->CellMax = _cellMax; - output->CellDiff = _cellMax - _cellMin; - output->CellAvg = _cellSum / output->NumOfCells; - - printCellInfo(); - - return true; -} - -bool bmsProcessPacket(byte *packet) -{ - bool isValid = isPacketValid(packet); - - if (isValid != true) - { - Serial.println("Invalid packer received"); - return false; - } - - bmsPacketHeaderStruct *pHeader = (bmsPacketHeaderStruct *)packet; - byte *data = packet + sizeof(bmsPacketHeaderStruct); // TODO Fix this ugly hack - unsigned int dataLen = pHeader->dataLen; - - bool result = false; - - // find packet type (basic info or cell info) - switch (pHeader->type) - { - case cBasicInfo: - { - // Process basic info - result = processBasicInfo(&packBasicInfo, data, dataLen); - if(result==true){ - ble_packets_received |= 0b01; - bms_last_update_time=millis(); - } - - break; - } - - case cCellInfo: - { - // Process cell info - result = processCellInfo(&packCellInfo, data, dataLen); - if(result==true){ - ble_packets_received |= 0b10; - bms_last_update_time=millis(); - } - break; - } - - default: - result = false; - Serial.printf("Unsupported packet type detected. Type: %d", pHeader->type); - } - - return result; -} - -bool bleCollectPacket(char *data, uint32_t dataSize) // reconstruct packet, called by notifyCallback function -{ - static uint8_t packetstate = 0; //0 - empty, 1 - first half of packet received, 2- second half of packet received - - // packet sizes: - // (packet ID 03) = 4 (header) + 23 + 2*N_NTCs + 2 (checksum) + 1 (stop) - // (packet ID 04) = 4 (header) + 2*NUM_CELLS + 2 (checksum) + 1 (stop) - static uint8_t packetbuff[4 + 2*25 + 2 + 1] = {0x0}; // buffer size suitable for up to 25 cells - - static uint32_t totalDataSize = 0; - bool retVal = false; - hexDump(data,dataSize); - - if(totalDataSize + dataSize > sizeof(packetbuff)){ - Serial.printf("ERROR: datasize is overlength."); - - debug( - String("ERROR: datasize is overlength. ") + - String("allocated=") + - String(sizeof(packetbuff)) + - String(", size=") + - String(totalDataSize + dataSize) - ); - - totalDataSize = 0; - packetstate = 0; - - retVal = false; - } - else if (data[0] == 0xdd && packetstate == 0) // probably got 1st half of packet - { - Serial.println("PKT1"); - packetstate = 1; - for (uint8_t i = 0; i < dataSize; i++) - { - packetbuff[i] = data[i]; - } - totalDataSize = dataSize; - retVal = true; - - if (data[dataSize - 1] == 0x77) { - //its full packets - packetstate = 2; - } - } - else if (data[dataSize - 1] == 0x77 && packetstate == 1) //probably got 2nd half of the packet - { - Serial.println("PKT2"); - packetstate = 2; - for (uint8_t i = 0; i < dataSize; i++) - { - packetbuff[i + totalDataSize] = data[i]; - } - totalDataSize += dataSize; - retVal = true; - } - - if (packetstate == 2) //got full packet - { - Serial.println("PKT3"); - uint8_t packet[totalDataSize]; - memcpy(packet, packetbuff, totalDataSize); - - bmsProcessPacket(packet); //pass pointer to retrieved packet to processing function - packetstate = 0; - totalDataSize = 0; - retVal = true; - } - return retVal; -} - -bool bmsRequestBasicInfo(){ - // header status command length data checksum footer - // DD A5 03 00 FF FD 77 - uint8_t data[7] = {0xdd, 0xa5, cBasicInfo, 0x0, 0xff, 0xfd, 0x77}; - return sendCommand(data, sizeof(data)); -} - -bool bmsRequestCellInfo(){ - // header status command length data checksum footer - // DD A5 04 00 FF FC 77 - uint8_t data[7] = {0xdd, 0xa5, cCellInfo, 0x0, 0xff, 0xfc, 0x77}; - return sendCommand(data, sizeof(data)); -} - -void printBasicInfo() //debug all data to uart -{ - Serial.printf("Total voltage: %f\r\n", (float)packBasicInfo.Volts / 1000); - Serial.printf("Amps: %f\r\n", (float)packBasicInfo.Amps / 1000); - Serial.printf("CapacityRemainAh: %f\r\n", (float)packBasicInfo.CapacityRemainAh / 1000); - Serial.printf("CapacityRemainPercent: %d\r\n", packBasicInfo.CapacityRemainPercent); - Serial.printf("Temp1: %f\r\n", (float)packBasicInfo.Temp1 / 10); - Serial.printf("Temp2: %f\r\n", (float)packBasicInfo.Temp2 / 10); - Serial.printf("Balance Code Low: 0x%x\r\n", packBasicInfo.BalanceCodeLow); - Serial.printf("Balance Code High: 0x%x\r\n", packBasicInfo.BalanceCodeHigh); - Serial.printf("Mosfet Status: 0x%x\r\n", packBasicInfo.MosfetStatus); -} - -void printCellInfo() //debug all data to uart -{ - Serial.printf("Number of cells: %u\r\n", packCellInfo.NumOfCells); - for (byte i = 1; i <= packCellInfo.NumOfCells; i++) - { - Serial.printf("Cell no. %u", i); - Serial.printf(" %f\r\n", (float)packCellInfo.CellVolt[i - 1] / 1000); - } - Serial.printf("Max cell volt: %f\r\n", (float)packCellInfo.CellMax / 1000); - Serial.printf("Min cell volt: %f\r\n", (float)packCellInfo.CellMin / 1000); - Serial.printf("Difference cell volt: %f\r\n", (float)packCellInfo.CellDiff / 1000); - Serial.printf("Average cell volt: %f\r\n", (float)packCellInfo.CellAvg / 1000); - Serial.println(); -} - -void hexDump(const char *data, uint32_t dataSize) //debug function -{ - Serial.println("HEX data:"); - - for (int i = 0; i < dataSize; i++) - { - Serial.printf("0x%x, ", data[i]); - } - Serial.println(""); -} - -int16_t two_ints_into16(int highbyte, int lowbyte) // turns two bytes into a single long integer -{ - int16_t result = (highbyte); - result <<= 8; //Left shift 8 bits, - result = (result | lowbyte); //OR operation, merge the two - return result; -}