refactor: simplify battery monitoring logic, remove unused fields, and replace BQ34Z100G1 integration with WCH I2C implementation
This commit is contained in:
1
Software/MainBoard/.idea/MainBoard.iml
generated
1
Software/MainBoard/.idea/MainBoard.iml
generated
@@ -3,6 +3,7 @@
|
||||
<component name="NewModuleRootManager">
|
||||
<content url="file://$MODULE_DIR$">
|
||||
<sourceFolder url="file://$MODULE_DIR$/rust/src" isTestSource="false" />
|
||||
<sourceFolder url="file://$MODULE_DIR$/rust/tests" isTestSource="true" />
|
||||
<excludeFolder url="file://$MODULE_DIR$/rust/target" />
|
||||
</content>
|
||||
<orderEntry type="inheritedJdk" />
|
||||
|
||||
@@ -95,12 +95,12 @@ embedded-can = "0.4.1"
|
||||
nb = "1.1.0"
|
||||
|
||||
# Concrete hardware drivers and sensors/IO expanders
|
||||
lib-bms-protocol = {git = "https://gitea.wlandt.de/judge/ch32-bms.git" , default-features = false }
|
||||
onewire = "0.4.0"
|
||||
ds323x = "0.7.0"
|
||||
eeprom24x = "0.7.2"
|
||||
pca9535 = { version = "2.0.0" }
|
||||
ina219 = { version = "0.2.0" }
|
||||
bq34z100 = { version = "0.4.0", default-features = false }
|
||||
|
||||
# Storage and filesystem
|
||||
littlefs2 = { version = "0.6.1", features = ["c-stubs", "alloc"] }
|
||||
|
||||
@@ -83,7 +83,6 @@ impl Default for TankConfig {
|
||||
pub enum BatteryBoardVersion {
|
||||
#[default]
|
||||
Disabled,
|
||||
BQ34Z100G1,
|
||||
WchI2cSlave,
|
||||
}
|
||||
#[derive(Serialize, Deserialize, Clone, Debug, PartialEq, Default)]
|
||||
|
||||
@@ -2,6 +2,7 @@ use alloc::format;
|
||||
use alloc::string::{String, ToString};
|
||||
use core::convert::Infallible;
|
||||
use core::fmt;
|
||||
use core::fmt::Debug;
|
||||
use core::str::Utf8Error;
|
||||
use embassy_embedded_hal::shared_bus::I2cDeviceError;
|
||||
use embassy_executor::SpawnError;
|
||||
@@ -12,6 +13,7 @@ use esp_hal::pcnt::unit::{InvalidHighLimit, InvalidLowLimit};
|
||||
use esp_hal::twai::EspTwaiError;
|
||||
use esp_radio::wifi::WifiError;
|
||||
use ina219::errors::{BusVoltageReadError, ShuntVoltageReadError};
|
||||
use lib_bms_protocol::BmsProtocolError;
|
||||
use littlefs2_core::PathError;
|
||||
use onewire::Error;
|
||||
use pca9535::ExpanderError;
|
||||
@@ -19,6 +21,9 @@ use pca9535::ExpanderError;
|
||||
//All error superconstruct
|
||||
#[derive(Debug)]
|
||||
pub enum FatError {
|
||||
BMSError {
|
||||
error: String,
|
||||
},
|
||||
OneWireError {
|
||||
error: Error<Infallible>,
|
||||
},
|
||||
@@ -100,6 +105,7 @@ impl fmt::Display for FatError {
|
||||
write!(f, "CanBusError {error:?}")
|
||||
}
|
||||
FatError::SNTPError { error } => write!(f, "SNTPError {error:?}"),
|
||||
FatError::BMSError { error } => write!(f, "BMSError, {error}"),
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -316,3 +322,14 @@ impl From<sntpc::Error> for FatError {
|
||||
FatError::SNTPError { error: value }
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
impl From<BmsProtocolError> for FatError{
|
||||
fn from(value: BmsProtocolError) -> Self {
|
||||
match value {
|
||||
BmsProtocolError::I2cCommunicationError => {
|
||||
FatError::String{error: "I2C communication error".to_string()}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,39 +1,30 @@
|
||||
use crate::fat_error::{FatError, FatResult};
|
||||
use crate::hal::Box;
|
||||
use crate::fat_error::{FatError, FatResult};
|
||||
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 lib_bms_protocol::{BatteryState as bstate, BmsReadable, Config, FirmwareVersion, ProtocolVersion};
|
||||
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>;
|
||||
async fn get_state(&mut self) -> FatResult<BatteryState>;
|
||||
async fn get_firmware(&mut self) -> FatResult<FirmwareVersion>;
|
||||
async fn get_protocol(&mut self) -> FatResult<ProtocolVersion>;
|
||||
async fn reset(&mut self) -> FatResult<()>;
|
||||
}
|
||||
|
||||
#[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,
|
||||
pub voltage_milli_volt: u32,
|
||||
pub average_current_milli_ampere: i32,
|
||||
pub design_milli_ampere_hour: u32,
|
||||
pub remaining_milli_ampere_hour: u32,
|
||||
pub state_of_charge: u8,
|
||||
pub state_of_health: u32,
|
||||
pub temperature: i32,
|
||||
}
|
||||
|
||||
#[derive(Debug, Serialize)]
|
||||
@@ -46,213 +37,62 @@ pub enum BatteryState {
|
||||
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> {
|
||||
async fn get_state(&mut self) -> FatResult<BatteryState> {
|
||||
Ok(BatteryState::Unknown)
|
||||
}
|
||||
|
||||
async fn get_firmware(&mut self) -> FatResult<FirmwareVersion> {
|
||||
Err(FatError::NoBatteryMonitor)
|
||||
}
|
||||
|
||||
async fn get_protocol(&mut self) -> FatResult<ProtocolVersion> {
|
||||
Err(FatError::NoBatteryMonitor)
|
||||
}
|
||||
|
||||
async fn reset(&mut self) -> FatResult<()> {
|
||||
Err(FatError::NoBatteryMonitor)
|
||||
}
|
||||
}
|
||||
|
||||
//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>,
|
||||
pub struct WCHI2CSlave<'a> {
|
||||
pub(crate) i2c: I2cDevice<'a, CriticalSectionRawMutex, I2c<'a, Blocking>>
|
||||
}
|
||||
|
||||
#[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:?}"),
|
||||
})
|
||||
}
|
||||
impl BatteryInteraction for WCHI2CSlave<'_> {
|
||||
|
||||
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 get_state(&mut self) -> FatResult<BatteryState> {
|
||||
let state = bstate::read_from_i2c(&mut self.i2c)?;
|
||||
let config = Config::read_from_i2c(&mut self.i2c)?;
|
||||
|
||||
async fn design_milli_ampere_hour(&mut self) -> FatResult<u16> {
|
||||
self.battery_driver
|
||||
.design_capacity()
|
||||
.map_err(|e| FatError::String {
|
||||
error: alloc::format!("{e:?}"),
|
||||
})
|
||||
}
|
||||
let state_of_charge = (state.remaining_capacity_mah * 100 / state.lifetime_capacity_mah) as u8;
|
||||
let state_of_health = state.lifetime_capacity_mah / config.capacity_mah * 100;
|
||||
|
||||
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?,
|
||||
voltage_milli_volt: state.current_mv,
|
||||
average_current_milli_ampere: 1337,
|
||||
design_milli_ampere_hour: config.capacity_mah,
|
||||
remaining_milli_ampere_hour: state.remaining_capacity_mah,
|
||||
state_of_charge,
|
||||
state_of_health,
|
||||
temperature: state.temperature_celcius,
|
||||
}))
|
||||
}
|
||||
}
|
||||
|
||||
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!");
|
||||
async fn get_firmware(&mut self) -> FatResult<FirmwareVersion> {
|
||||
todo!()
|
||||
}
|
||||
|
||||
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:?}");
|
||||
async fn get_protocol(&mut self) -> FatResult<ProtocolVersion> {
|
||||
todo!()
|
||||
}
|
||||
|
||||
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: {chem_id} Current voltage {voltage} and current {current} with charge {state}% and temp {temp_c} CVolt: {charge_voltage} CCur {charge_current}");
|
||||
let _ = battery_driver.unsealed();
|
||||
let _ = battery_driver.it_enable();
|
||||
Ok(())
|
||||
}
|
||||
async fn reset(&mut self) -> FatResult<()> {
|
||||
todo!()
|
||||
}
|
||||
}
|
||||
@@ -1,3 +1,4 @@
|
||||
use lib_bms_protocol::BmsReadable;
|
||||
pub(crate) mod battery;
|
||||
// mod can_api; // replaced by external canapi crate
|
||||
pub mod esp;
|
||||
@@ -8,6 +9,7 @@ mod shared_flash;
|
||||
mod v4_hal;
|
||||
mod water;
|
||||
|
||||
use lib_bms_protocol::ProtocolVersion;
|
||||
use crate::alloc::string::ToString;
|
||||
use crate::hal::rtc::{DS3231Module, RTCModuleInteraction};
|
||||
use esp_hal::peripherals::Peripherals;
|
||||
@@ -50,7 +52,6 @@ use alloc::format;
|
||||
use alloc::sync::Arc;
|
||||
use async_trait::async_trait;
|
||||
use bincode::{Decode, Encode};
|
||||
use bq34z100::Bq34z100g1Driver;
|
||||
use canapi::SensorSlot;
|
||||
use chrono::{DateTime, FixedOffset, Utc};
|
||||
use core::cell::RefCell;
|
||||
@@ -72,7 +73,7 @@ use esp_hal::gpio::{Input, InputConfig, Pull};
|
||||
use measurements::{Current, Voltage};
|
||||
|
||||
use crate::fat_error::{ContextExt, FatError, FatResult};
|
||||
use crate::hal::battery::{print_battery_bq34z100, BQ34Z100G1};
|
||||
use crate::hal::battery::{WCHI2CSlave};
|
||||
use crate::hal::little_fs2storage_adapter::LittleFs2Filesystem;
|
||||
use crate::hal::water::TankSensor;
|
||||
use crate::log::LOG_ACCESS;
|
||||
@@ -485,6 +486,7 @@ impl PlantHal {
|
||||
|
||||
let i2c_bus = I2C_DRIVER.get().await;
|
||||
let rtc_device = I2cDevice::new(i2c_bus);
|
||||
let mut bms_device = I2cDevice::new(i2c_bus);
|
||||
let eeprom_device = I2cDevice::new(i2c_bus);
|
||||
|
||||
let mut rtc: Ds323x<
|
||||
@@ -519,35 +521,18 @@ impl PlantHal {
|
||||
let battery_interaction: Box<dyn BatteryInteraction + Send> =
|
||||
match config.hardware.battery {
|
||||
BatteryBoardVersion::Disabled => Box::new(NoBatteryMonitor {}),
|
||||
BatteryBoardVersion::BQ34Z100G1 => {
|
||||
let battery_device = I2cDevice::new(I2C_DRIVER.get().await);
|
||||
let mut battery_driver = Bq34z100g1Driver {
|
||||
i2c: battery_device,
|
||||
delay: Delay::new(),
|
||||
flash_block_data: [0; 32],
|
||||
};
|
||||
let status = print_battery_bq34z100(&mut battery_driver);
|
||||
match status {
|
||||
Ok(_) => {}
|
||||
Err(err) => {
|
||||
LOG_ACCESS
|
||||
.lock()
|
||||
.await
|
||||
.log(
|
||||
LogMessage::BatteryCommunicationError,
|
||||
0u32,
|
||||
0,
|
||||
"",
|
||||
&format!("{err:?})"),
|
||||
)
|
||||
.await;
|
||||
}
|
||||
}
|
||||
Box::new(BQ34Z100G1 { battery_driver })
|
||||
}
|
||||
BatteryBoardVersion::WchI2cSlave => {
|
||||
// TODO use correct implementation once availible
|
||||
Box::new(NoBatteryMonitor {})
|
||||
let version = ProtocolVersion::read_from_i2c(&mut bms_device);
|
||||
let version_val = match version {
|
||||
Ok(v) => unsafe { core::mem::transmute::<ProtocolVersion, u32>(v) },
|
||||
Err(_) => 0,
|
||||
};
|
||||
if version_val == 1 {
|
||||
Box::new(WCHI2CSlave { i2c: bms_device })
|
||||
} else {
|
||||
//todo should be an error variant instead?
|
||||
Box::new(NoBatteryMonitor {})
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
@@ -280,6 +280,8 @@ pub enum LogMessage {
|
||||
PumpOpenLoopCurrent,
|
||||
#[strum(serialize = "Pump Open current sensor required but did not work: ${number_a}")]
|
||||
PumpMissingSensorCurrent,
|
||||
#[strum(serialize = "MPPT Current sensor could not be reached")]
|
||||
MPPTError,
|
||||
}
|
||||
|
||||
#[derive(Serialize)]
|
||||
|
||||
@@ -492,22 +492,18 @@ async fn safe_main(spawner: Spawner) -> FatResult<()> {
|
||||
|
||||
info!("state of charg");
|
||||
let is_day = board.board_hal.is_day();
|
||||
let state_of_charge = board
|
||||
.board_hal
|
||||
.get_battery_monitor()
|
||||
.state_charge_percent()
|
||||
.await
|
||||
.unwrap_or(0.);
|
||||
|
||||
// try to load full battery state if failed the battery state is unknown
|
||||
let battery_state = board
|
||||
.board_hal
|
||||
.get_battery_monitor()
|
||||
.get_battery_state()
|
||||
.await
|
||||
.unwrap_or(BatteryState::Unknown);
|
||||
|
||||
let battery_state = board.board_hal.get_battery_monitor().get_state().await.unwrap_or(BatteryState::Unknown);
|
||||
info!("Battery state is {battery_state:?}");
|
||||
|
||||
let state_of_charge = match &battery_state {
|
||||
BatteryState::Unknown => {
|
||||
0
|
||||
}
|
||||
BatteryState::Info(data) => {
|
||||
data.state_of_charge
|
||||
}
|
||||
};
|
||||
|
||||
let mut light_state = LightState {
|
||||
enabled: board.board_hal.get_config().night_lamp.enabled,
|
||||
..Default::default()
|
||||
@@ -530,7 +526,6 @@ async fn safe_main(spawner: Spawner) -> FatResult<()> {
|
||||
.get_config()
|
||||
.night_lamp
|
||||
.low_soc_cutoff
|
||||
.into()
|
||||
{
|
||||
board.board_hal.get_esp().set_low_voltage_in_cycle();
|
||||
info!("Set low voltage in cycle");
|
||||
@@ -540,7 +535,6 @@ async fn safe_main(spawner: Spawner) -> FatResult<()> {
|
||||
.get_config()
|
||||
.night_lamp
|
||||
.low_soc_restore
|
||||
.into()
|
||||
{
|
||||
board.board_hal.get_esp().clear_low_voltage_in_cycle();
|
||||
info!("Clear low voltage in cycle");
|
||||
@@ -591,7 +585,7 @@ async fn safe_main(spawner: Spawner) -> FatResult<()> {
|
||||
|
||||
let deep_sleep_duration_minutes: u32 =
|
||||
// if battery soc is unknown assume battery has enough change
|
||||
if state_of_charge < 10.0 && !matches!(battery_state, BatteryState::Unknown) {
|
||||
if state_of_charge < 10 && !matches!(battery_state, BatteryState::Unknown) {
|
||||
let _ = board
|
||||
.board_hal
|
||||
.get_esp()
|
||||
@@ -756,24 +750,19 @@ pub async fn do_secure_pump(
|
||||
async fn update_charge_indicator(
|
||||
board: &mut MutexGuard<'static, CriticalSectionRawMutex, HAL<'static>>,
|
||||
) {
|
||||
//FIXME add config and code to allow power supply mode, in this case this is a nop
|
||||
//we have mppt controller, ask it for charging current
|
||||
if let Ok(current) = board.board_hal.get_mptt_current().await {
|
||||
let _ = board
|
||||
.board_hal
|
||||
.set_charge_indicator(current.as_milliamperes() > 20_f64)
|
||||
.await;
|
||||
}
|
||||
//fallback to battery controller and ask it instead
|
||||
else if let Ok(charging) = board
|
||||
.board_hal
|
||||
.get_battery_monitor()
|
||||
.average_current_milli_ampere()
|
||||
.await
|
||||
{
|
||||
let _ = board.board_hal.set_charge_indicator(charging > 20).await;
|
||||
} else {
|
||||
//who knows
|
||||
board.board_hal.general_fault(true).await;
|
||||
log(LogMessage::MPPTError, 0, 0, "", "").await;
|
||||
let _ = board.board_hal.set_charge_indicator(false).await;
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
@@ -959,7 +948,7 @@ async fn publish_battery_state(
|
||||
let state = board
|
||||
.board_hal
|
||||
.get_battery_monitor()
|
||||
.get_battery_state()
|
||||
.get_state()
|
||||
.await;
|
||||
let value = match state {
|
||||
Ok(state) => {
|
||||
|
||||
@@ -131,7 +131,7 @@ pub(crate) async fn get_battery_state<T, const N: usize>(
|
||||
let battery_state = board
|
||||
.board_hal
|
||||
.get_battery_monitor()
|
||||
.get_battery_state()
|
||||
.get_state()
|
||||
.await?;
|
||||
Ok(Some(serde_json::to_string(&battery_state)?))
|
||||
}
|
||||
|
||||
@@ -167,7 +167,6 @@ export interface BatteryState {
|
||||
temperature: string
|
||||
voltage_milli_volt: string,
|
||||
current_milli_ampere: string,
|
||||
cycle_count: string,
|
||||
design_milli_ampere: string,
|
||||
remaining_milli_ampere: string,
|
||||
state_of_charge: string,
|
||||
|
||||
@@ -23,10 +23,6 @@
|
||||
<span class="powerflexkey">mA:</span>
|
||||
<span class="powerflexvalue" id="battery_current_milli_ampere" ></span>
|
||||
</div>
|
||||
<div class="flexcontainer">
|
||||
<span class="powerflexkey">Cycles:</span>
|
||||
<span class="powerflexvalue" id="battery_cycle_count" ></span>
|
||||
</div>
|
||||
<div class="flexcontainer">
|
||||
<span class="powerflexkey">design mA:</span>
|
||||
<span class="powerflexvalue" id="battery_design_milli_ampere" ></span>
|
||||
|
||||
@@ -4,7 +4,6 @@ import {BatteryState} from "./api";
|
||||
export class BatteryView{
|
||||
voltage_milli_volt: HTMLSpanElement;
|
||||
current_milli_ampere: HTMLSpanElement;
|
||||
cycle_count: HTMLSpanElement;
|
||||
design_milli_ampere: HTMLSpanElement;
|
||||
remaining_milli_ampere: HTMLSpanElement;
|
||||
state_of_charge: HTMLSpanElement;
|
||||
@@ -18,7 +17,6 @@ export class BatteryView{
|
||||
(document.getElementById("batteryview") as HTMLElement).innerHTML = require("./batteryview.html")
|
||||
this.voltage_milli_volt = document.getElementById("battery_voltage_milli_volt") as HTMLSpanElement;
|
||||
this.current_milli_ampere = document.getElementById("battery_current_milli_ampere") as HTMLSpanElement;
|
||||
this.cycle_count = document.getElementById("battery_cycle_count") as HTMLSpanElement;
|
||||
this.design_milli_ampere = document.getElementById("battery_design_milli_ampere") as HTMLSpanElement;
|
||||
this.remaining_milli_ampere = document.getElementById("battery_remaining_milli_ampere") as HTMLSpanElement;
|
||||
this.state_of_charge = document.getElementById("battery_state_of_charge") as HTMLSpanElement;
|
||||
@@ -41,7 +39,6 @@ export class BatteryView{
|
||||
if (batterystate == null) {
|
||||
this.voltage_milli_volt.innerText = "N/A"
|
||||
this.current_milli_ampere.innerText = "N/A"
|
||||
this.cycle_count.innerText = "N/A"
|
||||
this.design_milli_ampere.innerText = "N/A"
|
||||
this.remaining_milli_ampere.innerText = "N/A"
|
||||
this.state_of_charge.innerText = "N/A"
|
||||
@@ -50,12 +47,11 @@ export class BatteryView{
|
||||
} else {
|
||||
this.voltage_milli_volt.innerText = String(+batterystate.voltage_milli_volt/1000)
|
||||
this.current_milli_ampere.innerText = batterystate.current_milli_ampere
|
||||
this.cycle_count.innerText = batterystate.cycle_count
|
||||
this.design_milli_ampere.innerText = batterystate.design_milli_ampere
|
||||
this.remaining_milli_ampere.innerText = batterystate.remaining_milli_ampere
|
||||
this.state_of_charge.innerText = batterystate.state_of_charge
|
||||
this.state_of_health.innerText = batterystate.state_of_health
|
||||
this.temperature.innerText = String(+batterystate.temperature / 100)
|
||||
this.temperature.innerText = String(+batterystate.temperature)
|
||||
}
|
||||
|
||||
|
||||
|
||||
Reference in New Issue
Block a user