134 lines
5.1 KiB
C++
134 lines
5.1 KiB
C++
/*
|
|
* Xiaoxiang BMS to MQTT via WiFi
|
|
* by Bas Vermulst - https://github.com/BeaverUI/ESP32-BluetoothBMS2MQTT
|
|
*
|
|
* Based on original work from https://github.com/kolins-cz/Smart-BMS-Bluetooth-ESP32/blob/master/README.md
|
|
*
|
|
|
|
=== configuring ===
|
|
Using the #define parameters in the CONFIGURATION section, do the following:
|
|
1) configure WiFi via WIFI_SSID and WIFI_PASSWORD
|
|
2) configure MQTT broker via MQTTSERVER
|
|
3) set unique node name via NODE_NAME
|
|
4) ensure the BMS settings are OK. You can verify the name and address using the "BLE Scanner" app on an Android phone.
|
|
|
|
|
|
=== compiling ===
|
|
1) Add ESP-WROVER to the board manager:
|
|
- File --> Preferences, add to board manager URLs: https://raw.githubusercontent.com/espressif/arduino-esp32/gh-pages/package_esp32_index.json
|
|
- Then, Tools --> Board --> Board manager... --> install ESP32 package v2.0.3 or later.
|
|
|
|
|
|
2) Install required libraries:
|
|
- MQTT (by Joel Gaehwiler)
|
|
Install via "Manage Libraries..." under Tools.
|
|
|
|
3) Configure board:
|
|
Select Tools --> Board --> "ESP32 Arduino" --> "ESP WRover module"
|
|
|
|
4) Connect board via USB.
|
|
|
|
5) Configure programming options:
|
|
Select appropriate programming port under Tools --> Port
|
|
Select correct partitioning: 1.9MB app (with OTA) or 2MB app with 2 MB SPIFFS - otherwise it won't fit
|
|
|
|
6) Program and go!
|
|
|
|
*/
|
|
|
|
// ==== 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_MIN_RSSI -75 // minimum signal strength before connection is attempted
|
|
#define BLE_NAME "BMS 1.1" // name of BMS
|
|
#define BLE_ADDRESS "70:e3:97:d2:b0:bb" // address of BMS
|
|
|
|
#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 10*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)
|
|
|
|
// watchdog timeout
|
|
#define WATCHDOG_TIMEOUT (BLE_TIMEOUT+10*1000) // go to sleep after x seconds
|
|
|
|
|
|
// ==== MAIN CODE ====
|
|
#include "datatypes.h" // for brevity the BMS stuff is in this file
|
|
#include <BLEDevice.h> // for BLE
|
|
|
|
#include <driver/adc.h> // to read ESP battery voltage
|
|
#include <rom/rtc.h> // 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();
|
|
}
|
|
|
|
/*
|
|
mqttclient.publish(GetTopic("ip"), IPAddressString(WiFi.localIP()));
|
|
mqttclient.publish(GetTopic("free-heap"), String(ESP.getFreeHeap()));
|
|
mqttclient.publish(GetTopic("maxalloc-heap"), String(xPortGetMinimumEverFreeHeapSize()));
|
|
mqttclient.publish(GetTopic("ssid"), WiFi.SSID());
|
|
mqttclient.publish(GetTopic("rssi"), String(WiFi.RSSI()));
|
|
|
|
mqttclient.publish(GetTopic("reset-reason"), String(GetResetReason(0)) + String(" | ") + String(GetResetReason(1)));
|
|
|
|
mqttclient.publish(GetTopic("runtime"), String(millis()/1000));
|
|
mqttclient.publish(GetTopic("battery-voltage"), String(battery_voltage,2));
|
|
|
|
mqttclient.publish(GetTopic("bms-status"), String(bms_status));
|
|
mqttclient.publish(GetTopic("bms-status-age"), String( (millis()-bms_last_update_time)/1000 ));
|
|
|
|
if(bms_status){
|
|
mqttclient.publish(GetTopic("number-of-cells"), String(packCellInfo.NumOfCells));
|
|
mqttclient.publish(GetTopic("current"), String((float)packBasicInfo.Amps / 1000,2));
|
|
mqttclient.publish(GetTopic("voltage"), String((float)packBasicInfo.Volts / 1000,2));
|
|
if(packCellInfo.NumOfCells != 0){
|
|
mqttclient.publish(GetTopic("cell-voltage"), String((float)packBasicInfo.Volts /(1000*packCellInfo.NumOfCells), 2));
|
|
}
|
|
mqttclient.publish(GetTopic("cell-diff"), String((float)packCellInfo.CellDiff, 0));
|
|
mqttclient.publish(GetTopic("soc"), String((float)packBasicInfo.CapacityRemainPercent,1));
|
|
|
|
mqttclient.publish(GetTopic("temperature-1"), String((float)packBasicInfo.Temp1 / 10,1));
|
|
mqttclient.publish(GetTopic("temperature-2"), String((float)packBasicInfo.Temp2 / 10,1));
|
|
}
|
|
|
|
MqttPublishDebug();
|
|
|
|
mqttclient.loop();
|
|
}
|
|
|
|
*/
|