canbus sensor stub and pcnt impl

This commit is contained in:
2025-10-01 00:36:15 +02:00
parent cf58486cf5
commit 9c6dcc465e
11 changed files with 307 additions and 177 deletions

View File

@@ -160,6 +160,8 @@ option-lock = { version = "0.3.1", default-features = false }
#stay in sync with mcutie version here!
heapless = { version = "0.7.17", features = ["serde"] }
mcutie = { version = "0.3.0", default-features = false, features = ["log", "homeassistant"] }
nb = "1.1.0"
embedded-can = "0.4.1"
@@ -168,4 +170,4 @@ mcutie = { git = 'https://github.com/empirephoenix/mcutie.git' }
#bq34z100 = { path = "../../bq34z100_rust" }
[build-dependencies]
vergen = { version = "8.2.6", features = ["build", "git", "gitcl"] }
vergen = { version = "8.2.6", features = ["build", "git", "gitcl"] }

View File

@@ -8,6 +8,7 @@ use embassy_executor::SpawnError;
use embassy_sync::mutex::TryLockError;
use esp_hal::i2c::master::ConfigError;
use esp_hal::pcnt::unit::{InvalidHighLimit, InvalidLowLimit};
use esp_hal::twai::EspTwaiError;
use esp_wifi::wifi::WifiError;
use ina219::errors::{BusVoltageReadError, ShuntVoltageReadError};
use littlefs2_core::PathError;
@@ -60,6 +61,9 @@ pub enum FatError {
ExpanderError {
error: String,
},
CanBusError {
error: EspTwaiError,
},
}
pub type FatResult<T> = Result<T, FatError>;
@@ -88,6 +92,9 @@ impl fmt::Display for FatError {
FatError::DS323 { error } => write!(f, "DS323 {:?}", error),
FatError::Eeprom24x { error } => write!(f, "Eeprom24x {:?}", error),
FatError::ExpanderError { error } => write!(f, "ExpanderError {:?}", error),
FatError::CanBusError { error } => {
write!(f, "CanBusError {:?}", error)
}
}
}
}
@@ -279,3 +286,14 @@ impl From<InvalidHighLimit> for FatError {
}
}
}
impl From<nb::Error<EspTwaiError>> for FatError {
fn from(value: nb::Error<EspTwaiError>) -> Self {
match value {
nb::Error::Other(can_error) => FatError::CanBusError { error: can_error },
nb::Error::WouldBlock => FatError::String {
error: "Would block".to_string(),
},
}
}
}

20
rust/src/hal/can_api.rs Normal file
View File

@@ -0,0 +1,20 @@
use bincode::{Decode, Encode};
pub(crate) const SENSOR_BASE_ADDRESS: u16 = 1000;
#[derive(Debug, Clone, Copy, Encode, Decode)]
pub(crate) struct RequestMoisture {
pub(crate) sensor: Sensor,
}
#[derive(Debug, Clone, Copy, Encode, Decode)]
pub(crate) struct ResponseMoisture {
pub plant: u8,
pub sensor: Sensor,
pub hz: u32,
}
#[derive(Debug, Clone, Copy, Encode, Decode, PartialEq, Eq)]
pub(crate) enum Sensor {
A,
B,
}

View File

