inital structure for bms communication protocol implemented
This commit is contained in:
Generated
+3
@@ -535,6 +535,9 @@ dependencies = [
|
|||||||
[[package]]
|
[[package]]
|
||||||
name = "lib-bms-protocol"
|
name = "lib-bms-protocol"
|
||||||
version = "0.1.0"
|
version = "0.1.0"
|
||||||
|
dependencies = [
|
||||||
|
"embedded-hal 1.0.0",
|
||||||
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "litrs"
|
name = "litrs"
|
||||||
|
|||||||
@@ -4,6 +4,7 @@ version = "0.1.0"
|
|||||||
edition = "2024"
|
edition = "2024"
|
||||||
|
|
||||||
[dependencies]
|
[dependencies]
|
||||||
|
embedded-hal = "1.0.0"
|
||||||
|
|
||||||
|
|
||||||
[profile.dev]
|
[profile.dev]
|
||||||
|
|||||||
+169
-8
@@ -1,29 +1,190 @@
|
|||||||
#![no_std]
|
#![no_std]
|
||||||
|
|
||||||
|
use embedded_hal::i2c::{I2c, Operation, SevenBitAddress};
|
||||||
|
|
||||||
|
pub const BMS_I2C_ADDRESS: u8 = 0x55;
|
||||||
|
|
||||||
|
pub trait BmsReadable {
|
||||||
|
fn read_from_i2c<I>(i2c_dev: &mut I) -> Result<Self, BmsProtocolError>
|
||||||
|
where
|
||||||
|
Self: Sized,
|
||||||
|
I: I2c<SevenBitAddress>;
|
||||||
|
}
|
||||||
|
|
||||||
|
pub trait BmsWriteable {
|
||||||
|
fn write_to_device<I>(&self, i2c_dev: &mut I) -> Result<(), BmsProtocolError>
|
||||||
|
where
|
||||||
|
I: I2c<SevenBitAddress>;
|
||||||
|
}
|
||||||
|
|
||||||
|
pub enum BmsProtocolError {
|
||||||
|
I2cCommunicationError,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl<E> From<E> for BmsProtocolError
|
||||||
|
where
|
||||||
|
E: embedded_hal::i2c::Error,
|
||||||
|
{
|
||||||
|
fn from(_value: E) -> Self {
|
||||||
|
Self::I2cCommunicationError
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#[derive(Debug)]
|
||||||
|
pub struct BmsSoftwareReset;
|
||||||
|
|
||||||
|
impl BmsWriteable for BmsSoftwareReset {
|
||||||
|
fn write_to_device<I>(&self, i2c_dev: &mut I) -> Result<(), BmsProtocolError>
|
||||||
|
where
|
||||||
|
I: I2c<SevenBitAddress>,
|
||||||
|
{
|
||||||
|
i2c_dev.write(
|
||||||
|
BMS_I2C_ADDRESS,
|
||||||
|
&(BmsRegisterMap::Reset as u32).to_be_bytes(),
|
||||||
|
)?;
|
||||||
|
Ok(())
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
#[derive(Debug)]
|
#[derive(Debug)]
|
||||||
#[repr(transparent)]
|
#[repr(transparent)]
|
||||||
pub struct Version(u32);
|
pub struct ProtocolVersion(u32);
|
||||||
|
|
||||||
|
impl BmsReadable for ProtocolVersion {
|
||||||
|
fn read_from_i2c<I>(i2c_dev: &mut I) -> Result<Self, BmsProtocolError>
|
||||||
|
where
|
||||||
|
Self: Sized,
|
||||||
|
I: I2c<SevenBitAddress>,
|
||||||
|
{
|
||||||
|
let cmd = BmsRegisterMap::ProtocolVersion;
|
||||||
|
let mut version: [u8; 4] = [0x00; 4];
|
||||||
|
i2c_dev.transaction(
|
||||||
|
BMS_I2C_ADDRESS,
|
||||||
|
&mut [
|
||||||
|
Operation::Write(&(cmd as u32).to_be_bytes()),
|
||||||
|
Operation::Read(&mut version),
|
||||||
|
],
|
||||||
|
)?;
|
||||||
|
Ok(ProtocolVersion(u32::from_be_bytes(version)))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#[derive(Debug)]
|
||||||
|
#[repr(transparent)]
|
||||||
|
pub struct FirmwareVersion(u32);
|
||||||
|
|
||||||
|
impl BmsReadable for FirmwareVersion {
|
||||||
|
fn read_from_i2c<I>(i2c_dev: &mut I) -> Result<Self, BmsProtocolError>
|
||||||
|
where
|
||||||
|
Self: Sized,
|
||||||
|
I: I2c<SevenBitAddress>,
|
||||||
|
{
|
||||||
|
let cmd = BmsRegisterMap::FirmwareVersion;
|
||||||
|
let mut version: [u8; 4] = [0x00; 4];
|
||||||
|
i2c_dev.transaction(
|
||||||
|
BMS_I2C_ADDRESS,
|
||||||
|
&mut [
|
||||||
|
Operation::Write(&(cmd as u32).to_be_bytes()),
|
||||||
|
Operation::Read(&mut version),
|
||||||
|
],
|
||||||
|
)?;
|
||||||
|
Ok(FirmwareVersion(u32::from_be_bytes(version)))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
#[derive(Debug)]
|
#[derive(Debug)]
|
||||||
pub struct Config {
|
pub struct Config {
|
||||||
pub capacity_mah: u32,
|
pub capacity_mah: u32,
|
||||||
pub v_full_mv: u32,
|
pub v_full_mv: u32,
|
||||||
pub v_empty_mv: u32,
|
pub v_empty_mv: u32,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
impl BmsReadable for Config {
|
||||||
|
fn read_from_i2c<I>(i2c_dev: &mut I) -> Result<Self, BmsProtocolError>
|
||||||
|
where
|
||||||
|
Self: Sized,
|
||||||
|
I: I2c<SevenBitAddress>,
|
||||||
|
{
|
||||||
|
let cmd = BmsRegisterMap::ConfigCapacityMilliAmpereHours;
|
||||||
|
let mut capacity_mah: [u8; 4] = [0x00; 4];
|
||||||
|
let mut v_full_mv: [u8; 4] = [0x00; 4];
|
||||||
|
let mut v_empty_mv: [u8; 4] = [0x00; 4];
|
||||||
|
i2c_dev.transaction(
|
||||||
|
BMS_I2C_ADDRESS,
|
||||||
|
&mut [
|
||||||
|
Operation::Write(&(cmd as u32).to_be_bytes()),
|
||||||
|
Operation::Read(&mut capacity_mah),
|
||||||
|
Operation::Read(&mut v_full_mv),
|
||||||
|
Operation::Read(&mut v_empty_mv),
|
||||||
|
],
|
||||||
|
)?;
|
||||||
|
Ok(Config {
|
||||||
|
capacity_mah: u32::from_be_bytes(capacity_mah),
|
||||||
|
v_full_mv: u32::from_be_bytes(v_full_mv),
|
||||||
|
v_empty_mv: u32::from_be_bytes(v_empty_mv),
|
||||||
|
})
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
#[derive(Debug, Clone, Copy)]
|
#[derive(Debug, Clone, Copy)]
|
||||||
pub struct BatteryState {
|
pub struct BatteryState {
|
||||||
pub lifetime_capacity_mah: u32,
|
pub lifetime_capacity_mah: u32,
|
||||||
pub remaining_capacity_mah: u32,
|
pub remaining_capacity_mah: u32,
|
||||||
pub current_mv: u16,
|
pub current_mv: u32,
|
||||||
pub temperature_celcius: i32,
|
pub temperature_celcius: i32,
|
||||||
pub health_percent: u8
|
pub health_percent: u32,
|
||||||
}
|
}
|
||||||
|
|
||||||
pub enum BmsCommand {
|
impl BmsReadable for BatteryState {
|
||||||
GetVersion,
|
fn read_from_i2c<I>(i2c_dev: &mut I) -> Result<Self, BmsProtocolError>
|
||||||
GetConfig,
|
where
|
||||||
GetBatteryState,
|
Self: Sized,
|
||||||
|
I: I2c<SevenBitAddress>,
|
||||||
|
{
|
||||||
|
let cmd = BmsRegisterMap::BatteryLifetimeCapacityMilliAmpereHours;
|
||||||
|
let mut lifetime_capacity_mah: [u8; 4] = [0x00; 4];
|
||||||
|
let mut remaining_capacity_mah: [u8; 4] = [0x00; 4];
|
||||||
|
let mut current_mv: [u8; 4] = [0x00; 4];
|
||||||
|
let mut temperature_celcius: [u8; 4] = [0x00; 4];
|
||||||
|
let mut health_percent: [u8; 4] = [0x00; 4];
|
||||||
|
i2c_dev.transaction(
|
||||||
|
BMS_I2C_ADDRESS,
|
||||||
|
&mut [
|
||||||
|
Operation::Write(&(cmd as u32).to_be_bytes()),
|
||||||
|
Operation::Read(&mut lifetime_capacity_mah),
|
||||||
|
Operation::Read(&mut remaining_capacity_mah),
|
||||||
|
Operation::Read(&mut current_mv),
|
||||||
|
Operation::Read(&mut temperature_celcius),
|
||||||
|
Operation::Read(&mut health_percent),
|
||||||
|
],
|
||||||
|
)?;
|
||||||
|
Ok(BatteryState {
|
||||||
|
lifetime_capacity_mah: u32::from_be_bytes(lifetime_capacity_mah),
|
||||||
|
remaining_capacity_mah: u32::from_be_bytes(remaining_capacity_mah),
|
||||||
|
current_mv: u32::from_be_bytes(current_mv),
|
||||||
|
temperature_celcius: i32::from_be_bytes(temperature_celcius),
|
||||||
|
health_percent: u32::from_be_bytes(health_percent),
|
||||||
|
})
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#[repr(u32)]
|
||||||
|
#[non_exhaustive]
|
||||||
|
pub enum BmsRegisterMap {
|
||||||
|
// software reset register
|
||||||
|
Reset = 0x00000000,
|
||||||
|
// bms protocol revesion as u32 value
|
||||||
|
ProtocolVersion = 0x00000001,
|
||||||
|
// bms firmware revesion as u32 value
|
||||||
|
FirmwareVersion = 0x00000002,
|
||||||
|
// Configuration Values Start Here
|
||||||
|
ConfigCapacityMilliAmpereHours = 0x00010000,
|
||||||
|
ConfigFullMilliVolt = 0x00010004,
|
||||||
|
ConfigEmptyMilliVolt = 0x00010008,
|
||||||
|
// Battery State Values Start Here
|
||||||
|
BatteryLifetimeCapacityMilliAmpereHours = 0x00020000,
|
||||||
|
BatteryRemainingCapacityMilliAmpereHours = 0x00020004,
|
||||||
|
BatteryCurrentVoltageMilliVolt = 0x00020008,
|
||||||
|
BatteryTemperatureCelcius = 0x0002000c,
|
||||||
|
BatteryHealthPercent = 0x00020010,
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user