Skip to content

Commit a2d0c27

Browse files
committed
Update BMS code to use lib-mbed-ltc681x
1 parent 3f0a3a5 commit a2d0c27

File tree

11 files changed

+138
-507
lines changed

11 files changed

+138
-507
lines changed

bms/CMakeLists.txt

Lines changed: 7 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -8,28 +8,31 @@ set(MBED_CONFIG_PATH ${CMAKE_CURRENT_BINARY_DIR} CACHE INTERNAL "")
88
set(APP_TARGET bms)
99

1010
set(CMAKE_CXX_STANDARD 17)
11-
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -Wno-register")
11+
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -Wno-register -Wno-deprecated-declarations")
1212

1313
include(${MBED_PATH}/tools/cmake/app.cmake)
1414

1515
add_subdirectory(${MBED_PATH})
1616

1717
# Libraries
18-
#add_library(optional INTERFACE deps/optional)
18+
add_subdirectory(lib-mbed-ltc681x)
1919

2020
add_executable(${APP_TARGET}
2121
src/Main.cpp
2222
src/BmsThread.cpp
2323
src/EnergusTempSensor.cpp
24-
src/LTC6811Bus.cpp
2524
src/LTC6811.cpp
2625
)
26+
#target_include_directories(${APP_TARGET} ${ltc681x_SOURCE_DIR})
2727

2828
mbed_configure_app_target(${APP_TARGET})
2929

3030
project(${APP_TARGET})
3131

32-
target_link_libraries(${APP_TARGET} mbed-os)
32+
target_link_libraries(${APP_TARGET}
33+
mbed-os
34+
lib-mbed-ltc681x
35+
)
3336

3437
mbed_set_post_build(${APP_TARGET})
3538

bms/lib-mbed-ltc681x.lib

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
https://github.com/formulaslug/lib-mbed-ltc681x#main

bms/src/BmsConfig.h

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -19,7 +19,7 @@ extern DigitalOut* chargerControl;
1919

2020
// Number of LTC6811 battery banks to communicate with
2121
#ifndef BMS_BANK_COUNT
22-
#define BMS_BANK_COUNT 4
22+
#define BMS_BANK_COUNT 1
2323
#endif
2424

2525
// Number of cell voltage readings per LTC6811
@@ -82,7 +82,7 @@ const int BMS_CELL_MAP[12] = {0, 1, 2, 3, -1, -1, 4, 5, 6, -1, -1, -1};
8282
//
8383
// To be set high and held high when software enters fault state
8484
#ifndef BMS_PIN_BMS_FLT
85-
#define BMS_PIN_BMS_FLT NC
85+
#define BMS_PIN_BMS_FLT p10
8686
#endif
8787

8888
// BMS fault latch
@@ -110,7 +110,7 @@ const int BMS_CELL_MAP[12] = {0, 1, 2, 3, -1, -1, 4, 5, 6, -1, -1, -1};
110110
//
111111
// To be pulled high to enable charger
112112
#ifndef BMS_PIN_CHARGER_CONTROL
113-
#define BMS_PIN_CHARGER_CONTROL NC
113+
#define BMS_PIN_CHARGER_CONTROL p11
114114
#endif
115115

116116
// Current input

bms/src/BmsThread.cpp

Lines changed: 92 additions & 42 deletions
Original file line numberDiff line numberDiff line change
@@ -1,9 +1,13 @@
11
#include "BmsThread.h"
22