@@ -892,8 +892,8 @@ async fn mqtt_incoming_task(
MQTT_CONNECTED_EVENT_RECEIVED.store(true, Ordering::Relaxed);
}
MqttMessage::Publish(topic, payload) => match topic {
Topic::DeviceType(type_topic) => {}
Topic::Device(device_topic) => {}
Topic::DeviceType(_type_topic) => {}
Topic::Device(_device_topic) => {}
Topic::General(topic) => {
let subtopic = topic.as_str();

View File

@@ -1,4 +1,5 @@
pub(crate) mod battery;
mod can_api;
pub mod esp;
mod initial_hal;
mod little_fs2storage_adapter;
@@ -13,7 +14,6 @@ use crate::alloc::string::ToString;
use crate::hal::rtc::{DS3231Module, RTCModuleInteraction};
use esp_hal::peripherals::Peripherals;
use esp_hal::peripherals::ADC1;
use esp_hal::peripherals::APB_SARADC;
use esp_hal::peripherals::GPIO0;
use esp_hal::peripherals::GPIO10;
use esp_hal::peripherals::GPIO11;
@@ -41,7 +41,6 @@ use esp_hal::peripherals::GPIO5;
use esp_hal::peripherals::GPIO6;
use esp_hal::peripherals::GPIO7;
use esp_hal::peripherals::GPIO8;
use esp_hal::peripherals::PCNT;
use esp_hal::peripherals::TWAI0;
use crate::{

View File

@@ -20,7 +20,6 @@ use embassy_time::Timer;
use embedded_hal::digital::OutputPin as _;
use esp_hal::gpio::{Flex, Input, InputConfig, Level, Output, OutputConfig, Pull};
use esp_hal::pcnt::channel::CtrlMode::Keep;
use esp_hal::pcnt::channel::EdgeMode;
use esp_hal::pcnt::channel::EdgeMode::{Hold, Increment};
use esp_hal::pcnt::unit::Unit;
use measurements::{Current, Voltage};
@@ -146,7 +145,6 @@ pub(crate) fn create_v3(
let signal_counter = peripherals.pcnt0;
signal_counter.set_low_limit(Some(0))?;
signal_counter.set_high_limit(Some(i16::MAX))?;
let ch0 = &signal_counter.channel0;

View File

@@ -1,28 +1,25 @@
use crate::bail;
use crate::config::PlantControllerConfig;
use crate::fat_error::{FatError, FatResult};
use crate::hal::battery::BatteryInteraction;
use crate::hal::esp::{hold_disable, hold_enable, Esp};
use crate::hal::rtc::RTCModuleInteraction;
use crate::hal::v4_sensor::{SensorImpl, SensorInteraction};
use crate::hal::water::TankSensor;
use crate::hal::{BoardInteraction, FreePeripherals, Sensor, I2C_DRIVER, PLANT_COUNT, TIME_ACCESS};
use crate::log::{LogMessage, LOG_ACCESS};
use alloc::boxed::Box;
use alloc::string::ToString;
use async_trait::async_trait;
use embassy_embedded_hal::shared_bus::blocking::i2c::I2cDevice;
use embassy_sync::blocking_mutex::raw::CriticalSectionRawMutex;
use embassy_time::Timer;
use esp_hal::{twai, Blocking};
//use embedded_hal_bus::i2c::MutexDevice;
use crate::bail;
use crate::fat_error::{FatError, FatResult};
use crate::hal::v4_sensor::{SensorImpl, SensorInteraction};
use crate::log::{LogMessage, LOG_ACCESS};
use esp_hal::gpio::{Flex, Input, InputConfig, Level, Output, OutputConfig, Pull};
use esp_hal::i2c::master::I2c;
use esp_hal::pcnt::channel::CtrlMode::Keep;
use esp_hal::pcnt::channel::EdgeMode::{Hold, Increment};
use esp_hal::pcnt::Pcnt;
use esp_hal::twai::{EspTwaiFrame, StandardId, TwaiMode};
use esp_println::println;
use esp_hal::twai::TwaiMode;
use esp_hal::{twai, Blocking};
use ina219::address::{Address, Pin};
use ina219::calibration::UnCalibrated;
use ina219::configuration::{Configuration, OperatingMode, Resolution};
@@ -179,7 +176,6 @@ pub(crate) async fn create_v4(
let signal_counter = peripherals.pcnt0;
signal_counter.set_low_limit(Some(0))?;
signal_counter.set_high_limit(Some(i16::MAX))?;
let ch0 = &signal_counter.channel0;
@@ -203,23 +199,20 @@ pub(crate) async fn create_v4(
}
Err(_) => {
log::info!("Can bus mode ");
let twai_config = twai::TwaiConfiguration::new(
let twai_config = Some(twai::TwaiConfiguration::new(
peripherals.twai,
peripherals.gpio0,
peripherals.gpio2,
TWAI_BAUDRATE,
TwaiMode::Normal,
);
));
let can_power = Output::new(peripherals.gpio22, Level::Low, OutputConfig::default());
let mut twai = twai_config.start();
let frame = EspTwaiFrame::new(StandardId::ZERO, &[1, 2, 3]).unwrap();
twai.transmit(&frame).unwrap();
// let frame = twai.receive().unwrap();
println!("Received a frame: {frame:?}");
//can bus version
SensorImpl::CanBus { twai }
SensorImpl::CanBus {
twai_config,
can_power,
}
}
};
@@ -409,6 +402,14 @@ impl<'a> BoardInteraction<'a> for V4<'a> {
Timer::after_millis(100).await;
self.general_fault(false).await;
Timer::after_millis(500).await;
self.extra1.set_high();
Timer::after_millis(500).await;
self.extra1.set_low();
Timer::after_millis(500).await;
self.extra2.set_high();
Timer::after_millis(500).await;
self.extra2.set_low();
Timer::after_millis(500).await;
self.light(true).await?;
Timer::after_millis(500).await;
self.light(false).await?;

View File

@@ -1,17 +1,25 @@
use crate::fat_error::{FatError, FatResult};
use crate::hal::Box;
use crate::bail;
use crate::fat_error::{ContextExt, FatError, FatResult};
use crate::hal::can_api::ResponseMoisture;
use crate::hal::Sensor;
use crate::hal::{can_api, Box};
use crate::log::{LogMessage, LOG_ACCESS};
use alloc::format;
use alloc::string::ToString;
use async_trait::async_trait;
use bincode::config;
use bincode::error::DecodeError;
use can_api::RequestMoisture;
use embassy_embedded_hal::shared_bus::blocking::i2c::I2cDevice;
use embassy_sync::blocking_mutex::raw::CriticalSectionRawMutex;
use embassy_time::Timer;
use embassy_time::{Instant, Timer};
use embedded_can::Frame;
use esp_hal::gpio::Output;
use esp_hal::i2c::master::I2c;
use esp_hal::pcnt::unit::Unit;
use esp_hal::twai::Twai;
use esp_hal::twai::{EspTwaiFrame, StandardId, Twai, TwaiConfiguration};
use esp_hal::Blocking;
use log::info;
use pca9535::{GPIOBank, Pca9535Immediate, StandardExpanderInterface};
const REPEAT_MOIST_MEASURE: usize = 10;
@@ -35,7 +43,8 @@ pub enum SensorImpl {
Pca9535Immediate<I2cDevice<'static, CriticalSectionRawMutex, I2c<'static, Blocking>>>,
},
CanBus {
twai: Twai<'static, Blocking>,
twai_config: Option<TwaiConfiguration<'static, Blocking>>,
can_power: Output<'static>,
},
}
@@ -122,9 +131,95 @@ impl SensorInteraction for SensorImpl {
let median = results[mid];
Ok(median)
}
SensorImpl::CanBus { twai } => Err(FatError::String {
error: "Not yet implemented".to_string(),
}),
SensorImpl::CanBus {
twai_config,
can_power,
} => {
can_power.set_high();
let config = twai_config.take().expect("twai config not set");
let mut twai = config.start();
Timer::after_millis(10).await;
let can = Self::inner_can(plant, sensor, &mut twai).await;
can_power.set_low();
let config = twai.stop();
twai_config.replace(config);
let value = can?;
Ok(value)
}
}
}
}
impl SensorImpl {
async fn inner_can(
plant: usize,
sensor: Sensor,
twai: &mut Twai<'static, Blocking>,
) -> FatResult<f32> {
let can_sensor: can_api::Sensor = sensor.into();
let request = RequestMoisture { sensor: can_sensor };
let mut can_buffer = [0_u8; 8];
let config = config::standard();
let encoded = bincode::encode_into_slice(&request, &mut can_buffer, config)?;
let address = StandardId::new(can_api::SENSOR_BASE_ADDRESS + plant as u16)
.context(">> Could not create address for sensor! (plant: {}) <<")?;
let request = EspTwaiFrame::new(address, &can_buffer[0..encoded])
.context("Error building CAN frame")?;
twai.transmit(&request)?;
let timeout = Instant::now()
.checked_add(embassy_time::Duration::from_millis(100))
.context("Timeout")?;
loop {
let answer = twai.receive();
match answer {
Ok(answer) => {
let data = EspTwaiFrame::data(&answer);
let response: Result<(ResponseMoisture, usize), DecodeError> =
bincode::decode_from_slice(&data, config);
info!("Can answer {response:?}");
let value = response?.0;
if (value.plant as usize) != plant {
bail!(
"Received answer for wrong plant! Expected: {}, got: {}",
plant,
value.plant
);
}
if value.sensor != can_sensor {
bail!(
"Received answer for wrong sensor! Expected: {:?}, got: {:?}",
can_sensor,
value.sensor
);
}
return Ok(value.hz as f32);
}
Err(error) => match error {
nb::Error::Other(error) => {
return Err(FatError::CanBusError { error });
}
nb::Error::WouldBlock => {
if Instant::now() > timeout {
bail!("Timeout waiting for CAN answer");
}
Timer::after_millis(10).await;
}
},
}
}
}
}
impl From<Sensor> for can_api::Sensor {
fn from(value: Sensor) -> Self {
match value {
Sensor::A => can_api::Sensor::A,
Sensor::B => can_api::Sensor::B,
}
}
}

