Thanks to visit codestin.com
Credit goes to github.com

Skip to content

Conversation

@ManushPatell
Copy link
Contributor

Just wanted to make the initial set up with Harsh on call. I'm going to grind through this after wednesday but he has time right now so I wanted to show him the functions on the datasheets and a template to work on.

Copy link
Contributor

@BlakeFreer BlakeFreer left a comment

Choose a reason for hiding this comment

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

🫎

Copy link
Contributor

@BlakeFreer BlakeFreer left a comment

Choose a reason for hiding this comment

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

compiler error

@ManushPatell ManushPatell marked this pull request as draft October 28, 2025 17:19
@ManushPatell ManushPatell marked this pull request as ready for review October 30, 2025 04:28
@BlakeFreer BlakeFreer marked this pull request as draft November 2, 2025 17:48
@ManushPatell
Copy link
Contributor Author

I've written out the command codes that were on the 2950B datasheet. I know some codes have multiple versions where some include ADBMS: 6380B Compatible. 6830 seems to be a multicell battery stack monitor which we don't have so I think we can ignore those.

When writing the implementation of each command code, I strongly urge to recheck my hex conversion because there's a chance that 1/52 codes are wrong by 1 or more bits. Additionally, the codes ADI1, AD2, ADV are a little more complex. I've asked Sharvin to tackle this. @HarshPatel08, I think we can start to implement some of these functions now!

@ManushPatell
Copy link
Contributor Author

A problem I've faced is what happens if the BMS ignores a command or write function. We've implemented the CCNT (Counter), that tracks the number of write/command functions that have been successfully received by the BMS. Whenever, a read function is performed, we check if our CCNT count is equal to what the bms is sending back.

This is all great until we actually get an offset of 1 or more between the expected and actual value. In that case it will always be false, possibly flooding our CAN bus (I'm assuming we'll be creating CAN messages for this). We can send the message and offset it back, is that the best practice here? Any inputs? @BlakeFreer @HarshPatel08

@BlakeFreer
Copy link
Contributor

BlakeFreer commented Dec 21, 2025

Is CCNT a concept that you created? I don't see why it's needed. Everything is communicated over SPI/isoSPI (not CAN). Unlike CAN, SPI is an extremely reliable protocol.

You can assume that every command succeeds. When you start testing the actual hardware, either that assumption will be proved correct or you'll know what failures actually need detecting

return true;
}

uint16_t LvBms::commandPec15(const uint8_t* data, int len) const {
Copy link
Contributor

Choose a reason for hiding this comment

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

Nice bit wise implementation. this is how CRC circuits work in hardware, but software implementations usually use a lookup table method since it's far more efficient for a CPU

https://en.wikipedia.org/wiki/Computation_of_cyclic_redundancy_checks

This website can generate the CRC table for lots of polynomials. I'm assuming (but not 100% sure) that your particular CRC is there
https://crccalc.com/?crc=123456789&method=&datatype=ascii&outtype=hex

If it doesn't include your CRC, keep your current implementation

}

void LvBms::freezeResultRegisters() {
std::array<uint8_t, 2> cmd =
Copy link
Contributor

@BlakeFreer BlakeFreer Dec 21, 2025

Choose a reason for hiding this comment

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

It looks like you always call split_message and pass the uint8 array into sendControlCmd. I think a better division of the abstraction would be just to pass the command enum into sendControlCmd and do the splitting internally. This would make most of your command functions super simple, just calling sendControlCmd(enum_value)

Since this makes each command functions trivial, you may decide to remove all of the class methods which are just command names and let the user call lvbms.sendCommand(enum_value).

@ManushPatell
Copy link
Contributor Author

Is CCNT a concept that you created? I don't see why it's needed. Everything is communicated over SPI/isoSPI (not CAN). Unlike CAN, SPI is an extremely reliable protocol.

You can assume that every command succeeds. When you start testing the actual hardware, either that assumption will be proved correct or you'll know what failures actually need detecting

It isn't something I created. It's used in the data-sheet, where write/command calls should increment the count, read should compare the counts and reset/startup calls should set the value back to 0. I think it's pretty useful to find if something is consistently dismissed by the BMS but beyond that point, it's hard to tell which function call is being dismissed if it's an irregular event

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

4 participants