From df6d9bf03d2d366b242eaa4dc9fbfa9a5a0ff3ba Mon Sep 17 00:00:00 2001 From: ju6ge Date: Thu, 1 Jan 2026 21:20:55 +0100 Subject: [PATCH] starting with library and measurment implementation --- Cargo.lock | 34 +++++++++++++++++++++++++++ firmware/Cargo.toml | 4 ++++ firmware/src/main.rs | 24 +++++++++++++++++-- firmware/src/measurement.rs | 47 +++++++++++++++++++++++++++++++++++++ lib-bms-protocol/src/lib.rs | 18 +++++++------- 5 files changed, 117 insertions(+), 10 deletions(-) create mode 100644 firmware/src/measurement.rs diff --git a/Cargo.lock b/Cargo.lock index 427934a..2db1753 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -46,14 +46,18 @@ dependencies = [ "ch32-metapac 0.0.6", "embassy-executor", "embassy-futures", + "embassy-sync 0.7.2", "embassy-time 0.4.0", "embassy-usb", "embedded-hal 1.0.0", "heapless", + "ina219", + "lib-bms-protocol", "micromath", "panic-halt", "qingke", "qingke-rt", + "thiserror", ] [[package]] @@ -518,6 +522,16 @@ version = "1.0.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "b9e0384b61958566e926dc50660321d12159025e767c18e043daf26b70104c39" +[[package]] +name = "ina219" +version = "0.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "457a68120d2d0f0ca1b5c7f8e0ff3f77db9e34b1076a4e82f7097cbde7d2aaa4" +dependencies = [ + "embedded-hal 1.0.0", + "embedded-hal-async", +] + [[package]] name = "lib-bms-protocol" version = "0.1.0" @@ -804,6 +818,26 @@ dependencies = [ "unicode-ident", ] +[[package]] +name = "thiserror" +version = "2.0.17" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f63587ca0f12b72a0600bcba1d40081f830876000bb46dd2337a3051618f4fc8" +dependencies = [ + "thiserror-impl", +] + +[[package]] +name = "thiserror-impl" +version = "2.0.17" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3ff15c8ecd7de3849db632e14d18d2571fa09dfc5ed93479bc4485c7a517c913" +dependencies = [ + "proc-macro2", + "quote", + "syn 2.0.111", +] + [[package]] name = "unicode-ident" version = "1.0.22" diff --git a/firmware/Cargo.toml b/firmware/Cargo.toml index 57faf63..fa74169 100644 --- a/firmware/Cargo.toml +++ b/firmware/Cargo.toml @@ -21,6 +21,7 @@ embassy-executor = { version = "0.7.0", features = [ embassy-time = { version = "0.4.0" } embassy-usb = { version = "0.3.0" } embassy-futures = { version = "0.1.0" } +embassy-sync = { version = "0.7.2" } # This is okay because we should automatically use whatever ch32-hal uses qingke-rt = "*" @@ -32,6 +33,9 @@ embedded-hal = "1.0.0" heapless = "0.8.0" micromath = { version = "2.1.0", features = ["num-traits"] } ch32-metapac = { version = "0.0.6", features = ["ch32v203c8t6"] } +ina219 = "0.2.0" +lib-bms-protocol = { path = "../lib-bms-protocol" } +thiserror = { version = "2.0.17", default-features = false } [profile.dev] #lto = true diff --git a/firmware/src/main.rs b/firmware/src/main.rs index c699b99..3361c5d 100644 --- a/firmware/src/main.rs +++ b/firmware/src/main.rs @@ -3,20 +3,40 @@ #![feature(type_alias_impl_trait)] #![feature(impl_trait_in_assoc_type)] +mod measurement; + +use ch32_hal::i2c::mode::OperatingMode; +use ch32_hal::mode::Mode; use ch32_hal::println; use ch32_hal::time::Hertz; use embassy_executor::Spawner; +use embassy_sync::blocking_mutex::raw::{CriticalSectionRawMutex, NoopRawMutex}; +use embassy_sync::lazy_lock::LazyLock; +use embassy_sync::mutex::Mutex; +use embassy_sync::rwlock::RwLock; //use embassy_time::{Duration, Timer}; use hal::bind_interrupts; use hal::i2c::{Config, I2c, SlaveAddress, SlaveConfig}; use {ch32_hal as hal, panic_halt as _}; - bind_interrupts!(struct Irqs { I2C1_EV => ch32_hal::i2c::EventInterruptHandler; I2C1_ER => ch32_hal::i2c::ErrorInterruptHandler; }); +const MEASUREMENT_SAMPLES_CAPACITY: usize = 1024; +static MEASUREMENTS: LazyLock< + embassy_sync::mutex::Mutex< + CriticalSectionRawMutex, + heapless::Deque, + >, +> = LazyLock::new(|| Mutex::new(heapless::Deque::new())); + +async fn measurement_task<'m, M: Mode, O: OperatingMode>( + i2c_dev: I2c<'m, ch32_hal::peripherals::I2C2, M, O>, +) { +} + #[embassy_executor::main(entry = "qingke_rt::entry")] async fn main(_spawner: Spawner) -> ! { let p = hal::init(Default::default()); @@ -44,7 +64,7 @@ async fn main(_spawner: Spawner) -> ! { println!("received byte 0x{buf:x?}"); } } - }, + } Err(err) => { println!("{:?}", err) } diff --git a/firmware/src/measurement.rs b/firmware/src/measurement.rs new file mode 100644 index 0000000..cfc03fc --- /dev/null +++ b/firmware/src/measurement.rs @@ -0,0 +1,47 @@ + +use embassy_usb::msos::ConfigurationSubsetHeader; +use lib_bms_protocol::BatteryState; + +use ina219::{address::Address, calibration::{IntCalibration, MicroAmpere, MicroWatt, UnCalibrated}, configuration::Configuration, errors::{ConfigurationReadError, InitializationError}, measurements::{CurrentRegister, Measurements, PowerRegister}, SyncIna219}; +use thiserror::Error; + +pub(crate) const INA219_DEVICE_ADDR: u8 = 0b100_1011; + +#[derive(Debug, Error)] +pub(crate) enum MeasurementError { + #[error("ina219 sensor initialization failed")] + Ina219InitError, + #[error("ina219 configuration read error")] + Ina219ConfigReadErr, + #[error("ina219 measurement read error")] + Ina219MeasurementReadError, +} + +impl From> for MeasurementError { + fn from(value: ina219::errors::MeasurementError) -> Self { + MeasurementError::Ina219MeasurementReadError + } +} + +impl From> for MeasurementError { + fn from(value: ConfigurationReadError) -> Self { + MeasurementError::Ina219InitError + } +} + +impl From> for MeasurementError { + fn from(value: InitializationError) -> Self { + MeasurementError::Ina219InitError + } +} + +pub(crate) fn read_ina219(i2c_dev: &mut T) -> Result, MeasurementError> { + let mut dev: SyncIna219<&mut T, _> = SyncIna219::new_calibrated(i2c_dev, Address::from_byte(INA219_DEVICE_ADDR).unwrap(), IntCalibration::default())?; + let config: Configuration = dev.configuration()?; + + if let Some(ina_measurement) = dev.next_measurement()? { + let ina_measurement: Measurements = ina_measurement; + } + let measurement = todo!(); + Ok(measurement) +} diff --git a/lib-bms-protocol/src/lib.rs b/lib-bms-protocol/src/lib.rs index 24659b4..842be77 100644 --- a/lib-bms-protocol/src/lib.rs +++ b/lib-bms-protocol/src/lib.rs @@ -2,22 +2,24 @@ #[derive(Debug)] +#[repr(transparent)] pub struct Version(u32); #[derive(Debug)] pub struct Config { - capacity_mah: u32, - v_full_mv: u32, - v_empty_mv: u32, + pub capacity_mah: u32, + pub v_full_mv: u32, + pub v_empty_mv: u32, } +#[derive(Debug, Clone, Copy)] pub struct BatteryState { - lifetime_capacity_mAh: u32, - remaining_capacity_mAh: u32, - current_milli_volts: u16, - temperature_celcius: i32, - health_percent: u8 + pub lifetime_capacity_mah: u32, + pub remaining_capacity_mah: u32, + pub current_mv: u16, + pub temperature_celcius: i32, + pub health_percent: u8 } pub enum BmsCommand {