add i2c initial and pull configs
This commit is contained in:
parent
9473466feb
commit
12463c557b
File diff suppressed because it is too large
Load Diff
@ -1,6 +1,6 @@
|
|||||||
{
|
{
|
||||||
"board": {
|
"board": {
|
||||||
"active_layer": 0,
|
"active_layer": 44,
|
||||||
"active_layer_preset": "",
|
"active_layer_preset": "",
|
||||||
"auto_track_width": false,
|
"auto_track_width": false,
|
||||||
"hidden_netclasses": [],
|
"hidden_netclasses": [],
|
||||||
|
@ -11041,10 +11041,10 @@
|
|||||||
(effects (font (size 1.27 1.27)) (justify left) hide)
|
(effects (font (size 1.27 1.27)) (justify left) hide)
|
||||||
)
|
)
|
||||||
)
|
)
|
||||||
(global_label "IsDay" (shape input) (at 107.696 117.602 0) (fields_autoplaced)
|
(global_label "IsDay" (shape input) (at 115.316 117.602 0) (fields_autoplaced)
|
||||||
(effects (font (size 1.27 1.27)) (justify left))
|
(effects (font (size 1.27 1.27)) (justify left))
|
||||||
(uuid f9414b76-a92a-468b-b946-a220ff9116fe)
|
(uuid f9414b76-a92a-468b-b946-a220ff9116fe)
|
||||||
(property "Intersheetrefs" "${INTERSHEET_REFS}" (at 114.9671 117.602 0)
|
(property "Intersheetrefs" "${INTERSHEET_REFS}" (at 122.5871 117.602 0)
|
||||||
(effects (font (size 1.27 1.27)) (justify left) hide)
|
(effects (font (size 1.27 1.27)) (justify left) hide)
|
||||||
)
|
)
|
||||||
)
|
)
|
||||||
@ -21854,6 +21854,32 @@
|
|||||||
)
|
)
|
||||||
)
|
)
|
||||||
|
|
||||||
|
(symbol (lib_id "Device:R") (at 111.506 117.602 90) (unit 1)
|
||||||
|
(in_bom yes) (on_board yes) (dnp no)
|
||||||
|
(uuid cf61d446-6821-4eb1-853c-956de372075a)
|
||||||
|
(property "Reference" "R45" (at 111.506 112.522 90)
|
||||||
|
(effects (font (size 1.27 1.27)))
|
||||||
|
)
|
||||||
|
(property "Value" "1k ? unclear if required" (at 134.874 115.062 90)
|
||||||
|
(effects (font (size 1.27 1.27)))
|
||||||
|
)
|
||||||
|
(property "Footprint" "Resistor_SMD:R_0603_1608Metric" (at 111.506 119.38 90)
|
||||||
|
(effects (font (size 1.27 1.27)) hide)
|
||||||
|
)
|
||||||
|
(property "Datasheet" "~" (at 111.506 117.602 0)
|
||||||
|
(effects (font (size 1.27 1.27)) hide)
|
||||||
|
)
|
||||||
|
(pin "1" (uuid 965529aa-0bae-4e1a-bac1-72c5adfd81aa))
|
||||||
|
(pin "2" (uuid 490001cc-f9a7-4b11-a1b5-b95679c0e8f6))
|
||||||
|
(instances
|
||||||
|
(project "PlantCtrlESP32"
|
||||||
|
(path "/c26e8d55-0b6e-4c4e-b7c8-b1fed973201c"
|
||||||
|
(reference "R45") (unit 1)
|
||||||
|
)
|
||||||
|
)
|
||||||
|
)
|
||||||
|
)
|
||||||
|
|
||||||
(symbol (lib_id "Device:LED") (at 602.996 104.394 180) (unit 1)
|
(symbol (lib_id "Device:LED") (at 602.996 104.394 180) (unit 1)
|
||||||
(in_bom yes) (on_board yes) (dnp no) (fields_autoplaced)
|
(in_bom yes) (on_board yes) (dnp no) (fields_autoplaced)
|
||||||
(uuid cf7c9688-c042-4127-845f-a77e26e24ea9)
|
(uuid cf7c9688-c042-4127-845f-a77e26e24ea9)
|
||||||
|
@ -77,6 +77,7 @@ heapless = { version = "0.7", features = ["serde"] }
|
|||||||
serde_json = "1.0.108"
|
serde_json = "1.0.108"
|
||||||
strum = { version = "0.25.0", features = ["derive"] }
|
strum = { version = "0.25.0", features = ["derive"] }
|
||||||
once_cell = "1.19.0"
|
once_cell = "1.19.0"
|
||||||
|
measurements = "0.11.0"
|
||||||
#?bq34z100 required
|
#?bq34z100 required
|
||||||
|
|
||||||
[build-dependencies]
|
[build-dependencies]
|
||||||
|
@ -5,6 +5,4 @@ CONFIG_ESP_MAIN_TASK_STACK_SIZE=20000
|
|||||||
# This allows to use 1 ms granuality for thread sleeps (10 ms by default).
|
# This allows to use 1 ms granuality for thread sleeps (10 ms by default).
|
||||||
CONFIG_FREERTOS_HZ=1000
|
CONFIG_FREERTOS_HZ=1000
|
||||||
|
|
||||||
# Workaround for https://github.com/espressif/esp-idf/issues/7631
|
CONFIG_BOOTLOADER_APP_ROLLBACK_ENABLE=true
|
||||||
#CONFIG_MBEDTLS_CERTIFICATE_BUNDLE=n
|
|
||||||
#CONFIG_MBEDTLS_CERTIFICATE_BUNDLE_DEFAULT_FULL=n
|
|
452
rust/src/bq34z100.rs
Normal file
452
rust/src/bq34z100.rs
Normal file
@ -0,0 +1,452 @@
|
|||||||
|
use embedded_hal::blocking::i2c::{WriteRead, Write, Read};
|
||||||
|
|
||||||
|
const BQ34Z100_G1_ADDRESS:u8 = 0x55;
|
||||||
|
|
||||||
|
//
|
||||||
|
// bq34z100g1.cpp
|
||||||
|
// SMC
|
||||||
|
//
|
||||||
|
// Created by Empire-Phoenix,
|
||||||
|
// directly ported from
|
||||||
|
// https://github.com/xkam1x/BQ34Z100G1/blob/master/bq34z100g1.cpp by Kamran Ahmad on 08/05/2019.
|
||||||
|
//
|
||||||
|
|
||||||
|
impl <I2C, E: std::fmt::Debug> Bq34z100g1 for Bq34z100g1Driver<I2C> where I2C: WriteRead<Error = E> + Write<Error = E> + Read<Error = E> {
|
||||||
|
fn read_register(&mut self, address:u8 , length:u8) -> u16 {
|
||||||
|
let data: [u8;1] = [address];
|
||||||
|
self.i2c.write(BQ34Z100_G1_ADDRESS, &data).unwrap();
|
||||||
|
if length != 1 && length != 2{
|
||||||
|
todo!();
|
||||||
|
}
|
||||||
|
if length == 2 {
|
||||||
|
let mut buffer : [u8;2] = [0_u8,0_u8];
|
||||||
|
let _ = self.i2c.read(BQ34Z100_G1_ADDRESS, &mut buffer);
|
||||||
|
return ((buffer[1] as u16) << 8) | buffer[0] as u16;
|
||||||
|
} else {
|
||||||
|
let mut buffer : [u8;1] = [0_u8];
|
||||||
|
let _ = self.i2c.read(BQ34Z100_G1_ADDRESS, &mut buffer);
|
||||||
|
return buffer[0] as u16;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Wire.beginTransmission(BQ34Z100_G1_ADDRESS);
|
||||||
|
// Wire.write(address);
|
||||||
|
// Wire.endTransmission(false);
|
||||||
|
// Wire.requestFrom(BQ34Z100_G1_ADDRESS, length, true);
|
||||||
|
|
||||||
|
// uint16_t temp = 0;
|
||||||
|
// for (uint8_t i = 0; i < length; i++) {
|
||||||
|
// temp |= Wire.read() << (8 * i);
|
||||||
|
// }
|
||||||
|
// return temp;
|
||||||
|
}
|
||||||
|
|
||||||
|
fn read_control(&mut self,address_lsb:u8, address_msb: u8) -> u16 {
|
||||||
|
let data: [u8;3] = [0x00_u8, address_lsb, address_msb];
|
||||||
|
self.i2c.write(BQ34Z100_G1_ADDRESS, &data).unwrap();
|
||||||
|
return self.read_register(0x00, 2);
|
||||||
|
// Wire.beginTransmission(BQ34Z100_G1_ADDRESS);
|
||||||
|
// Wire.write(0x00);
|
||||||
|
// Wire.write(address_lsb);
|
||||||
|
// Wire.write(address_msb);
|
||||||
|
// Wire.endTransmission(true);
|
||||||
|
// return read_register(0x00, 2);
|
||||||
|
}
|
||||||
|
|
||||||
|
fn read_flash_block(sub_class:u8, offset:u8) {
|
||||||
|
todo!()
|
||||||
|
}
|
||||||
|
|
||||||
|
fn write_reg(address:u8, value:u8 ) {
|
||||||
|
todo!()
|
||||||
|
}
|
||||||
|
|
||||||
|
fn write_flash_block(sub_class:u8 , offset:u8) {
|
||||||
|
todo!()
|
||||||
|
}
|
||||||
|
|
||||||
|
fn flash_block_checksum() -> u8 {
|
||||||
|
todo!()
|
||||||
|
}
|
||||||
|
|
||||||
|
fn xemics_to_f64( value: u32) -> f64 {
|
||||||
|
todo!()
|
||||||
|
}
|
||||||
|
|
||||||
|
fn f64_to_xemics( value:f64) -> u32 {
|
||||||
|
todo!()
|
||||||
|
}
|
||||||
|
|
||||||
|
fn unsealed() {
|
||||||
|
todo!()
|
||||||
|
}
|
||||||
|
|
||||||
|
fn enter_calibration() {
|
||||||
|
todo!()
|
||||||
|
}
|
||||||
|
|
||||||
|
fn exit_calibration() {
|
||||||
|
todo!()
|
||||||
|
}
|
||||||
|
|
||||||
|
fn update_design_capacity(capacity:u16) -> bool {
|
||||||
|
todo!()
|
||||||
|
}
|
||||||
|
|
||||||
|
fn update_q_max(capacity:i16) -> bool {
|
||||||
|
todo!()
|
||||||
|
}
|
||||||
|
|
||||||
|
fn update_design_energy(energy:i16) -> bool {
|
||||||
|
todo!()
|
||||||
|
}
|
||||||
|
|
||||||
|
fn update_cell_charge_voltage_range(t1_t2:u16, t2_t3:u16, t3_t4:u16)-> bool {
|
||||||
|
todo!()
|
||||||
|
}
|
||||||
|
|
||||||
|
fn update_number_of_series_cells(cells:u8)-> bool {
|
||||||
|
todo!()
|
||||||
|
}
|
||||||
|
|
||||||
|
fn update_pack_configuration(config:u16) -> bool {
|
||||||
|
todo!()
|
||||||
|
}
|
||||||
|
|
||||||
|
fn update_charge_termination_parameters(taper_current:i16, min_taper_capacity:i16, cell_taper_voltage:i16,
|
||||||
|
taper_window:u8, tca_set:i8, tca_clear:i8, fc_set:i8, fc_clear:i8) -> bool {
|
||||||
|
todo!()
|
||||||
|
}
|
||||||
|
|
||||||
|
fn calibrate_cc_offset() {
|
||||||
|
todo!()
|
||||||
|
}
|
||||||
|
|
||||||
|
fn calibrate_board_offset() {
|
||||||
|
todo!()
|
||||||
|
}
|
||||||
|
|
||||||
|
fn calibrate_voltage_divider(applied_voltage:u16, cells_count:u8) {
|
||||||
|
todo!()
|
||||||
|
}
|
||||||
|
|
||||||
|
fn calibrate_sense_resistor(applied_current:i16) {
|
||||||
|
todo!()
|
||||||
|
}
|
||||||
|
|
||||||
|
fn set_current_deadband( deadband:u8) {
|
||||||
|
todo!()
|
||||||
|
}
|
||||||
|
|
||||||
|
fn ready() {
|
||||||
|
todo!()
|
||||||
|
}
|
||||||
|
|
||||||
|
fn control_status() -> u16 {
|
||||||
|
todo!()
|
||||||
|
}
|
||||||
|
|
||||||
|
fn device_type() ->u16 {
|
||||||
|
todo!()
|
||||||
|
}
|
||||||
|
|
||||||
|
fn fw_version(&mut self)->u16 {
|
||||||
|
return self.read_control(0x02, 0x00);
|
||||||
|
}
|
||||||
|
|
||||||
|
fn hw_version()->u16 {
|
||||||
|
todo!()
|
||||||
|
}
|
||||||
|
|
||||||
|
fn reset_data() -> u16 {
|
||||||
|
todo!()
|
||||||
|
}
|
||||||
|
|
||||||
|
fn prev_macwrite() -> u16 {
|
||||||
|
todo!()
|
||||||
|
}
|
||||||
|
|
||||||
|
fn chem_id() -> u16 {
|
||||||
|
todo!()
|
||||||
|
}
|
||||||
|
|
||||||
|
fn board_offset() -> u16 {
|
||||||
|
todo!()
|
||||||
|
}
|
||||||
|
|
||||||
|
fn cc_offset() -> u16 {
|
||||||
|
todo!()
|
||||||
|
}
|
||||||
|
|
||||||
|
fn cc_offset_save() -> u16 {
|
||||||
|
todo!()
|
||||||
|
}
|
||||||
|
|
||||||
|
fn df_version() -> u16 {
|
||||||
|
todo!()
|
||||||
|
}
|
||||||
|
|
||||||
|
fn set_fullsleep() -> u16 {
|
||||||
|
todo!()
|
||||||
|
}
|
||||||
|
|
||||||
|
fn static_chem_chksum() -> u16 {
|
||||||
|
todo!()
|
||||||
|
}
|
||||||
|
|
||||||
|
fn sealed() -> u16 {
|
||||||
|
todo!()
|
||||||
|
}
|
||||||
|
|
||||||
|
fn it_enable() -> u16 {
|
||||||
|
todo!()
|
||||||
|
}
|
||||||
|
|
||||||
|
fn cal_enable() -> u16 {
|
||||||
|
todo!()
|
||||||
|
}
|
||||||
|
|
||||||
|
fn reset() -> u16 {
|
||||||
|
todo!()
|
||||||
|
}
|
||||||
|
|
||||||
|
fn exit_cal() -> u16 {
|
||||||
|
todo!()
|
||||||
|
}
|
||||||
|
|
||||||
|
fn enter_cal() -> u16 {
|
||||||
|
todo!()
|
||||||
|
}
|
||||||
|
|
||||||
|
fn offset_cal() -> u16 {
|
||||||
|
todo!()
|
||||||
|
}
|
||||||
|
|
||||||
|
fn state_of_charge() -> u8 {
|
||||||
|
todo!()
|
||||||
|
}
|
||||||
|
|
||||||
|
fn state_of_charge_max_error() -> u8 {
|
||||||
|
todo!()
|
||||||
|
}
|
||||||
|
|
||||||
|
fn remaining_capacity() -> u16 {
|
||||||
|
todo!()
|
||||||
|
}
|
||||||
|
|
||||||
|
fn full_charge_capacity() -> u16 {
|
||||||
|
todo!()
|
||||||
|
}
|
||||||
|
|
||||||
|
fn voltage() -> u16 {
|
||||||
|
todo!()
|
||||||
|
}
|
||||||
|
|
||||||
|
fn average_current() -> i16 {
|
||||||
|
todo!()
|
||||||
|
}
|
||||||
|
|
||||||
|
fn temperature() -> u16 {
|
||||||
|
todo!()
|
||||||
|
}
|
||||||
|
|
||||||
|
fn flags() -> u16 {
|
||||||
|
todo!()
|
||||||
|
}
|
||||||
|
|
||||||
|
fn flags_b() -> u16 {
|
||||||
|
todo!()
|
||||||
|
}
|
||||||
|
|
||||||
|
fn current() -> i16 {
|
||||||
|
todo!()
|
||||||
|
}
|
||||||
|
|
||||||
|
fn average_time_to_empty() -> u16 {
|
||||||
|
todo!()
|
||||||
|
}
|
||||||
|
|
||||||
|
fn average_time_to_full() -> u16 {
|
||||||
|
todo!()
|
||||||
|
}
|
||||||
|
|
||||||
|
fn passed_charge() -> i16 {
|
||||||
|
todo!()
|
||||||
|
}
|
||||||
|
|
||||||
|
fn do_d0_time() -> u16 {
|
||||||
|
todo!()
|
||||||
|
}
|
||||||
|
|
||||||
|
fn available_energy() -> u16 {
|
||||||
|
todo!()
|
||||||
|
}
|
||||||
|
|
||||||
|
fn average_power() -> u16 {
|
||||||
|
todo!()
|
||||||
|
}
|
||||||
|
|
||||||
|
fn serial_number() -> u16 {
|
||||||
|
todo!()
|
||||||
|
}
|
||||||
|
|
||||||
|
fn internal_temperature(&mut self) -> u16 {
|
||||||
|
return self.read_register(0x2a, 2);
|
||||||
|
}
|
||||||
|
|
||||||
|
fn cycle_count() -> u16 {
|
||||||
|
todo!()
|
||||||
|
}
|
||||||
|
|
||||||
|
fn state_of_health() -> u16 {
|
||||||
|
todo!()
|
||||||
|
}
|
||||||
|
|
||||||
|
fn charge_voltage() -> u16 {
|
||||||
|
todo!()
|
||||||
|
}
|
||||||
|
|
||||||
|
fn charge_current() -> u16 {
|
||||||
|
todo!()
|
||||||
|
}
|
||||||
|
|
||||||
|
fn pack_configuration() -> u16 {
|
||||||
|
todo!()
|
||||||
|
}
|
||||||
|
|
||||||
|
fn design_capacity() -> u16 {
|
||||||
|
todo!()
|
||||||
|
}
|
||||||
|
|
||||||
|
fn grid_number() -> u8 {
|
||||||
|
todo!()
|
||||||
|
}
|
||||||
|
|
||||||
|
fn learned_status() -> u8 {
|
||||||
|
todo!()
|
||||||
|
}
|
||||||
|
|
||||||
|
fn dod_at_eoc() -> u16 {
|
||||||
|
todo!()
|
||||||
|
}
|
||||||
|
|
||||||
|
fn q_start() -> u16 {
|
||||||
|
todo!()
|
||||||
|
}
|
||||||
|
|
||||||
|
fn true_fcc() -> u16 {
|
||||||
|
todo!()
|
||||||
|
}
|
||||||
|
|
||||||
|
fn state_time() -> u16 {
|
||||||
|
todo!()
|
||||||
|
}
|
||||||
|
|
||||||
|
fn q_max_passed_q() -> u16 {
|
||||||
|
todo!()
|
||||||
|
}
|
||||||
|
|
||||||
|
fn dod_0() -> u16 {
|
||||||
|
todo!()
|
||||||
|
}
|
||||||
|
|
||||||
|
fn q_max_dod_0() -> u16 {
|
||||||
|
todo!()
|
||||||
|
}
|
||||||
|
|
||||||
|
fn q_max_time() -> u16 {
|
||||||
|
todo!()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
pub struct Bq34z100g1Driver<I2C>{
|
||||||
|
pub i2c: I2C,
|
||||||
|
pub flash_block_data: [u8;32],
|
||||||
|
}
|
||||||
|
pub trait Bq34z100g1 {
|
||||||
|
fn read_register(&mut self, address:u8 , length:u8) -> u16;
|
||||||
|
fn read_control(&mut self, address_lsb:u8, address_msb: u8) -> u16;
|
||||||
|
fn read_flash_block(sub_class:u8, offset:u8);
|
||||||
|
fn write_reg(address:u8, value:u8 );
|
||||||
|
fn write_flash_block(sub_class:u8 , offset:u8);
|
||||||
|
|
||||||
|
fn flash_block_checksum() -> u8;
|
||||||
|
|
||||||
|
fn xemics_to_f64( value: u32) -> f64 ;
|
||||||
|
fn f64_to_xemics( value:f64) -> u32 ;
|
||||||
|
|
||||||
|
fn unsealed();
|
||||||
|
fn enter_calibration();
|
||||||
|
fn exit_calibration();
|
||||||
|
|
||||||
|
fn update_design_capacity(capacity:u16) -> bool;
|
||||||
|
fn update_q_max(capacity:i16) -> bool ;
|
||||||
|
fn update_design_energy(energy:i16) -> bool ;
|
||||||
|
fn update_cell_charge_voltage_range(t1_t2:u16, t2_t3:u16, t3_t4:u16)-> bool ;
|
||||||
|
fn update_number_of_series_cells(cells:u8)-> bool ;
|
||||||
|
fn update_pack_configuration(config:u16) -> bool ;
|
||||||
|
fn update_charge_termination_parameters(taper_current:i16, min_taper_capacity:i16, cell_taper_voltage:i16,
|
||||||
|
taper_window:u8, tca_set:i8, tca_clear:i8, fc_set:i8, fc_clear:i8) -> bool ;
|
||||||
|
fn calibrate_cc_offset();
|
||||||
|
fn calibrate_board_offset();
|
||||||
|
fn calibrate_voltage_divider(applied_voltage:u16, cells_count:u8);
|
||||||
|
fn calibrate_sense_resistor(applied_current:i16);
|
||||||
|
fn set_current_deadband( deadband:u8);
|
||||||
|
fn ready();
|
||||||
|
|
||||||
|
fn control_status() -> u16;
|
||||||
|
fn device_type() ->u16;
|
||||||
|
fn fw_version(&mut self)->u16;
|
||||||
|
fn hw_version()->u16;
|
||||||
|
fn reset_data() -> u16 ;
|
||||||
|
fn prev_macwrite() -> u16 ;
|
||||||
|
fn chem_id() -> u16 ;
|
||||||
|
fn board_offset() -> u16 ;
|
||||||
|
fn cc_offset() -> u16 ;
|
||||||
|
fn cc_offset_save() -> u16 ;
|
||||||
|
fn df_version() -> u16 ;
|
||||||
|
fn set_fullsleep() -> u16 ;
|
||||||
|
fn static_chem_chksum() -> u16 ;
|
||||||
|
fn sealed() -> u16 ;
|
||||||
|
fn it_enable() -> u16 ;
|
||||||
|
fn cal_enable() -> u16 ;
|
||||||
|
fn reset() -> u16 ;
|
||||||
|
fn exit_cal() -> u16 ;
|
||||||
|
fn enter_cal() -> u16 ;
|
||||||
|
fn offset_cal() -> u16 ;
|
||||||
|
|
||||||
|
fn state_of_charge() -> u8 ; // 0 to 100%
|
||||||
|
fn state_of_charge_max_error() -> u8 ; // 1 to 100%
|
||||||
|
fn remaining_capacity() -> u16 ; // mAh
|
||||||
|
fn full_charge_capacity() -> u16 ; // mAh
|
||||||
|
fn voltage() -> u16 ; // mV
|
||||||
|
fn average_current() -> i16; // mA
|
||||||
|
fn temperature() -> u16 ; // Unit of x10 K
|
||||||
|
fn flags() -> u16 ;
|
||||||
|
fn flags_b() -> u16 ;
|
||||||
|
fn current() -> i16; // mA
|
||||||
|
|
||||||
|
fn average_time_to_empty() -> u16; // Minutes
|
||||||
|
fn average_time_to_full() -> u16; // Minutes
|
||||||
|
fn passed_charge() -> i16; // mAh
|
||||||
|
fn do_d0_time() -> u16 ; // Minutes
|
||||||
|
fn available_energy() -> u16 ; // 10 mWh
|
||||||
|
fn average_power() -> u16 ; // 10 mW
|
||||||
|
fn serial_number() -> u16 ;
|
||||||
|
fn internal_temperature(&mut self) -> u16 ; // Unit of x10 K
|
||||||
|
fn cycle_count() -> u16 ; // Counts
|
||||||
|
fn state_of_health() -> u16 ; // 0 to 100%
|
||||||
|
fn charge_voltage() -> u16 ; // mV
|
||||||
|
fn charge_current() -> u16; // mA
|
||||||
|
fn pack_configuration() -> u16 ;
|
||||||
|
fn design_capacity() -> u16 ; // mAh
|
||||||
|
fn grid_number() -> u8 ;
|
||||||
|
fn learned_status() -> u8 ;
|
||||||
|
fn dod_at_eoc() -> u16 ;
|
||||||
|
fn q_start() -> u16; // mAh
|
||||||
|
fn true_fcc() -> u16; // mAh
|
||||||
|
fn state_time() -> u16 ; // s
|
||||||
|
fn q_max_passed_q() -> u16; // mAh
|
||||||
|
fn dod_0() -> u16;
|
||||||
|
fn q_max_dod_0() -> u16;
|
||||||
|
fn q_max_time() -> u16;
|
||||||
|
}
|
@ -18,6 +18,7 @@ use crate::{
|
|||||||
config::{Config, WifiConfig},
|
config::{Config, WifiConfig},
|
||||||
webserver::webserver::{httpd, httpd_initial},
|
webserver::webserver::{httpd, httpd_initial},
|
||||||
};
|
};
|
||||||
|
pub mod bq34z100;
|
||||||
mod config;
|
mod config;
|
||||||
pub mod plant_hal;
|
pub mod plant_hal;
|
||||||
|
|
||||||
@ -49,6 +50,14 @@ enum WaitType {
|
|||||||
StayAlive,
|
StayAlive,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[derive(Serialize, Deserialize, Copy, Clone, Debug, PartialEq, Default)]
|
||||||
|
struct LightState{
|
||||||
|
active: bool,
|
||||||
|
out_of_work_hour: bool,
|
||||||
|
battery_low: bool,
|
||||||
|
is_day: bool
|
||||||
|
}
|
||||||
|
|
||||||
#[derive(Serialize, Deserialize, Copy, Clone, Debug, PartialEq, Default)]
|
#[derive(Serialize, Deserialize, Copy, Clone, Debug, PartialEq, Default)]
|
||||||
struct PlantState {
|
struct PlantState {
|
||||||
a: Option<u8>,
|
a: Option<u8>,
|
||||||
@ -134,11 +143,11 @@ fn map_range_moisture(s: f32) -> Result<u8> {
|
|||||||
fn in_time_range(cur: DateTime<Tz>, start:u8, end:u8) -> bool{
|
fn in_time_range(cur: DateTime<Tz>, start:u8, end:u8) -> bool{
|
||||||
let curhour = cur.hour() as u8;
|
let curhour = cur.hour() as u8;
|
||||||
//eg 10-14
|
//eg 10-14
|
||||||
if(start < end){
|
if start < end {
|
||||||
return curhour > start && curhour < end;
|
return curhour > start && curhour < end;
|
||||||
} else {
|
} else {
|
||||||
//eg 20-05
|
//eg 20-05
|
||||||
return curhour > start || curhour < end;;
|
return curhour > start || curhour < end;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -188,7 +197,7 @@ fn determine_next_plant(plantstate: &mut [PlantState;PLANT_COUNT],cur: DateTime<
|
|||||||
state.out_of_work_hour = true;
|
state.out_of_work_hour = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
if(state.dry && !state.no_water && !state.cooldown && !state.out_of_work_hour){
|
if state.dry && !state.no_water && !state.cooldown && !state.out_of_work_hour {
|
||||||
state.do_water = true;
|
state.do_water = true;
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
@ -210,7 +219,7 @@ fn determine_next_plant(plantstate: &mut [PlantState;PLANT_COUNT],cur: DateTime<
|
|||||||
if !in_time_range(cur, plant_config.pump_hour_start, plant_config.pump_hour_end) {
|
if !in_time_range(cur, plant_config.pump_hour_start, plant_config.pump_hour_end) {
|
||||||
state.out_of_work_hour = true;
|
state.out_of_work_hour = true;
|
||||||
}
|
}
|
||||||
if(!state.cooldown && !state.out_of_work_hour){
|
if !state.cooldown && !state.out_of_work_hour {
|
||||||
state.do_water = true;
|
state.do_water = true;
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
@ -237,7 +246,7 @@ fn determine_next_plant(plantstate: &mut [PlantState;PLANT_COUNT],cur: DateTime<
|
|||||||
return None
|
return None
|
||||||
}
|
}
|
||||||
|
|
||||||
fn main() -> Result<()> {
|
fn safe_main() -> Result<()> {
|
||||||
// It is necessary to call this function once. Otherwise some patches to the runtime
|
// It is necessary to call this function once. Otherwise some patches to the runtime
|
||||||
// implemented by esp-idf-sys might not link properly. See https://github.com/esp-rs/esp-idf-template/issues/71
|
// implemented by esp-idf-sys might not link properly. See https://github.com/esp-rs/esp-idf-template/issues/71
|
||||||
esp_idf_svc::sys::link_patches();
|
esp_idf_svc::sys::link_patches();
|
||||||
@ -281,7 +290,7 @@ fn main() -> Result<()> {
|
|||||||
|
|
||||||
println!("Board hal init");
|
println!("Board hal init");
|
||||||
let mut board: std::sync::MutexGuard<'_, PlantCtrlBoard<'_>> = BOARD_ACCESS.lock().unwrap();
|
let mut board: std::sync::MutexGuard<'_, PlantCtrlBoard<'_>> = BOARD_ACCESS.lock().unwrap();
|
||||||
board.disable_all()?;
|
|
||||||
println!("Mounting filesystem");
|
println!("Mounting filesystem");
|
||||||
board.mount_file_system()?;
|
board.mount_file_system()?;
|
||||||
let free_space = board.file_system_size()?;
|
let free_space = board.file_system_size()?;
|
||||||
@ -475,7 +484,7 @@ fn main() -> Result<()> {
|
|||||||
Ok(temp) => {
|
Ok(temp) => {
|
||||||
//FIXME mqtt here
|
//FIXME mqtt here
|
||||||
println!("Water temp is {}", temp);
|
println!("Water temp is {}", temp);
|
||||||
if(temp < 4_f32){
|
if temp < 4_f32 {
|
||||||
water_frozen = true;
|
water_frozen = true;
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
@ -533,7 +542,21 @@ fn main() -> Result<()> {
|
|||||||
,
|
,
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
let mut light_state = LightState{ ..Default::default() };
|
||||||
|
light_state.is_day = board.is_day();
|
||||||
|
light_state.out_of_work_hour = !in_time_range(europe_time, config.night_lamp_hour_start, config.night_lamp_hour_end);
|
||||||
|
if !light_state.out_of_work_hour {
|
||||||
|
if config.night_lamp_only_when_dark {
|
||||||
|
if !light_state.is_day {
|
||||||
|
board.light(true).unwrap();
|
||||||
|
}
|
||||||
|
}else {
|
||||||
|
board.light(true).unwrap();
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
board.light(false).unwrap();
|
||||||
|
}
|
||||||
|
println!("Lightstate is {:?}", light_state);
|
||||||
|
|
||||||
//check if during light time
|
//check if during light time
|
||||||
//lightstate += out of worktime
|
//lightstate += out of worktime
|
||||||
@ -544,19 +567,14 @@ fn main() -> Result<()> {
|
|||||||
//if no preventing lightstate, enable light
|
//if no preventing lightstate, enable light
|
||||||
//lightstate = active
|
//lightstate = active
|
||||||
|
|
||||||
//keep webserver in scope
|
|
||||||
let webserver = httpd(true);
|
|
||||||
let delay = Delay::new_default();
|
|
||||||
loop {
|
|
||||||
//let freertos do shit
|
|
||||||
delay.delay_ms(1001);
|
|
||||||
}
|
|
||||||
*/
|
|
||||||
//deepsleep here?
|
//deepsleep here?
|
||||||
unsafe { esp_deep_sleep(1000*1000*10) };
|
unsafe { esp_deep_sleep(1000*1000*10) };
|
||||||
Ok(())
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fn main(){
|
||||||
|
let result = safe_main();
|
||||||
|
result.unwrap();
|
||||||
|
}
|
||||||
//error codes
|
//error codes
|
||||||
//error_reading_config_after_upgrade
|
//error_reading_config_after_upgrade
|
||||||
//error_no_config_after_upgrade
|
//error_no_config_after_upgrade
|
||||||
|
@ -1,15 +1,19 @@
|
|||||||
//mod config;
|
//mod config;
|
||||||
|
|
||||||
|
use embedded_hal::blocking::i2c::Operation;
|
||||||
use embedded_svc::wifi::{
|
use embedded_svc::wifi::{
|
||||||
AccessPointConfiguration, AccessPointInfo, AuthMethod, ClientConfiguration, Configuration,
|
AccessPointConfiguration, AccessPointInfo, AuthMethod, ClientConfiguration, Configuration,
|
||||||
};
|
};
|
||||||
|
|
||||||
|
use esp_idf_hal::i2c::{I2cConfig, I2cDriver, APBTickType};
|
||||||
|
use esp_idf_hal::units::FromValueType;
|
||||||
use esp_idf_svc::eventloop::EspSystemEventLoop;
|
use esp_idf_svc::eventloop::EspSystemEventLoop;
|
||||||
use esp_idf_svc::mqtt::client::QoS::ExactlyOnce;
|
use esp_idf_svc::mqtt::client::QoS::ExactlyOnce;
|
||||||
use esp_idf_svc::mqtt::client::{EspMqttClient, MqttClientConfiguration};
|
use esp_idf_svc::mqtt::client::{EspMqttClient, MqttClientConfiguration};
|
||||||
use esp_idf_svc::nvs::EspDefaultNvsPartition;
|
use esp_idf_svc::nvs::EspDefaultNvsPartition;
|
||||||
use esp_idf_svc::wifi::config::{ScanConfig, ScanType};
|
use esp_idf_svc::wifi::config::{ScanConfig, ScanType};
|
||||||
use esp_idf_svc::wifi::EspWifi;
|
use esp_idf_svc::wifi::EspWifi;
|
||||||
|
use measurements::{Measurement, Temperature};
|
||||||
use plant_ctrl2::sipo::ShiftRegister40;
|
use plant_ctrl2::sipo::ShiftRegister40;
|
||||||
|
|
||||||
use anyhow::anyhow;
|
use anyhow::anyhow;
|
||||||
@ -29,7 +33,7 @@ use ds18b20::Ds18b20;
|
|||||||
use embedded_hal::digital::v2::OutputPin;
|
use embedded_hal::digital::v2::OutputPin;
|
||||||
use esp_idf_hal::adc::{attenuation, AdcChannelDriver, AdcDriver};
|
use esp_idf_hal::adc::{attenuation, AdcChannelDriver, AdcDriver};
|
||||||
use esp_idf_hal::delay::Delay;
|
use esp_idf_hal::delay::Delay;
|
||||||
use esp_idf_hal::gpio::{AnyInputPin, Gpio39, Gpio4, Level, PinDriver};
|
use esp_idf_hal::gpio::{AnyInputPin, Gpio39, Gpio4, Level, PinDriver, Pull, InputOutput};
|
||||||
use esp_idf_hal::pcnt::{
|
use esp_idf_hal::pcnt::{
|
||||||
PcntChannel, PcntChannelConfig, PcntControlMode, PcntCountMode, PcntDriver, PinIndex,
|
PcntChannel, PcntChannelConfig, PcntControlMode, PcntCountMode, PcntDriver, PinIndex,
|
||||||
};
|
};
|
||||||
@ -42,6 +46,7 @@ use one_wire_bus::OneWire;
|
|||||||
|
|
||||||
use crate::config::{self, Config, WifiConfig};
|
use crate::config::{self, Config, WifiConfig};
|
||||||
use crate::STAY_ALIVE;
|
use crate::STAY_ALIVE;
|
||||||
|
use crate::bq34z100::{Bq34z100g1Driver, Bq34z100g1};
|
||||||
|
|
||||||
pub const PLANT_COUNT: usize = 8;
|
pub const PLANT_COUNT: usize = 8;
|
||||||
const PINS_PER_PLANT: usize = 5;
|
const PINS_PER_PLANT: usize = 5;
|
||||||
@ -163,7 +168,6 @@ pub trait PlantCtrlBoardInteraction {
|
|||||||
fn test(&mut self) -> Result<()>;
|
fn test(&mut self) -> Result<()>;
|
||||||
fn is_wifi_config_file_existant(&mut self) -> bool;
|
fn is_wifi_config_file_existant(&mut self) -> bool;
|
||||||
fn mqtt(&mut self, config: &Config) -> Result<()>;
|
fn mqtt(&mut self, config: &Config) -> Result<()>;
|
||||||
fn disable_all(&mut self) -> Result<()>;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
pub trait CreatePlantHal<'a> {
|
pub trait CreatePlantHal<'a> {
|
||||||
@ -174,9 +178,9 @@ pub struct PlantHal {}
|
|||||||
|
|
||||||
pub struct PlantCtrlBoard<'a> {
|
pub struct PlantCtrlBoard<'a> {
|
||||||
shift_register: ShiftRegister40<
|
shift_register: ShiftRegister40<
|
||||||
PinDriver<'a, esp_idf_hal::gpio::Gpio21, esp_idf_hal::gpio::Output>,
|
PinDriver<'a, esp_idf_hal::gpio::Gpio21, InputOutput>,
|
||||||
PinDriver<'a, esp_idf_hal::gpio::Gpio22, esp_idf_hal::gpio::Output>,
|
PinDriver<'a, esp_idf_hal::gpio::Gpio22, InputOutput>,
|
||||||
PinDriver<'a, esp_idf_hal::gpio::Gpio19, esp_idf_hal::gpio::Output>,
|
PinDriver<'a, esp_idf_hal::gpio::Gpio19, InputOutput>,
|
||||||
>,
|
>,
|
||||||
consecutive_watering_plant: Mutex<[u32; PLANT_COUNT]>,
|
consecutive_watering_plant: Mutex<[u32; PLANT_COUNT]>,
|
||||||
last_watering_timestamp: Mutex<[i64; PLANT_COUNT]>,
|
last_watering_timestamp: Mutex<[i64; PLANT_COUNT]>,
|
||||||
@ -186,10 +190,10 @@ pub struct PlantCtrlBoard<'a> {
|
|||||||
solar_is_day: PinDriver<'a, esp_idf_hal::gpio::Gpio25, esp_idf_hal::gpio::Input>,
|
solar_is_day: PinDriver<'a, esp_idf_hal::gpio::Gpio25, esp_idf_hal::gpio::Input>,
|
||||||
boot_button: PinDriver<'a, esp_idf_hal::gpio::Gpio0, esp_idf_hal::gpio::Input>,
|
boot_button: PinDriver<'a, esp_idf_hal::gpio::Gpio0, esp_idf_hal::gpio::Input>,
|
||||||
signal_counter: PcntDriver<'a>,
|
signal_counter: PcntDriver<'a>,
|
||||||
light: PinDriver<'a, esp_idf_hal::gpio::Gpio26, esp_idf_hal::gpio::Output>,
|
light: PinDriver<'a, esp_idf_hal::gpio::Gpio26, InputOutput>,
|
||||||
main_pump: PinDriver<'a, esp_idf_hal::gpio::Gpio23, esp_idf_hal::gpio::Output>,
|
main_pump: PinDriver<'a, esp_idf_hal::gpio::Gpio23, InputOutput>,
|
||||||
tank_power: PinDriver<'a, esp_idf_hal::gpio::Gpio27, esp_idf_hal::gpio::Output>,
|
tank_power: PinDriver<'a, esp_idf_hal::gpio::Gpio27, InputOutput>,
|
||||||
general_fault: PinDriver<'a, esp_idf_hal::gpio::Gpio13, esp_idf_hal::gpio::Output>,
|
general_fault: PinDriver<'a, esp_idf_hal::gpio::Gpio13, InputOutput>,
|
||||||
pub wifi_driver: EspWifi<'a>,
|
pub wifi_driver: EspWifi<'a>,
|
||||||
one_wire_bus: OneWire<PinDriver<'a, Gpio4, esp_idf_hal::gpio::InputOutput>>,
|
one_wire_bus: OneWire<PinDriver<'a, Gpio4, esp_idf_hal::gpio::InputOutput>>,
|
||||||
mqtt_client: Option<EspMqttClient<'a>>,
|
mqtt_client: Option<EspMqttClient<'a>>,
|
||||||
@ -660,26 +664,54 @@ impl PlantCtrlBoardInteraction for PlantCtrlBoard<'_> {
|
|||||||
}
|
}
|
||||||
bail!("Mqtt did not complete roundtrip in time");
|
bail!("Mqtt did not complete roundtrip in time");
|
||||||
}
|
}
|
||||||
|
|
||||||
fn disable_all(&mut self) -> Result<()> {
|
|
||||||
for mut pin in self.shift_register.decompose() {
|
|
||||||
pin.set_low().unwrap();
|
|
||||||
}
|
|
||||||
self.general_fault(false);
|
|
||||||
self.any_pump(false)?;
|
|
||||||
return Ok(());
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
impl CreatePlantHal<'_> for PlantHal {
|
impl CreatePlantHal<'_> for PlantHal {
|
||||||
fn create() -> Result<Mutex<PlantCtrlBoard<'static>>> {
|
fn create() -> Result<Mutex<PlantCtrlBoard<'static>>> {
|
||||||
let peripherals = Peripherals::take()?;
|
let peripherals = Peripherals::take()?;
|
||||||
|
|
||||||
let clock = PinDriver::output(peripherals.pins.gpio21)?;
|
let i2c = peripherals.i2c1;
|
||||||
let latch = PinDriver::output(peripherals.pins.gpio22)?;
|
let config = I2cConfig::new()
|
||||||
let data = PinDriver::output(peripherals.pins.gpio19)?;
|
.scl_enable_pullup(false)
|
||||||
|
.sda_enable_pullup(false)
|
||||||
|
.timeout(Duration::from_millis(10).into())
|
||||||
|
.baudrate(10_u32.kHz().into());
|
||||||
|
let scl = peripherals.pins.gpio16;
|
||||||
|
let sda = peripherals.pins.gpio17;
|
||||||
|
|
||||||
let one_wire_pin = PinDriver::input_output_od(peripherals.pins.gpio4)?;
|
|
||||||
|
let driver = I2cDriver::new(i2c, sda, scl, &config).unwrap();
|
||||||
|
let mut battery_driver :Bq34z100g1Driver<I2cDriver> = Bq34z100g1Driver{
|
||||||
|
i2c :driver,
|
||||||
|
flash_block_data : [0;32],
|
||||||
|
};
|
||||||
|
|
||||||
|
let fwversion = battery_driver.fw_version();
|
||||||
|
println!("fw version is {}", fwversion);
|
||||||
|
loop {
|
||||||
|
let bat_temp = battery_driver.internal_temperature();
|
||||||
|
let temp_c = Temperature::from_kelvin(bat_temp as f64/10_f64).as_celsius();
|
||||||
|
println!("bat int temp is is {}", temp_c);
|
||||||
|
unsafe{
|
||||||
|
vTaskDelay(1000);
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
let mut clock = PinDriver::input_output(peripherals.pins.gpio21)?;
|
||||||
|
clock.set_pull(Pull::Floating);
|
||||||
|
let mut latch = PinDriver::input_output(peripherals.pins.gpio22)?;
|
||||||
|
latch.set_pull(Pull::Floating);
|
||||||
|
let mut data = PinDriver::input_output(peripherals.pins.gpio19)?;
|
||||||
|
data.set_pull(Pull::Floating);
|
||||||
|
let shift_register = ShiftRegister40::new(clock.into(), latch.into(), data.into());
|
||||||
|
for mut pin in shift_register.decompose() {
|
||||||
|
pin.set_low().unwrap();
|
||||||
|
}
|
||||||
|
|
||||||
|
let mut one_wire_pin = PinDriver::input_output_od(peripherals.pins.gpio4)?;
|
||||||
|
one_wire_pin.set_pull(Pull::Floating);
|
||||||
//TODO make to none if not possible to init
|
//TODO make to none if not possible to init
|
||||||
|
|
||||||
//init,reset rtc memory depending on cause
|
//init,reset rtc memory depending on cause
|
||||||
@ -744,7 +776,7 @@ impl CreatePlantHal<'_> for PlantHal {
|
|||||||
let nvs = EspDefaultNvsPartition::take()?;
|
let nvs = EspDefaultNvsPartition::take()?;
|
||||||
let wifi_driver = EspWifi::new(peripherals.modem, sys_loop, Some(nvs))?;
|
let wifi_driver = EspWifi::new(peripherals.modem, sys_loop, Some(nvs))?;
|
||||||
|
|
||||||
let shift_register = ShiftRegister40::new(clock, latch, data);
|
|
||||||
let last_watering_timestamp = Mutex::new(unsafe { LAST_WATERING_TIMESTAMP });
|
let last_watering_timestamp = Mutex::new(unsafe { LAST_WATERING_TIMESTAMP });
|
||||||
let consecutive_watering_plant = Mutex::new(unsafe { CONSECUTIVE_WATERING_PLANT });
|
let consecutive_watering_plant = Mutex::new(unsafe { CONSECUTIVE_WATERING_PLANT });
|
||||||
let low_voltage_detected = Mutex::new(unsafe { LOW_VOLTAGE_DETECTED });
|
let low_voltage_detected = Mutex::new(unsafe { LOW_VOLTAGE_DETECTED });
|
||||||
@ -752,12 +784,22 @@ impl CreatePlantHal<'_> for PlantHal {
|
|||||||
AdcDriver::new(peripherals.adc1, &esp_idf_hal::adc::config::Config::new())?;
|
AdcDriver::new(peripherals.adc1, &esp_idf_hal::adc::config::Config::new())?;
|
||||||
let tank_channel: AdcChannelDriver<'_, { attenuation::DB_11 }, Gpio39> =
|
let tank_channel: AdcChannelDriver<'_, { attenuation::DB_11 }, Gpio39> =
|
||||||
AdcChannelDriver::new(peripherals.pins.gpio39)?;
|
AdcChannelDriver::new(peripherals.pins.gpio39)?;
|
||||||
let solar_is_day = PinDriver::input(peripherals.pins.gpio25)?;
|
|
||||||
let boot_button = PinDriver::input(peripherals.pins.gpio0)?;
|
let mut solar_is_day = PinDriver::input(peripherals.pins.gpio25)?;
|
||||||
let light = PinDriver::output(peripherals.pins.gpio26)?;
|
solar_is_day.set_pull(Pull::Floating)?;
|
||||||
let main_pump = PinDriver::output(peripherals.pins.gpio23)?;
|
|
||||||
let tank_power = PinDriver::output(peripherals.pins.gpio27)?;
|
let mut boot_button = PinDriver::input(peripherals.pins.gpio0)?;
|
||||||
let general_fault = PinDriver::output(peripherals.pins.gpio13)?;
|
boot_button.set_pull(Pull::Floating)?;
|
||||||
|
let mut light = PinDriver::input_output(peripherals.pins.gpio26)?;
|
||||||
|
light.set_pull(Pull::Floating)?;
|
||||||
|
let mut main_pump = PinDriver::input_output(peripherals.pins.gpio23)?;
|
||||||
|
main_pump.set_pull(Pull::Floating)?;
|
||||||
|
main_pump.set_low()?;
|
||||||
|
let mut tank_power = PinDriver::input_output(peripherals.pins.gpio27)?;
|
||||||
|
tank_power.set_pull(Pull::Floating)?;
|
||||||
|
let mut general_fault = PinDriver::input_output(peripherals.pins.gpio13)?;
|
||||||
|
general_fault.set_pull(Pull::Floating)?;
|
||||||
|
general_fault.set_low()?;
|
||||||
let one_wire_bus = OneWire::new(one_wire_pin)
|
let one_wire_bus = OneWire::new(one_wire_pin)
|
||||||
.map_err(|err| -> anyhow::Error { anyhow!("Missing attribute: {:?}", err) })?;
|
.map_err(|err| -> anyhow::Error { anyhow!("Missing attribute: {:?}", err) })?;
|
||||||
|
|
||||||
|
Loading…
Reference in New Issue
Block a user