cleanups
This commit is contained in:
258
Software/MainBoard/rust/src/hal/battery.rs
Normal file
258
Software/MainBoard/rust/src/hal/battery.rs
Normal file
@@ -0,0 +1,258 @@
|
||||
use crate::fat_error::{FatError, FatResult};
|
||||
use crate::hal::Box;
|
||||
use async_trait::async_trait;
|
||||
use bq34z100::{Bq34z100g1, Bq34z100g1Driver, Flags};
|
||||
use embassy_embedded_hal::shared_bus::blocking::i2c::I2cDevice;
|
||||
use embassy_sync::blocking_mutex::raw::CriticalSectionRawMutex;
|
||||
use esp_hal::delay::Delay;
|
||||
use esp_hal::i2c::master::I2c;
|
||||
use esp_hal::Blocking;
|
||||
use measurements::Temperature;
|
||||
use serde::Serialize;
|
||||
|
||||
#[async_trait(?Send)]
|
||||
pub trait BatteryInteraction {
|
||||
async fn state_charge_percent(&mut self) -> FatResult<f32>;
|
||||
async fn remaining_milli_ampere_hour(&mut self) -> FatResult<u16>;
|
||||
async fn max_milli_ampere_hour(&mut self) -> FatResult<u16>;
|
||||
async fn design_milli_ampere_hour(&mut self) -> FatResult<u16>;
|
||||
async fn voltage_milli_volt(&mut self) -> FatResult<u16>;
|
||||
async fn average_current_milli_ampere(&mut self) -> FatResult<i16>;
|
||||
async fn cycle_count(&mut self) -> FatResult<u16>;
|
||||
async fn state_health_percent(&mut self) -> FatResult<u16>;
|
||||
async fn bat_temperature(&mut self) -> FatResult<u16>;
|
||||
async fn get_battery_state(&mut self) -> FatResult<BatteryState>;
|
||||
}
|
||||
|
||||
#[derive(Debug, Serialize)]
|
||||
pub struct BatteryInfo {
|
||||
pub voltage_milli_volt: u16,
|
||||
pub average_current_milli_ampere: i16,
|
||||
pub cycle_count: u16,
|
||||
pub design_milli_ampere_hour: u16,
|
||||
pub remaining_milli_ampere_hour: u16,
|
||||
pub state_of_charge: f32,
|
||||
pub state_of_health: u16,
|
||||
pub temperature: u16,
|
||||
}
|
||||
|
||||
#[derive(Debug, Serialize)]
|
||||
pub enum BatteryState {
|
||||
Unknown,
|
||||
Info(BatteryInfo),
|
||||
}
|
||||
|
||||
/// If no battery monitor is installed this implementation will be used
|
||||
pub struct NoBatteryMonitor {}
|
||||
#[async_trait(?Send)]
|
||||
impl BatteryInteraction for NoBatteryMonitor {
|
||||
async fn state_charge_percent(&mut self) -> FatResult<f32> {
|
||||
// No monitor configured: assume full battery for lightstate logic
|
||||
Ok(100.0)
|
||||
}
|
||||
|
||||
async fn remaining_milli_ampere_hour(&mut self) -> FatResult<u16> {
|
||||
Err(FatError::NoBatteryMonitor)
|
||||
}
|
||||
|
||||
async fn max_milli_ampere_hour(&mut self) -> FatResult<u16> {
|
||||
Err(FatError::NoBatteryMonitor)
|
||||
}
|
||||
|
||||
async fn design_milli_ampere_hour(&mut self) -> FatResult<u16> {
|
||||
Err(FatError::NoBatteryMonitor)
|
||||
}
|
||||
|
||||
async fn voltage_milli_volt(&mut self) -> FatResult<u16> {
|
||||
Err(FatError::NoBatteryMonitor)
|
||||
}
|
||||
|
||||
async fn average_current_milli_ampere(&mut self) -> FatResult<i16> {
|
||||
Err(FatError::NoBatteryMonitor)
|
||||
}
|
||||
|
||||
async fn cycle_count(&mut self) -> FatResult<u16> {
|
||||
Err(FatError::NoBatteryMonitor)
|
||||
}
|
||||
|
||||
async fn state_health_percent(&mut self) -> FatResult<u16> {
|
||||
Err(FatError::NoBatteryMonitor)
|
||||
}
|
||||
|
||||
async fn bat_temperature(&mut self) -> FatResult<u16> {
|
||||
Err(FatError::NoBatteryMonitor)
|
||||
}
|
||||
|
||||
async fn get_battery_state(&mut self) -> FatResult<BatteryState> {
|
||||
Ok(BatteryState::Unknown)
|
||||
}
|
||||
}
|
||||
|
||||
//TODO implement this battery monitor kind once controller is complete
|
||||
#[allow(dead_code)]
|
||||
pub struct WchI2cSlave {}
|
||||
|
||||
pub type I2cDev = I2cDevice<'static, CriticalSectionRawMutex, I2c<'static, Blocking>>;
|
||||
|
||||
pub struct BQ34Z100G1 {
|
||||
pub battery_driver: Bq34z100g1Driver<I2cDev, Delay>,
|
||||
}
|
||||
|
||||
#[async_trait(?Send)]
|
||||
impl BatteryInteraction for BQ34Z100G1 {
|
||||
async fn state_charge_percent(&mut self) -> FatResult<f32> {
|
||||
self.battery_driver
|
||||
.state_of_charge()
|
||||
.map(|v| v as f32)
|
||||
.map_err(|e| FatError::String {
|
||||
error: alloc::format!("{:?}", e),
|
||||
})
|
||||
}
|
||||
|
||||
async fn remaining_milli_ampere_hour(&mut self) -> FatResult<u16> {
|
||||
self.battery_driver
|
||||
.remaining_capacity()
|
||||
.map_err(|e| FatError::String {
|
||||
error: alloc::format!("{:?}", e),
|
||||
})
|
||||
}
|
||||
|
||||
async fn max_milli_ampere_hour(&mut self) -> FatResult<u16> {
|
||||
self.battery_driver
|
||||
.full_charge_capacity()
|
||||
.map_err(|e| FatError::String {
|
||||
error: alloc::format!("{:?}", e),
|
||||
})
|
||||
}
|
||||
|
||||
async fn design_milli_ampere_hour(&mut self) -> FatResult<u16> {
|
||||
self.battery_driver
|
||||
.design_capacity()
|
||||
.map_err(|e| FatError::String {
|
||||
error: alloc::format!("{:?}", e),
|
||||
})
|
||||
}
|
||||
|
||||
async fn voltage_milli_volt(&mut self) -> FatResult<u16> {
|
||||
self.battery_driver.voltage().map_err(|e| FatError::String {
|
||||
error: alloc::format!("{:?}", e),
|
||||
})
|
||||
}
|
||||
|
||||
async fn average_current_milli_ampere(&mut self) -> FatResult<i16> {
|
||||
self.battery_driver
|
||||
.average_current()
|
||||
.map_err(|e| FatError::String {
|
||||
error: alloc::format!("{:?}", e),
|
||||
})
|
||||
}
|
||||
|
||||
async fn cycle_count(&mut self) -> FatResult<u16> {
|
||||
self.battery_driver
|
||||
.cycle_count()
|
||||
.map_err(|e| FatError::String {
|
||||
error: alloc::format!("{:?}", e),
|
||||
})
|
||||
}
|
||||
|
||||
async fn state_health_percent(&mut self) -> FatResult<u16> {
|
||||
self.battery_driver
|
||||
.state_of_health()
|
||||
.map_err(|e| FatError::String {
|
||||
error: alloc::format!("{:?}", e),
|
||||
})
|
||||
}
|
||||
|
||||
async fn bat_temperature(&mut self) -> FatResult<u16> {
|
||||
self.battery_driver
|
||||
.temperature()
|
||||
.map_err(|e| FatError::String {
|
||||
error: alloc::format!("{:?}", e),
|
||||
})
|
||||
}
|
||||
|
||||
async fn get_battery_state(&mut self) -> FatResult<BatteryState> {
|
||||
Ok(BatteryState::Info(BatteryInfo {
|
||||
voltage_milli_volt: self.voltage_milli_volt().await?,
|
||||
average_current_milli_ampere: self.average_current_milli_ampere().await?,
|
||||
cycle_count: self.cycle_count().await?,
|
||||
design_milli_ampere_hour: self.design_milli_ampere_hour().await?,
|
||||
remaining_milli_ampere_hour: self.remaining_milli_ampere_hour().await?,
|
||||
state_of_charge: self.state_charge_percent().await?,
|
||||
state_of_health: self.state_health_percent().await?,
|
||||
temperature: self.bat_temperature().await?,
|
||||
}))
|
||||
}
|
||||
}
|
||||
|
||||
pub fn print_battery_bq34z100(
|
||||
battery_driver: &mut Bq34z100g1Driver<I2cDevice<CriticalSectionRawMutex, I2c<Blocking>>, Delay>,
|
||||
) -> FatResult<()> {
|
||||
log::info!("Try communicating with battery");
|
||||
let fwversion = battery_driver.fw_version().unwrap_or_else(|e| {
|
||||
log::info!("Firmware {:?}", e);
|
||||
0
|
||||
});
|
||||
log::info!("fw version is {}", fwversion);
|
||||
|
||||
let design_capacity = battery_driver.design_capacity().unwrap_or_else(|e| {
|
||||
log::info!("Design capacity {:?}", e);
|
||||
0
|
||||
});
|
||||
log::info!("Design Capacity {}", design_capacity);
|
||||
if design_capacity == 1000 {
|
||||
log::info!("Still stock configuring battery, readouts are likely to be wrong!");
|
||||
}
|
||||
|
||||
let flags = battery_driver.get_flags_decoded().unwrap_or(Flags {
|
||||
fast_charge_allowed: false,
|
||||
full_chage: false,
|
||||
charging_not_allowed: false,
|
||||
charge_inhibit: false,
|
||||
bat_low: false,
|
||||
bat_high: false,
|
||||
over_temp_discharge: false,
|
||||
over_temp_charge: false,
|
||||
discharge: false,
|
||||
state_of_charge_f: false,
|
||||
state_of_charge_1: false,
|
||||
cf: false,
|
||||
ocv_taken: false,
|
||||
});
|
||||
log::info!("Flags {:?}", flags);
|
||||
|
||||
let chem_id = battery_driver.chem_id().unwrap_or_else(|e| {
|
||||
log::info!("Chemid {:?}", e);
|
||||
0
|
||||
});
|
||||
|
||||
let bat_temp = battery_driver.internal_temperature().unwrap_or_else(|e| {
|
||||
log::info!("Bat Temp {:?}", e);
|
||||
0
|
||||
});
|
||||
let temp_c = Temperature::from_kelvin(bat_temp as f64 / 10_f64).as_celsius();
|
||||
let voltage = battery_driver.voltage().unwrap_or_else(|e| {
|
||||
log::info!("Bat volt {:?}", e);
|
||||
0
|
||||
});
|
||||
let current = battery_driver.current().unwrap_or_else(|e| {
|
||||
log::info!("Bat current {:?}", e);
|
||||
0
|
||||
});
|
||||
let state = battery_driver.state_of_charge().unwrap_or_else(|e| {
|
||||
log::info!("Bat Soc {:?}", e);
|
||||
0
|
||||
});
|
||||
let charge_voltage = battery_driver.charge_voltage().unwrap_or_else(|e| {
|
||||
log::info!("Bat Charge Volt {:?}", e);
|
||||
0
|
||||
});
|
||||
let charge_current = battery_driver.charge_current().unwrap_or_else(|e| {
|
||||
log::info!("Bat Charge Current {:?}", e);
|
||||
0
|
||||
});
|
||||
log::info!("ChemId: {} Current voltage {} and current {} with charge {}% and temp {} CVolt: {} CCur {}", chem_id, voltage, current, state, temp_c, charge_voltage, charge_current);
|
||||
let _ = battery_driver.unsealed();
|
||||
let _ = battery_driver.it_enable();
|
||||
Ok(())
|
||||
}
|
||||
Reference in New Issue
Block a user