Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 2 additions & 2 deletions BMS/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -39,8 +39,8 @@ add_executable(BMS src/main.cpp
src/EnergusTempSensor.cpp
src/EnergusTempSensor.h
src/Event.h
src/LTC6811.h
src/LTC6811.cpp
src/LTC6810.h
src/LTC6810.cpp
src/StateOfCharge.cpp
src/DS18B20.cpp
)
Expand Down
41 changes: 25 additions & 16 deletions BMS/src/BmsThread.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -9,10 +9,12 @@

#include "EnergusTempSensor.h"

#include "LTC6810.h"

BMSThread::BMSThread(LTC681xBus &bus, unsigned int frequency, BmsEventMailbox* bmsEventMailbox, MainToBMSMailbox* mainToBMSMailbox)
: m_bus(bus), bmsEventMailbox(bmsEventMailbox), mainToBMSMailbox(mainToBMSMailbox) {
for (int i = 0; i < BMS_BANK_COUNT; i++) {
m_chips.push_back(LTC6811(bus, i));
m_chips.push_back(LTC6810(bus, i));
}
for (int i = 0; i < BMS_BANK_COUNT; i++) {
// m_chips[i].getConfig().gpio5 = LTC6811::GPIOOutputState::kLow;
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

See my comment below; the change to GPIOOutputState::kHigh gpio configs should be done here (in the constructor of BMSThread, where the LTC6811's are created) rather than in the default constructor of the LTC6811

Expand Down Expand Up @@ -119,6 +121,13 @@ void BMSThread::threadWorker() {
charging = mainToBMSEvent->charging;// assign charging to mainToBMSEvent
// that is assigned the value held by charging
// printf("Balance Allowed: %x\nCharging: %x\n", balanceAllowed, charging);
if (mainToBMSEvent->readI2CTemp) {
// Read temperature from I2C sensor on each bank
for (int i = 0; i < BMS_BANK_COUNT; i++) {
float temp = m_chips[i].readTemperatureTMP1075();
printf("Bank %d I2C Temperature: %.2f°C\n", i, temp);
}
}
delete mainToBMSEvent; // deallocate memory that was previously allocated dynamically to mainToBMSEvent
}

Expand All @@ -130,14 +139,14 @@ void BMSThread::threadWorker() {
// TODO: This should be in some sort of config class

for (int i = 0; i < BMS_BANK_COUNT; i++) {
LTC6811::Configuration &config = m_chips[i].getConfig();
config.gpio5 = LTC6811::GPIOOutputState::kLow;
LTC6810::Configuration &config = m_chips[i].getConfig();
config.gpio5 = LTC6810::GPIOOutputState::kLow;
m_chips[i].updateConfig();
}

// turn off cell balancing for voltage reading
for (int i = 0; i < BMS_BANK_COUNT; i++) {
LTC6811::Configuration &config = m_chips[i].getConfig();
LTC6810::Configuration &config = m_chips[i].getConfig();

config.dischargeState.value = 0x0000;

Expand Down Expand Up @@ -207,14 +216,14 @@ void BMSThread::threadWorker() {
for (uint8_t j = 0; j < BMS_BANK_CELL_COUNT; j++) {
for (int i = 0; i < BMS_BANK_COUNT; i++) {
// set the GPIOs for the segment we are looking at to the cell # we are getting temperature for
LTC6811::Configuration &config = m_chips[i].getConfig();
config.gpio1 = (j & 0b001) ? LTC6811::GPIOOutputState::kHigh
: LTC6811::GPIOOutputState::kLow;
config.gpio2 = ((j & 0b010) >> 1) ? LTC6811::GPIOOutputState::kHigh
: LTC6811::GPIOOutputState::kLow;
config.gpio3 = ((j & 0b100) >> 2) ? LTC6811::GPIOOutputState::kHigh
: LTC6811::GPIOOutputState::kLow;
config.gpio4 = LTC6811::GPIOOutputState::kPassive;
LTC6810::Configuration &config = m_chips[i].getConfig();
config.gpio1 = (j & 0b001) ? LTC6810::GPIOOutputState::kHigh
: LTC6810::GPIOOutputState::kLow;
config.gpio2 = ((j & 0b010) >> 1) ? LTC6810::GPIOOutputState::kHigh
: LTC6810::GPIOOutputState::kLow;
config.gpio3 = ((j & 0b100) >> 2) ? LTC6810::GPIOOutputState::kHigh
: LTC6810::GPIOOutputState::kLow;
config.gpio4 = LTC6810::GPIOOutputState::kPassive;

m_chips[i].updateConfig();

Expand Down Expand Up @@ -337,7 +346,7 @@ void BMSThread::threadWorker() {
if (bmsState == BMSThreadState::BMSIdle && balanceAllowed) {
for (int i = 0; i < BMS_BANK_COUNT; i++) {

LTC6811::Configuration &config = m_chips[i].getConfig();
LTC6810::Configuration &config = m_chips[i].getConfig();

uint16_t dischargeValue = 0x0000;

Expand All @@ -364,15 +373,15 @@ void BMSThread::threadWorker() {
} else {
for (int i = 0; i < BMS_BANK_COUNT; i++) {

LTC6811::Configuration &config = m_chips[i].getConfig();
LTC6810::Configuration &config = m_chips[i].getConfig();
config.dischargeState.value = 0x0000;
m_chips[i].updateConfig();
}
}

for (int i = 0; i < BMS_BANK_COUNT; i++) {
LTC6811::Configuration &config = m_chips[i].getConfig();
config.gpio5 = LTC6811::GPIOOutputState::kLow;
LTC6810::Configuration &config = m_chips[i].getConfig();
config.gpio5 = LTC6810::GPIOOutputState::kLow;
m_chips[i].updateConfig();
}

Expand Down
5 changes: 3 additions & 2 deletions BMS/src/BmsThread.h
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,7 @@
//#include "Can.h"

#include "EnergusTempSensor.h"
#include "LTC6811.h"
#include "LTC6810.h"
#include "LTC681xBus.h"
#include "Event.h"

Expand All @@ -32,8 +32,9 @@ class BMSThread {
private:
bool balanceAllowed = false;
bool charging = false;
bool readI2CTemp;
LTC681xBus& m_bus;
std::vector<LTC6811> m_chips;
std::vector<LTC6810> m_chips;
BmsEventMailbox* bmsEventMailbox;
MainToBMSMailbox* mainToBMSMailbox;

Expand Down
1 change: 1 addition & 0 deletions BMS/src/Event.h
Original file line number Diff line number Diff line change
Expand Up @@ -34,6 +34,7 @@ class MainToBMSEvent {
public:
bool balanceAllowed = false;
bool charging = false;
bool readI2CTemp;
};

static constexpr auto mailboxSize = 4;
Expand Down
109 changes: 94 additions & 15 deletions BMS/src/LTC6811.cpp → BMS/src/LTC6810.cpp
Original file line number Diff line number Diff line change
@@ -1,16 +1,19 @@
#include "LTC6811.h"
#include "LTC6810.h"
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@meghanabaddipudireddy Instead of renaming/replacing the LTC6811 class with the LTC6810 class, could you keep them both but as separate files? This should be fairly straightforward since you still have the LTC6811 version in the main branch. Reasoning being that we will very likely want to test this TMP1075 code on an old spare fs-3 BMS board and acc board, which uses the LTC6811, but we'll use the LTC6810 for fs-4's bms, so we should be ready to use both at any time.


#include "mbed.h"
#include "rtos.h"

#include "LTC681xParallelBus.h"

LTC6811::LTC6811(LTC681xBus &bus, uint8_t id) : m_bus(bus), m_id(id) {
#define TMP1075_I2C_ADDR 0x48
#define TMP1075_TEMP_REG 0x00
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

These #defines should be removed, since they are only true for some configurations of the TMP1075 (eg. 0x48 is the I2C address for a sensor where all three adress pins A0/A1/A2 are pulled low, but we will have multiple configurations). We will need to use many different TMP1075s with different I2C addresses.

Instead, they should be made parameters to LTC6810::readTemperatureTMP1075().


LTC6810::LTC6810(LTC681xBus &bus, uint8_t id) : m_bus(bus), m_id(id) {
m_config =
Configuration{.gpio5 = GPIOOutputState::kPassive,
.gpio4 = GPIOOutputState::kPassive,
.gpio3 = GPIOOutputState::kPassive,
.gpio2 = GPIOOutputState::kPassive,
.gpio4 = GPIOOutputState::kHigh,
.gpio3 = GPIOOutputState::kHigh,
.gpio2 = GPIOOutputState::kHigh,
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think GPIOOutputState::kPassive is probably the correct default for the LTC6811 class, and these changes to GPIOOutputState::kHigh should be moved to where we construct the class, in BMSThread's constructor. See my comment above in BMSThread

.gpio1 = GPIOOutputState::kPassive,
.referencePowerOff = ReferencePowerOff::kAfterConversions,
.dischargeTimerEnabled = DischargeTimerEnable::kDisabled,
Expand All @@ -21,7 +24,7 @@ LTC6811::LTC6811(LTC681xBus &bus, uint8_t id) : m_bus(bus), m_id(id) {
.dischargeTimeout = DischargeTimeoutValue::kDisabled};
}

void LTC6811::updateConfig() {
void LTC6810::updateConfig() {
// Create configuration data to write
uint8_t config[6];
config[0] = (uint8_t) m_config.gpio5 << 7
Expand All @@ -45,25 +48,24 @@ void LTC6811::updateConfig() {
m_bus.SendDataCommand(cmd, config);
}

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

uint16_t *LTC6811::getVoltages() {
uint16_t *LTC6810::getVoltages() {
auto cmd = StartCellVoltageADC(AdcMode::k7k, false, CellSelection::kAll);
m_bus.SendCommand(LTC681xBus::BuildAddressedBusCommand(cmd, m_id));

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

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

m_bus.SendReadCommand(LTC681xBus::BuildAddressedBusCommand(ReadCellVoltageGroupA(), m_id), rxbuf);
m_bus.SendReadCommand(LTC681xBus::BuildAddressedBusCommand(ReadCellVoltageGroupB(), m_id), rxbuf + 8);
m_bus.SendReadCommand(LTC681xBus::BuildAddressedBusCommand(ReadCellVoltageGroupC(), m_id), rxbuf + 16);
m_bus.SendReadCommand(LTC681xBus::BuildAddressedBusCommand(ReadCellVoltageGroupD(), m_id), rxbuf + 24);


// Voltage = val • 100μV
uint16_t *voltages = new uint16_t[12];
uint16_t *voltages = new uint16_t[6];
for (unsigned int i = 0; i < sizeof(rxbuf); i++) {
// Skip over PEC
if (i % 8 == 6 || i % 8 == 7) continue;
Expand All @@ -78,7 +80,7 @@ uint16_t *LTC6811::getVoltages() {
return voltages;
}

uint16_t *LTC6811::getGpio() {
uint16_t *LTC6810::getGpio() {
auto cmd = StartGpioADC(AdcMode::k7k, GpioSelection::kAll);
m_bus.SendCommand(LTC681xBus::BuildAddressedBusCommand(cmd, m_id));

Expand Down Expand Up @@ -106,7 +108,7 @@ uint16_t *LTC6811::getGpio() {
return voltages;
}

uint16_t *LTC6811::getGpioPin(GpioSelection pin) {
uint16_t *LTC6810::getGpioPin(GpioSelection pin) {
auto cmd = StartGpioADC(AdcMode::k7k, pin);
m_bus.SendCommand(LTC681xBus::BuildAddressedBusCommand(cmd, m_id));

Expand All @@ -132,4 +134,81 @@ uint16_t *LTC6811::getGpioPin(GpioSelection pin) {
}

return voltages;
}
}

void LTC6810::buildCOMMBytes(uint8_t icom, uint8_t fcom, uint8_t data, uint8_t *commBytes) {
// COMMn (even byte): Upper 4 bits = ICOM, Lower 4 bits = upper half of data
commBytes[0] = (icom << 4) | ((data >> 4) & 0x0F);

// COMMn+1 (odd byte): Upper 4 bits = lower half of data, Lower 4 bits = FCOM
commBytes[1] = ((data & 0x0F) << 4) | fcom;
}

float LTC6810::readTemperatureTMP1075() {
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Eventually we should probably try to decouple the TMP1075 I2C register logic from the LTC6811 I2C COMM group logic, in case we want to use the I2C for something else. But its alright for now, until we get it working

uint8_t commData[6];
uint8_t rxData[8];
uint8_t tempBytes[2];

buildCOMMBytes(0x6, 0x0, (TMP1075_I2C_ADDR << 1) | 0x00, tempBytes);
commData[0] = tempBytes[0]; // COMM0
commData[1] = tempBytes[1]; // COMM1

buildCOMMBytes(0x0, 0x0, TMP1075_TEMP_REG, tempBytes);
commData[2] = tempBytes[0]; // COMM2
commData[3] = tempBytes[1]; // COMM3

buildCOMMBytes(0x1, 0x0, 0x00, tempBytes);
commData[4] = tempBytes[0]; // COMM4
commData[5] = tempBytes[1]; // COMM5

auto wrCmd = LTC681xBus::BuildAddressedBusCommand(WriteCommGroup(), m_id);
m_bus.SendDataCommand(wrCmd, commData);

auto stCmd = LTC681xBus::BuildAddressedBusCommand(StartComm(), m_id);
m_bus.SendCommand(stCmd);

ThisThread::sleep_for(3ms);

buildCOMMBytes(0x6, 0x0, (TMP1075_I2C_ADDR << 1) | 0x01, tempBytes);
commData[0] = tempBytes[0]; // COMM0
commData[1] = tempBytes[1]; // COMM1


buildCOMMBytes(0x0, 0x0, 0xFF, tempBytes);
commData[2] = tempBytes[0]; // COMM2
commData[3] = tempBytes[1]; // COMM3

buildCOMMBytes(0x0, 0x9, 0xFF, tempBytes);
commData[4] = tempBytes[0]; // COMM4
commData[5] = tempBytes[1]; // COMM5

m_bus.SendDataCommand(wrCmd, commData);
m_bus.SendCommand(stCmd);

ThisThread::sleep_for(3ms);

auto rdCmd = LTC681xBus::BuildAddressedBusCommand(ReadCommGroup(), m_id);
m_bus.SendReadCommand(rdCmd, rxData);

uint8_t tempMSB = ((rxData[2] & 0x0F) << 4) | ((rxData[3] >> 4) & 0x0F);

uint8_t tempLSB = ((rxData[4] & 0x0F) << 4) | ((rxData[5] >> 4) & 0x0F);

int16_t rawTemp = (tempMSB << 8) | tempLSB;

float temperature = (rawTemp >> 4) * 0.0625f;

return temperature;
}

bool LTC6810::verifyI2CStatus(uint8_t *rxData) {
uint8_t data1 = ((rxData[2] & 0x0F) << 4) | ((rxData[3] >> 4) & 0x0F);
uint8_t data2 = ((rxData[4] & 0x0F) << 4) | ((rxData[5] >> 4) & 0x0F);

if (data1 == 0xFF && data2 == 0xFF) {
return false; // No response from sensor
}

return true;
}

10 changes: 6 additions & 4 deletions BMS/src/LTC6811.h → BMS/src/LTC6810.h
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@

#include <LTC681xParallelBus.h>

class LTC6811 {
class LTC6810 {
public:
enum class GPIOOutputState : uint8_t {
// States with pull up resistor
Expand All @@ -20,8 +20,7 @@ class LTC6811 {
enum class AdcModeOption : uint8_t { kDefault = 0, kLowSpeed = 1 };
union DischargeState {
struct {
uint8_t cell12 : 1, cell11 : 1, cell10 : 1, cell9 : 1, cell8 : 1,
cell7 : 1, cell6 : 1, cell5 : 1, cell4 : 1, cell3 : 1, cell2 : 1,
uint8_t cell6 : 1, cell5 : 1, cell4 : 1, cell3 : 1, cell2 : 1,
cell1 : 1;
};
uint16_t value;
Expand Down Expand Up @@ -63,13 +62,16 @@ class LTC6811 {
DischargeTimeoutValue dischargeTimeout;
};

LTC6811(LTC681xBus &bus, uint8_t id);
LTC6810(LTC681xBus &bus, uint8_t id);
Configuration &getConfig();
void updateConfig();

uint16_t *getVoltages();
uint16_t *getGpio();
uint16_t *getGpioPin(GpioSelection pin);
void buildCOMMBytes(uint8_t icom, uint8_t fcom, uint8_t data, uint8_t *commBytes);
float readTemperatureTMP1075();
bool verifyI2CStatus(uint8_t *rxData);
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

These functions should be static if they're gonna be in the LTC6811/LTC6810 class, since they don't act on any of the data of the instance of LTC6811/LTC6810.


private:
LTC681xBus &m_bus;
Expand Down
17 changes: 17 additions & 0 deletions BMS/src/main.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -118,13 +118,30 @@ int main() {
Timer soc_timer;
t.start(); // start timer
soc_timer.start();

uint32_t last_i2c_temp_read = 0;

int32_t capacityDischarged = -1;
while (true) {
// infinite loop
glvVoltage = (uint16_t)(glv_voltage_pin * 185.3); // Read voltage from glv_voltage_pin and convert it to mV
status_message.glv_voltage = glvVoltage;
// printf("GLV voltage: %d mV\n", glvVoltage * 100);
// capacity initialization using the voltage lookup table

uint32_t current_time = t.read_ms();
// read I2C temperature
if (current_time - last_i2c_temp_read >= 1000) { // Every 1 second
if (!mainToBMSMailbox->full()) {
MainToBMSEvent* tempEvent = new MainToBMSEvent();
tempEvent->balanceAllowed = shutdown_measure_pin;
tempEvent->charging = isCharging;
tempEvent->readI2CTemp = true; // Request temperature reading
mainToBMSMailbox->put(tempEvent);
}
last_i2c_temp_read = current_time;
}

while (!bmsMailbox->empty()) {
// while the bmsMailbox is not empty
BmsEvent* bmsEvent; // create bms event pointer
Expand Down