3-
BMSThread::BMSThread(LTC6811Bus* bus, unsigned int frequency, std::vector<Queue<BmsEvent, mailboxSize>*> mailboxes) : m_bus(bus), mailboxes(mailboxes) {
3+
#include "LTC681xBus.h"
4+
#include "LTC681xCommand.h"
5+
#include "ThisThread.h"
6+
7+
BMSThread::BMSThread(LTC681xBus& bus, unsigned int frequency, std::vector<Queue<BmsEvent, mailboxSize>*> mailboxes) : m_bus(bus), mailboxes(mailboxes) {
48
m_delay = 1000 / frequency;
59
for (int i = 0; i < BMS_BANK_COUNT; i++) {
6-
m_chips.push_back(LTC6811(*bus, i));
10+
m_chips.push_back(LTC6811(bus, i));
711
}
812
for (int i = 0; i < BMS_BANK_COUNT; i++) {
913
//m_chips[i].getConfig().gpio5 = LTC6811::GPIOOutputState::kLow;
@@ -14,79 +18,125 @@ BMSThread::BMSThread(LTC6811Bus* bus, unsigned int frequency, std::vector<Queue<
1418
}
1519

1620
void BMSThread::threadWorker() {
17-
std::array<uint16_t, BMS_BANK_COUNT * BMS_BANK_CELL_COUNT> allVoltages;
18-
std::array<std::optional<int8_t>, BMS_BANK_COUNT * BMS_BANK_TEMP_COUNT> allTemps;
21+
// Perform self tests
1922

20-
while (true) {
21-
// Measure from all BMS banks
22-
for (int i = 0; i < BMS_BANK_COUNT; i++) {
23-
LTC6811::Configuration& conf = m_chips[i].getConfig();
23+
// Cell Voltage self test
24+
m_bus.WakeupBus();
25+
m_bus.SendCommand(LTC681xBus::BuildBroadcastBusCommand(StartSelfTestCellVoltage(AdcMode::k7k, SelfTestMode::kSelfTest1)));
26+
ThisThread::sleep_for(4);
27+
m_bus.WakeupBus();
28+
for (int i = 0; i < BMS_BANK_COUNT; i++) {
29+
uint16_t rawVoltages[12];
30+
if(m_bus.SendReadCommand(LTC681xBus::BuildAddressedBusCommand(ReadCellVoltageGroupA(), i), (uint8_t*)rawVoltages) != LTC681xBus::LTC681xBusStatus::Ok) {
31+
printf("Things are not okay. SelfTestVoltageA\n");
32+
}
33+
if(m_bus.SendReadCommand(LTC681xBus::BuildAddressedBusCommand(ReadCellVoltageGroupB(), i), (uint8_t*)rawVoltages + 6) != LTC681xBus::LTC681xBusStatus::Ok) {
34+
printf("Things are not okay. SelfTestVoltageB\n");
35+
}
36+
if(m_bus.SendReadCommand(LTC681xBus::BuildAddressedBusCommand(ReadCellVoltageGroupC(), i), (uint8_t*)rawVoltages + 12) != LTC681xBus::LTC681xBusStatus::Ok) {
37+
printf("Things are not okay. SelfTestVoltageC\n");
38+
}
39+
if(m_bus.SendReadCommand(LTC681xBus::BuildAddressedBusCommand(ReadCellVoltageGroupD(), i), (uint8_t*)rawVoltages + 18) != LTC681xBus::LTC681xBusStatus::Ok) {
40+
printf("Things are not okay. SelfTestVoltageD\n");
41+
}
2442

25-
// Turn on status LED
26-
conf.gpio5 = LTC6811::GPIOOutputState::kLow;
27-
m_chips[i].updateConfig();
43+
for (int j = 0; j < 12; j++) {
44+
printf("AXST %2d: %4x\n", j, rawVoltages[i]);
45+
}
46+
}
2847

29-
uint16_t* voltages = m_chips[i].getVoltages();
48+
// Cell GPIO self test
49+
m_bus.WakeupBus();
50+
m_bus.SendCommand(LTC681xBus::BuildBroadcastBusCommand(StartSelfTestGpio(AdcMode::k7k, SelfTestMode::kSelfTest1)));
51+
ThisThread::sleep_for(4);
52+
m_bus.WakeupBus();
53+
for (int i = 0; i < BMS_BANK_COUNT; i++) {
54+
uint16_t rawVoltages[12];
55+
if(m_bus.SendReadCommand(LTC681xBus::BuildAddressedBusCommand(ReadCellVoltageGroupA(), i), (uint8_t*)rawVoltages) != LTC681xBus::LTC681xBusStatus::Ok) {
56+
printf("Things are not okay. SelfTestVoltageA\n");
57+
}
58+
if(m_bus.SendReadCommand(LTC681xBus::BuildAddressedBusCommand(ReadCellVoltageGroupB(), i), (uint8_t*)rawVoltages + 6) != LTC681xBus::LTC681xBusStatus::Ok) {
59+
printf("Things are not okay. SelfTestVoltageB\n");
60+
}
3061

31-
// Measure all temperature sensors on the current bank
32-
uint16_t temperatures[BMS_BANK_TEMP_COUNT];
33-
for (unsigned int j = 0; j < BMS_BANK_TEMP_COUNT; j++) {
34-
conf.gpio1 = (j & 0x01) ? LTC6811::GPIOOutputState::kHigh
35-
: LTC6811::GPIOOutputState::kLow;
36-
conf.gpio2 = (j & 0x02) ? LTC6811::GPIOOutputState::kHigh
37-
: LTC6811::GPIOOutputState::kLow;
38-
conf.gpio3 = (j & 0x04) ? LTC6811::GPIOOutputState::kHigh
39-
: LTC6811::GPIOOutputState::kLow;
40-
conf.gpio4 = LTC6811::GPIOOutputState::kPassive;
41-
m_chips[i].updateConfig();
62+
for (int j = 0; j < 12; j++) {
63+
printf("CVST %2d: %4x\n", j, rawVoltages[i]);
64+
}
65+
}
4266

43-
// Wait for config changes to take effect
44-
ThisThread::sleep_for(3);
67+
printf("SELF TEST DONE \n");
4568

46-
uint16_t* temps = m_chips[i].getGpioPin(GpioSelection::k4);
47-
temperatures[j] = temps[j] / 10;
69+
std::array<uint16_t, BMS_BANK_COUNT * BMS_BANK_CELL_COUNT> allVoltages;
70+
std::array<std::optional<int8_t>, BMS_BANK_COUNT * BMS_BANK_TEMP_COUNT> allTemps;
71+
while (true) {
72+
m_bus.WakeupBus();
73+
74+
// Set all status lights high
75+
// TODO: This should be in some sort of config class
76+
uint8_t statusOn[6] = { 0x78, 0x00, 0x00, 0x00, 0x00, 0x00 };
77+
uint8_t statusOff[6] = { 0xf8, 0x00, 0x00, 0x00, 0x00, 0x00 };
78+
auto ledCmd = LTC681xBus::BuildBroadcastBusCommand(WriteConfigurationGroupA());
79+
m_bus.SendDataCommand(ledCmd, statusOn);
80+
81+
// Start ADC on all chips
82+
auto startAdcCmd = StartCellVoltageADC(AdcMode::k7k, false, CellSelection::kAll);
83+
if(m_bus.SendCommand(LTC681xBus::BuildBroadcastBusCommand(startAdcCmd)) != LTC681xBus::LTC681xBusStatus::Ok) {
84+
printf("Things are not okay. StartADC\n");
85+
}
4886

49-
delete temps;
87+
// Read back values from all chips
88+
for (int i = 0; i < BMS_BANK_COUNT; i++) {
89+
if(m_bus.PollAdcCompletion(LTC681xBus::BuildAddressedBusCommand(PollADCStatus(), 0)) == LTC681xBus::LTC681xBusStatus::PollTimeout) {
90+
printf("Poll timeout.\n");
91+
} else {
92+
printf("Poll OK.\n");
5093
}
5194

52-
// Turn off status LED
53-
conf.gpio5 = LTC6811::GPIOOutputState::kHigh;
54-
m_chips[i].updateConfig();
95+
uint16_t rawVoltages[12];
96+
if(m_bus.SendReadCommand(LTC681xBus::BuildAddressedBusCommand(ReadCellVoltageGroupA(), i), (uint8_t*)rawVoltages) != LTC681xBus::LTC681xBusStatus::Ok) {
97+
printf("Things are not okay. VoltageA\n");
98+
}
99+
if(m_bus.SendReadCommand(LTC681xBus::BuildAddressedBusCommand(ReadCellVoltageGroupB(), i), (uint8_t*)rawVoltages + 6) != LTC681xBus::LTC681xBusStatus::Ok) {
100+
printf("Things are not okay. VoltageB\n");
101+
}
102+
if(m_bus.SendReadCommand(LTC681xBus::BuildAddressedBusCommand(ReadCellVoltageGroupC(), i), (uint8_t*)rawVoltages + 12) != LTC681xBus::LTC681xBusStatus::Ok) {
103+
printf("Things are not okay. VoltageC\n");
104+
}
105+
if(m_bus.SendReadCommand(LTC681xBus::BuildAddressedBusCommand(ReadCellVoltageGroupD(), i), (uint8_t*)rawVoltages + 18) != LTC681xBus::LTC681xBusStatus::Ok) {
106+
printf("Things are not okay. VoltageD\n");
107+
}
55108

56-
//
57-
// Process values
58-
//
59109
for (int j = 0; j < 12; j++) {
60-
uint16_t voltage = voltages[j] / 10;
110+
// Endianness of the protocol allows a simple cast :-)
111+
uint16_t voltage = rawVoltages[j] / 10;
61112

62113
int index = BMS_CELL_MAP[j];
63114
if (index != -1) {
64115
allVoltages[(BMS_BANK_CELL_COUNT * i) + index] = voltage;
65116
}
66117
}
67-
68-
for (unsigned int j = 0; j < BMS_BANK_TEMP_COUNT; j++) {
69-
auto temp = convertTemp(temperatures[j]);
70-
allTemps[(BMS_BANK_TEMP_COUNT * i) + j] = temp;
71-
}
72-
73-
delete voltages;
74118
}
75119

120+
m_bus.SendDataCommand(ledCmd, statusOff);
121+
76122
for(auto mailbox : mailboxes) {
77123
if(!mailbox->full()) {
78124
{
79125
auto msg = new VoltageMeasurement();
80126
msg->voltageValues = allVoltages;
81127
mailbox->put((BmsEvent*) msg);
82128
}
129+
/*
83130
{
84131
auto msg = new TemperatureMeasurement();
85132
msg->temperatureValues = allTemps;
86133
mailbox->put((BmsEvent*) msg);
87134
}
135+
*/
88136
}
89137
}
138+
139+
ThisThread::sleep_for(100);
90140
}
91141
}
92142

bms/src/BmsThread.h

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -16,13 +16,13 @@
1616

1717
#include "EnergusTempSensor.h"
1818
#include "LTC6811.h"
19-
#include "LTC6811Bus.h"
19+
#include "LTC681xBus.h"
2020
#include "Event.h"
2121

2222
class BMSThread {
2323
public:
2424

25-
BMSThread(LTC6811Bus* bus, unsigned int frequency, std::vector<BmsEventMailbox*> mailboxes);
25+
BMSThread(LTC681xBus& bus, unsigned int frequency, std::vector<BmsEventMailbox*> mailboxes);
2626

2727
// Function to allow for starting threads from static context
2828
static void startThread(BMSThread *p) {
@@ -31,7 +31,7 @@ class BMSThread {
3131

3232
private:
3333
unsigned int m_delay;
34-
LTC6811Bus* m_bus;
34+
LTC681xBus& m_bus;
3535
std::vector<LTC6811> m_chips;
3636
std::vector<BmsEventMailbox*> mailboxes;
3737

bms/src/LTC6811.cpp

Lines changed: 23 additions & 23 deletions
Original file line numberDiff line numberDiff line change
@@ -3,9 +3,9 @@
33
#include "mbed.h"
44
#include "rtos.h"
55

6-
#include "LTC6811Bus.h"
6+
#include "LTC681xParallelBus.h"
77

8-
LTC6811::LTC6811(LTC6811Bus &bus, uint8_t id) : m_bus(bus), m_id(id) {
8+
LTC6811::LTC6811(LTC681xBus &bus, uint8_t id) : m_bus(bus), m_id(id) {
99
m_config =
1010
Configuration{.gpio5 = GPIOOutputState::kPassive,
1111
.gpio4 = GPIOOutputState::kPassive,
@@ -24,14 +24,14 @@ LTC6811::LTC6811(LTC6811Bus &bus, uint8_t id) : m_bus(bus), m_id(id) {
2424
void LTC6811::updateConfig() {
2525
// Create configuration data to write
2626
uint8_t config[6];
27-
config[0] = (uint8_t)m_config.gpio5 << 7
28-
| (uint8_t)m_config.gpio4 << 6
29-
| (uint8_t)m_config.gpio3 << 5
30-
| (uint8_t)m_config.gpio2 << 4
31-
| (uint8_t)m_config.gpio1 << 3
32-
| (uint8_t)m_config.referencePowerOff << 2
33-
| (uint8_t)m_config.dischargeTimerEnabled << 1
34-
| (uint8_t)m_config.adcMode;
27+
config[0] = (uint8_t) m_config.gpio5 << 7
28+
| (uint8_t) m_config.gpio4 << 6
29+
| (uint8_t) m_config.gpio3 << 5
30+
| (uint8_t) m_config.gpio2 << 4
31+
| (uint8_t) m_config.gpio1 << 3
32+
| (uint8_t) m_config.referencePowerOff << 2
33+
| (uint8_t) m_config.dischargeTimerEnabled << 1
34+
| (uint8_t) m_config.adcMode;
3535
config[1] = m_config.undervoltageComparison & 0xFF;
3636
config[2] = ((m_config.undervoltageComparison >> 8) & 0x0F)
3737
| (((uint8_t)m_config.overvoltageComparison & 0x0F) << 4);
@@ -40,27 +40,27 @@ void LTC6811::updateConfig() {
4040
config[5] = (((uint8_t)m_config.dischargeTimeout & 0x0F) << 4)
4141
| ((m_config.dischargeState.value >> 8) & 0x0F);
4242

43-
LTC6811Bus::Command cmd = LTC6811Bus::buildAddressedCommand(m_id, WriteConfigurationGroupA());
43+
auto cmd = LTC681xBus::BuildAddressedBusCommand(WriteConfigurationGroupA(), m_id);
4444

45-
m_bus.sendCommandWithData(cmd, config);
45+
m_bus.SendDataCommand(cmd, config);
4646
}
4747

4848
LTC6811::Configuration &LTC6811::getConfig() { return m_config; }
4949

5050
uint16_t *LTC6811::getVoltages() {
5151
auto cmd = StartCellVoltageADC(AdcMode::k7k, false, CellSelection::kAll);
52-
m_bus.sendCommand(LTC6811Bus::buildAddressedCommand(m_id, cmd));
52+
m_bus.SendCommand(LTC681xBus::BuildAddressedBusCommand(cmd, m_id));
5353

5454
// Wait 2 ms for ADC to finish
5555
ThisThread::sleep_for(2); // TODO: Change
5656

5757
// 4 * (Register of 6 Bytes + PEC)
5858
uint8_t rxbuf[8 * 4];
5959

60-
m_bus.readCommand(LTC6811Bus::buildAddressedCommand(m_id, ReadCellVoltageGroupA()), rxbuf);
61-
m_bus.readCommand(LTC6811Bus::buildAddressedCommand(m_id, ReadCellVoltageGroupB()), rxbuf + 8);
62-
m_bus.readCommand(LTC6811Bus::buildAddressedCommand(m_id, ReadCellVoltageGroupC()), rxbuf + 16);
63-
m_bus.readCommand(LTC6811Bus::buildAddressedCommand(m_id, ReadCellVoltageGroupD()), rxbuf + 24);
60+
m_bus.SendReadCommand(LTC681xBus::BuildAddressedBusCommand(ReadCellVoltageGroupA(), m_id), rxbuf);
61+
m_bus.SendReadCommand(LTC681xBus::BuildAddressedBusCommand(ReadCellVoltageGroupB(), m_id), rxbuf + 8);
62+
m_bus.SendReadCommand(LTC681xBus::BuildAddressedBusCommand(ReadCellVoltageGroupC(), m_id), rxbuf + 16);
63+
m_bus.SendReadCommand(LTC681xBus::BuildAddressedBusCommand(ReadCellVoltageGroupD(), m_id), rxbuf + 24);
6464

6565
// Voltage = val • 100μV
6666
uint16_t *voltages = new uint16_t[12];
@@ -80,15 +80,15 @@ uint16_t *LTC6811::getVoltages() {
8080

8181
uint16_t *LTC6811::getGpio() {
8282
auto cmd = StartGpioADC(AdcMode::k7k, GpioSelection::kAll);
83-
m_bus.sendCommand(LTC6811Bus::buildAddressedCommand(m_id, cmd));
83+
m_bus.SendCommand(LTC681xBus::BuildAddressedBusCommand(cmd, m_id));
8484

8585
// Wait 15 ms for ADC to finish
8686
ThisThread::sleep_for(5); // TODO: This could be done differently
8787

8888
uint8_t rxbuf[8 * 2];
8989

90-
m_bus.readCommand(LTC6811Bus::buildAddressedCommand(m_id, ReadAuxiliaryGroupA()), rxbuf);
91-
m_bus.readCommand(LTC6811Bus::buildAddressedCommand(m_id, ReadAuxiliaryGroupB()), rxbuf + 8);
90+
m_bus.SendReadCommand(LTC681xBus::BuildAddressedBusCommand(ReadAuxiliaryGroupA(), m_id), rxbuf);
91+
m_bus.SendReadCommand(LTC681xBus::BuildAddressedBusCommand(ReadAuxiliaryGroupB(), m_id), rxbuf + 8);
9292

9393
uint16_t *voltages = new uint16_t[5];
9494

@@ -108,15 +108,15 @@ uint16_t *LTC6811::getGpio() {
108108

109109
uint16_t *LTC6811::getGpioPin(GpioSelection pin) {
110110
auto cmd = StartGpioADC(AdcMode::k7k, pin);
111-
m_bus.sendCommand(LTC6811Bus::buildAddressedCommand(m_id, cmd));
111+
m_bus.SendCommand(LTC681xBus::BuildAddressedBusCommand(cmd, m_id));
112112

113113
// Wait 5 ms for ADC to finish
114114
ThisThread::sleep_for(pin == GpioSelection::kAll ? 15 : 5); // TODO: Change to polling
115115

116116
uint8_t rxbuf[8 * 2];
117117

118-
m_bus.readCommand(LTC6811Bus::buildAddressedCommand(m_id, ReadAuxiliaryGroupA()), rxbuf);
119-
m_bus.readCommand(LTC6811Bus::buildAddressedCommand(m_id, ReadAuxiliaryGroupB()), rxbuf + 8);
118+
m_bus.SendReadCommand(LTC681xBus::BuildAddressedBusCommand(ReadAuxiliaryGroupA(), m_id), rxbuf);
119+
m_bus.SendReadCommand(LTC681xBus::BuildAddressedBusCommand(ReadAuxiliaryGroupB(), m_id), rxbuf + 8);
120120

121121
uint16_t *voltages = new uint16_t[5];
122122

0 commit comments

Comments
 (0)