View File

@@ -5,6 +5,8 @@ use embassy_time::Timer;
use esp_hal::analog::adc::{Adc, AdcConfig, AdcPin, Attenuation};
use esp_hal::delay::Delay;
use esp_hal::gpio::{Flex, Input, Output, OutputConfig, Pull};
use esp_hal::pcnt::channel::CtrlMode::Keep;
use esp_hal::pcnt::channel::EdgeMode::{Hold, Increment};
use esp_hal::pcnt::unit::Unit;
use esp_hal::peripherals::GPIO5;
use esp_hal::Blocking;
@@ -16,8 +18,7 @@ pub struct TankSensor<'a> {
tank_channel: Adc<'a, ADC1<'a>, Blocking>,
tank_power: Output<'a>,
tank_pin: AdcPin<GPIO5<'a>, ADC1<'a>>,
// flow_counter: PcntDriver<'a>,
// delay: Delay,
flow_counter: Unit<'a, 1>,
}
impl<'a> TankSensor<'a> {
@@ -37,54 +38,38 @@ impl<'a> TankSensor<'a> {
let one_wire_bus = OneWire::new(one_wire_pin, false);
//
// let mut flow_counter = PcntDriver::new(
// pcnt1,
// Some(flow_sensor_pin),
// Option::<AnyInputPin>::None,
// Option::<AnyInputPin>::None,
// Option::<AnyInputPin>::None,
// )?;
//
// flow_counter.channel_config(
// PcntChannel::Channel1,
// PinIndex::Pin0,
// PinIndex::Pin1,
// &PcntChannelConfig {
// lctrl_mode: PcntControlMode::Keep,
// hctrl_mode: PcntControlMode::Keep,
// pos_mode: PcntCountMode::Increment,
// neg_mode: PcntCountMode::Hold,
// counter_h_lim: i16::MAX,
// counter_l_lim: 0,
// },
// )?;
//
pcnt1.set_high_limit(Some(i16::MAX))?;
let ch0 = &pcnt1.channel0;
ch0.set_edge_signal(flow_sensor.peripheral_input());
ch0.set_input_mode(Hold, Increment);
ch0.set_ctrl_mode(Keep, Keep);
pcnt1.listen();
Ok(TankSensor {
one_wire_bus,
tank_channel,
tank_power,
tank_pin, // flow_counter,
// delay: Default::default(),
tank_pin,
flow_counter: pcnt1,
})
}
pub fn reset_flow_meter(&mut self) {
// self.flow_counter.counter_pause().unwrap();
// self.flow_counter.counter_clear().unwrap();
self.flow_counter.pause();
self.flow_counter.clear();
}
pub fn start_flow_meter(&mut self) {
//self.flow_counter.counter_resume().unwrap();
self.flow_counter.resume();
}
pub fn get_flow_meter_value(&mut self) -> i16 {
//self.flow_counter.get_counter_value().unwrap()
5_i16
self.flow_counter.value()
}
pub fn stop_flow_meter(&mut self) -> i16 {
//self.flow_counter.counter_pause().unwrap();
self.flow_counter.pause();
self.get_flow_meter_value()
}

View File

@@ -77,6 +77,20 @@ impl From<LogEntryInner> for LogEntry {
}
}
pub async fn log(
message_key: LogMessage,
number_a: u32,
number_b: u32,
txt_short: &str,
txt_long: &str,
) {
LOG_ACCESS
.lock()
.await
.log(message_key, number_a, number_b, txt_short, txt_long)
.await
}
impl LogArray {
pub fn get(&mut self) -> Vec<LogEntry> {
let head: RangedU8<0, MAX_LOG_ARRAY_INDEX> =

View File

@@ -17,7 +17,7 @@ use crate::config::{NetworkConfig, PlantConfig};
use crate::fat_error::FatResult;
use crate::hal::esp::MQTT_STAY_ALIVE;
use crate::hal::{esp_time, TIME_ACCESS};
use crate::log::LOG_ACCESS;
use crate::log::{log, LOG_ACCESS};
use crate::tank::{determine_tank_state, TankError, TankState, WATER_FROZEN_THRESH};
use crate::webserver::http_server;
use crate::{
@@ -326,7 +326,7 @@ async fn safe_main(spawner: Spawner) -> FatResult<()> {
.await;
}
let _dry_run = false;
let dry_run = false;
let tank_state = determine_tank_state(&mut board).await;
@@ -383,7 +383,7 @@ async fn safe_main(spawner: Spawner) -> FatResult<()> {
}
}
let mut _water_frozen = false;
let mut water_frozen = false;
let water_temp: FatResult<f32> = match board.board_hal.get_tank_sensor() {
Ok(sensor) => sensor.water_temperature_c().await,
Err(e) => Err(e),
@@ -391,7 +391,7 @@ async fn safe_main(spawner: Spawner) -> FatResult<()> {
if let Ok(res) = water_temp {
if res < WATER_FROZEN_THRESH {
_water_frozen = true;
water_frozen = true;
}
}
info!("Water temp is {}", water_temp.as_ref().unwrap_or(&0.));
@@ -411,74 +411,81 @@ async fn safe_main(spawner: Spawner) -> FatResult<()> {
publish_plant_states(&mut board, &timezone_time.clone(), &plantstate).await;
// let pump_required = plantstate
// .iter()
// .zip(&board.board_hal.get_config().plants)
// .any(|(it, conf)| it.needs_to_be_watered(conf, &timezone_time))
// && !water_frozen;
// if pump_required {
// log(LogMessage::EnableMain, dry_run as u32, 0, "", "");
// for (plant_id, (state, plant_config)) in plantstate
// .iter()
// .zip(&board.board_hal.get_config().plants.clone())
// .enumerate()
// {
// if state.needs_to_be_watered(plant_config, &timezone_time) {
// let pump_count = board.board_hal.get_esp().consecutive_pump_count(plant_id) + 1;
// board
// .board_hal
// .get_esp()
// .store_consecutive_pump_count(plant_id, pump_count);
//
// let pump_ineffective = pump_count > plant_config.max_consecutive_pump_count as u32;
// if pump_ineffective {
// log(
// LogMessage::ConsecutivePumpCountLimit,
// pump_count,
// plant_config.max_consecutive_pump_count as u32,
// &(plant_id + 1).to_string(),
// "",
// );
// board.board_hal.fault(plant_id, true).await?;
// }
// log(
// LogMessage::PumpPlant,
// (plant_id + 1) as u32,
// plant_config.pump_time_s as u32,
// &dry_run.to_string(),
// "",
// );
// board
// .board_hal
// .get_esp()
// .store_last_pump_time(plant_id, cur);
// board.board_hal.get_esp().last_pump_time(plant_id);
// //state.active = true;
//
// pump_info(plant_id, true, pump_ineffective, 0, 0, 0, false).await;
//
// let result = do_secure_pump(plant_id, plant_config, dry_run).await?;
// board.board_hal.pump(plant_id, false).await?;
// pump_info(
// plant_id,
// false,
// pump_ineffective,
// result.median_current_ma,
// result.max_current_ma,
// result.min_current_ma,
// result.error,
// )
// .await;
// } else if !state.pump_in_timeout(plant_config, &timezone_time) {
// // plant does not need to be watered and is not in timeout
// // -> reset consecutive pump count
// board
// .board_hal
// .get_esp()
// .store_consecutive_pump_count(plant_id, 0);
// }
// }
// }
let pump_required = plantstate
.iter()
.zip(&board.board_hal.get_config().plants)
.any(|(it, conf)| it.needs_to_be_watered(conf, &timezone_time))
&& !water_frozen;
if pump_required {
LOG_ACCESS
.lock()
.await
.log(LogMessage::EnableMain, dry_run as u32, 0, "", "")
.await;
for (plant_id, (state, plant_config)) in plantstate
.iter()
.zip(&board.board_hal.get_config().plants.clone())
.enumerate()
{
if state.needs_to_be_watered(plant_config, &timezone_time) {
let pump_count = board.board_hal.get_esp().consecutive_pump_count(plant_id) + 1;
board
.board_hal
.get_esp()
.store_consecutive_pump_count(plant_id, pump_count);
let pump_ineffective = pump_count > plant_config.max_consecutive_pump_count as u32;
if pump_ineffective {
log(
LogMessage::ConsecutivePumpCountLimit,
pump_count,
plant_config.max_consecutive_pump_count as u32,
&(plant_id + 1).to_string(),
"",
)
.await;
board.board_hal.fault(plant_id, true).await?;
}
log(
LogMessage::PumpPlant,
(plant_id + 1) as u32,
plant_config.pump_time_s as u32,
&dry_run.to_string(),
"",
)
.await;
board
.board_hal
.get_esp()
.store_last_pump_time(plant_id, cur);
board.board_hal.get_esp().last_pump_time(plant_id);
//state.active = true;
pump_info(plant_id, true, pump_ineffective, 0, 0, 0, false).await;
let result = do_secure_pump(&mut board, plant_id, plant_config, dry_run).await?;
//stop pump regardless of prior result//todo refactor to inner?
board.board_hal.pump(plant_id, false).await?;
pump_info(
plant_id,
false,
pump_ineffective,
result.median_current_ma,
result.max_current_ma,
result.min_current_ma,
result.error,
)
.await;
} else if !state.pump_in_timeout(plant_config, &timezone_time) {
// plant does not need to be watered and is not in timeout
// -> reset consecutive pump count
board
.board_hal
.get_esp()
.store_consecutive_pump_count(plant_id, 0);
}
}
}
info!("state of charg");
let is_day = board.board_hal.is_day();
@@ -671,17 +678,14 @@ pub async fn do_secure_pump(
let high_current = current_ma > plant_config.max_pump_current_ma;
if high_current {
if first_error {
LOG_ACCESS
.lock()
.await
.log(
LogMessage::PumpOverCurrent,
plant_id as u32 + 1,
current_ma as u32,
plant_config.max_pump_current_ma.to_string().as_str(),
step.to_string().as_str(),
)
.await;
log(
LogMessage::PumpOverCurrent,
plant_id as u32 + 1,
current_ma as u32,
plant_config.max_pump_current_ma.to_string().as_str(),
step.to_string().as_str(),
)
.await;
board.board_hal.general_fault(true).await;
board.board_hal.fault(plant_id, true).await?;
if !plant_config.ignore_current_error {
@@ -694,17 +698,14 @@ pub async fn do_secure_pump(
let low_current = current_ma < plant_config.min_pump_current_ma;
if low_current {
if first_error {
LOG_ACCESS
.lock()
.await
.log(
LogMessage::PumpOpenLoopCurrent,
plant_id as u32 + 1,
current_ma as u32,
plant_config.min_pump_current_ma.to_string().as_str(),
step.to_string().as_str(),
)
.await;
log(
LogMessage::PumpOpenLoopCurrent,
plant_id as u32 + 1,
current_ma as u32,
plant_config.min_pump_current_ma.to_string().as_str(),
step.to_string().as_str(),
)
.await;
board.board_hal.general_fault(true).await;
board.board_hal.fault(plant_id, true).await?;
if !plant_config.ignore_current_error {
@@ -718,17 +719,14 @@ pub async fn do_secure_pump(
Err(err) => {
if !plant_config.ignore_current_error {
info!("Error getting pump current: {}", err);
LOG_ACCESS
.lock()
.await
.log(
LogMessage::PumpMissingSensorCurrent,
plant_id as u32,
0,
"",
"",
)
.await;
log(
LogMessage::PumpMissingSensorCurrent,
plant_id as u32,
0,
"",
"",
)
.await;
error = true;
break;
} else {
@@ -1003,21 +1001,21 @@ async fn wait_infinity(
led_count %= 8;
led_count += 1;
for i in 0..8 {
let _ = board.board_hal.fault(i, i < led_count);
let _ = board.board_hal.fault(i, i < led_count).await;
}
}
WaitType::ConfigButton => {
// Alternating pattern: 1010 1010 -> 0101 0101
pattern_step = (pattern_step + 1) % 2;
for i in 0..8 {
let _ = board.board_hal.fault(i, (i + pattern_step) % 2 == 0);
let _ = board.board_hal.fault(i, (i + pattern_step) % 2 == 0).await;
}
}
WaitType::MqttConfig => {
// Moving dot pattern
pattern_step = (pattern_step + 1) % 8;
for i in 0..8 {
let _ = board.board_hal.fault(i, i == pattern_step);
let _ = board.board_hal.fault(i, i == pattern_step).await;
}
}
}
@@ -1031,7 +1029,7 @@ async fn wait_infinity(
// Clear all LEDs
for i in 0..8 {
let _ = board.board_hal.fault(i, false);
let _ = board.board_hal.fault(i, false).await;
}
}