rejig
This commit is contained in:
parent
28f86e8ecc
commit
7dbdf8a27b
173
ESPBMS.ino
173
ESPBMS.ino
@ -1,66 +1,133 @@
|
|||||||
#include "BLEDevice.h"
|
/*
|
||||||
|
* 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
|
||||||
|
*
|
||||||
|
|
||||||
void setup() {
|
=== 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);
|
Serial.begin(115200);
|
||||||
BLEDevice::init(""); // Initialize BLE device
|
}
|
||||||
|
|
||||||
BLEScan* pBLEScan = BLEDevice::getScan(); // Create new scan
|
|
||||||
pBLEScan->setActiveScan(true); // Active scan uses more power, but get results faster
|
|
||||||
BLEScanResults foundDevices = pBLEScan->start(30); // Scan for 30 seconds
|
|
||||||
|
|
||||||
Serial.println("Scanning completed");
|
// === Main stuff ====
|
||||||
Serial.println("Devices found: " + String(foundDevices.getCount()));
|
void loop(){
|
||||||
|
bleGatherPackets();
|
||||||
|
}
|
||||||
|
|
||||||
for (int i = 0; i < foundDevices.getCount(); i++) {
|
/*
|
||||||
BLEAdvertisedDevice advertisedDevice = foundDevices.getDevice(i);
|
mqttclient.publish(GetTopic("ip"), IPAddressString(WiFi.localIP()));
|
||||||
Serial.println("\nFound Device: " + String(advertisedDevice.toString().c_str()));
|
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()));
|
||||||
|
|
||||||
// Now connect to the device and then discover its services and characteristics
|
mqttclient.publish(GetTopic("reset-reason"), String(GetResetReason(0)) + String(" | ") + String(GetResetReason(1)));
|
||||||
BLEClient* pClient = BLEDevice::createClient();
|
|
||||||
Serial.println("Connecting to: " + String(advertisedDevice.getAddress().toString().c_str()));
|
|
||||||
|
|
||||||
if (pClient->connect(&advertisedDevice)) {
|
mqttclient.publish(GetTopic("runtime"), String(millis()/1000));
|
||||||
Serial.println("Connected to device!");
|
mqttclient.publish(GetTopic("battery-voltage"), String(battery_voltage,2));
|
||||||
// Obtain references to all services
|
|
||||||
std::map<std::string, BLERemoteService*>* pRemoteServices = pClient->getServices();
|
|
||||||
for (auto &myService : *pRemoteServices) {
|
|
||||||
Serial.println("Service: " + String(myService.first.c_str()));
|
|
||||||
BLERemoteService* pRemoteService = myService.second;
|
|
||||||
|
|
||||||
// List all characteristics of this service
|
mqttclient.publish(GetTopic("bms-status"), String(bms_status));
|
||||||
std::map<std::string, BLERemoteCharacteristic*>* pChars = pRemoteService->getCharacteristics();
|
mqttclient.publish(GetTopic("bms-status-age"), String( (millis()-bms_last_update_time)/1000 ));
|
||||||
for (auto &myChar : *pChars) {
|
|
||||||
String properties = getCharacteristicProperties(myChar.second);
|
|
||||||
Serial.print("\tCharacteristic: " + String(myChar.first.c_str()) + " | Properties: " + properties);
|
|
||||||
|
|
||||||
// Read descriptors of the characteristic
|
if(bms_status){
|
||||||
std::map<std::string, BLERemoteDescriptor*>* pDescs = myChar.second->getDescriptors();
|
mqttclient.publish(GetTopic("number-of-cells"), String(packCellInfo.NumOfCells));
|
||||||
for (auto &desc : *pDescs) {
|
mqttclient.publish(GetTopic("current"), String((float)packBasicInfo.Amps / 1000,2));
|
||||||
std::string descValue = desc.second->readValue();
|
mqttclient.publish(GetTopic("voltage"), String((float)packBasicInfo.Volts / 1000,2));
|
||||||
Serial.print(" | Descriptor: " + String(desc.first.c_str()) + " Value: " + String(descValue.c_str()));
|
if(packCellInfo.NumOfCells != 0){
|
||||||
}
|
mqttclient.publish(GetTopic("cell-voltage"), String((float)packBasicInfo.Volts /(1000*packCellInfo.NumOfCells), 2));
|
||||||
|
|
||||||
Serial.println();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
pClient->disconnect();
|
|
||||||
} else {
|
|
||||||
Serial.println("Failed to connect.");
|
|
||||||
}
|
}
|
||||||
|
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();
|
||||||
}
|
}
|
||||||
|
|
||||||
String getCharacteristicProperties(BLERemoteCharacteristic* pChar) {
|
*/
|
||||||
String propDesc = "";
|
|
||||||
if (pChar->canRead()) propDesc += "read ";
|
|
||||||
if (pChar->canWrite()) propDesc += "write ";
|
|
||||||
if (pChar->canWriteNoResponse()) propDesc += "write_no_resp ";
|
|
||||||
if (pChar->canNotify()) propDesc += "notify ";
|
|
||||||
if (pChar->canIndicate()) propDesc += "indicate ";
|
|
||||||
propDesc.trim();
|
|
||||||
return propDesc;
|
|
||||||
}
|
|
||||||
|
|
||||||
void loop() {
|
|
||||||
// Nothing to do here
|
|
||||||
}
|
|
||||||
|
133
old/ESPBMS.ino
133
old/ESPBMS.ino
@ -1,133 +0,0 @@
|
|||||||
/*
|
|
||||||
* 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();
|
|
||||||
}
|
|
||||||
|
|
||||||
*/
|
|
66
test/ESPBMS.ino
Normal file
66
test/ESPBMS.ino
Normal file
@ -0,0 +1,66 @@
|
|||||||
|
#include "BLEDevice.h"
|
||||||
|
|
||||||
|
void setup() {
|
||||||
|
Serial.begin(115200);
|
||||||
|
BLEDevice::init(""); // Initialize BLE device
|
||||||
|
|
||||||
|
BLEScan* pBLEScan = BLEDevice::getScan(); // Create new scan
|
||||||
|
pBLEScan->setActiveScan(true); // Active scan uses more power, but get results faster
|
||||||
|
BLEScanResults foundDevices = pBLEScan->start(30); // Scan for 30 seconds
|
||||||
|
|
||||||
|
Serial.println("Scanning completed");
|
||||||
|
Serial.println("Devices found: " + String(foundDevices.getCount()));
|
||||||
|
|
||||||
|
for (int i = 0; i < foundDevices.getCount(); i++) {
|
||||||
|
BLEAdvertisedDevice advertisedDevice = foundDevices.getDevice(i);
|
||||||
|
Serial.println("\nFound Device: " + String(advertisedDevice.toString().c_str()));
|
||||||
|
|
||||||
|
// Now connect to the device and then discover its services and characteristics
|
||||||
|
BLEClient* pClient = BLEDevice::createClient();
|
||||||
|
Serial.println("Connecting to: " + String(advertisedDevice.getAddress().toString().c_str()));
|
||||||
|
|
||||||
|
if (pClient->connect(&advertisedDevice)) {
|
||||||
|
Serial.println("Connected to device!");
|
||||||
|
// Obtain references to all services
|
||||||
|
std::map<std::string, BLERemoteService*>* pRemoteServices = pClient->getServices();
|
||||||
|
for (auto &myService : *pRemoteServices) {
|
||||||
|
Serial.println("Service: " + String(myService.first.c_str()));
|
||||||
|
BLERemoteService* pRemoteService = myService.second;
|
||||||
|
|
||||||
|
// List all characteristics of this service
|
||||||
|
std::map<std::string, BLERemoteCharacteristic*>* pChars = pRemoteService->getCharacteristics();
|
||||||
|
for (auto &myChar : *pChars) {
|
||||||
|
String properties = getCharacteristicProperties(myChar.second);
|
||||||
|
Serial.print("\tCharacteristic: " + String(myChar.first.c_str()) + " | Properties: " + properties);
|
||||||
|
|
||||||
|
// Read descriptors of the characteristic
|
||||||
|
std::map<std::string, BLERemoteDescriptor*>* pDescs = myChar.second->getDescriptors();
|
||||||
|
for (auto &desc : *pDescs) {
|
||||||
|
std::string descValue = desc.second->readValue();
|
||||||
|
Serial.print(" | Descriptor: " + String(desc.first.c_str()) + " Value: " + String(descValue.c_str()));
|
||||||
|
}
|
||||||
|
|
||||||
|
Serial.println();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
pClient->disconnect();
|
||||||
|
} else {
|
||||||
|
Serial.println("Failed to connect.");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
String getCharacteristicProperties(BLERemoteCharacteristic* pChar) {
|
||||||
|
String propDesc = "";
|
||||||
|
if (pChar->canRead()) propDesc += "read ";
|
||||||
|
if (pChar->canWrite()) propDesc += "write ";
|
||||||
|
if (pChar->canWriteNoResponse()) propDesc += "write_no_resp ";
|
||||||
|
if (pChar->canNotify()) propDesc += "notify ";
|
||||||
|
if (pChar->canIndicate()) propDesc += "indicate ";
|
||||||
|
propDesc.trim();
|
||||||
|
return propDesc;
|
||||||
|
}
|
||||||
|
|
||||||
|
void loop() {
|
||||||
|
// Nothing to do here
|
||||||
|
}
|
Loading…
Reference in New Issue
Block a user