finis exersise 8.3

This commit is contained in:
2025-10-30 16:30:40 +01:00
parent 1410897f8f
commit a8d37effb2
4 changed files with 631 additions and 86 deletions

View File

@@ -52,37 +52,44 @@ impl<'a, T: OutputPin> Toggle<T> for ToggleLed<'a, T> {
pub struct Leds<'a, pub struct Leds<'a,
RP: OutputPin, RT: Toggle<RP>, RP: OutputPin, RT: Toggle<RP>,
GP: OutputPin, GT: Toggle<GP>, GP: OutputPin, GT: Toggle<GP>,
OP: OutputPin, OT: Toggle<OP>,
BP: OutputPin, BT: Toggle<BP> BP: OutputPin, BT: Toggle<BP>
> { > {
pub red: &'a mut RT, pub red: &'a mut RT,
pub green: &'a mut GT, pub green: &'a mut GT,
pub orange: &'a mut OT,
pub blue: &'a mut BT, pub blue: &'a mut BT,
// phantom data to convince rustc the generics RP, GP and BP are used. // phantom data to convince rustc the generics RP, GP and BP are used.
_r: PhantomData<RP>, _r: PhantomData<RP>,
_g: PhantomData<GP>, _g: PhantomData<GP>,
_o: PhantomData<OP>,
_b: PhantomData<BP>, _b: PhantomData<BP>,
} }
impl<'a, impl<'a,
RP: OutputPin, RT: Toggle<RP>, RP: OutputPin, RT: Toggle<RP>,
GP: OutputPin, GT: Toggle<GP>, GP: OutputPin, GT: Toggle<GP>,
OP: OutputPin, OT: Toggle<OP>,
BP: OutputPin, BT: Toggle<BP> BP: OutputPin, BT: Toggle<BP>
> Leds<'a, RP, RT, GP, GT, BP, BT> { > Leds<'a, RP, RT, GP, GT, OP, OT, BP, BT> {
pub fn new(red: &'a mut RT, green: &'a mut GT, blue: &'a mut BT) -> Self { pub fn new(red: &'a mut RT, green: &'a mut GT, orange: &'a mut OT, blue: &'a mut BT) -> Self {
Self { Self {
red, red,
green, green,
orange,
blue, blue,
_r: PhantomData, _r: PhantomData,
_g: PhantomData, _g: PhantomData,
_o: PhantomData,
_b: PhantomData, _b: PhantomData,
} }
} }
pub fn set_all(&mut self, red: PinState, green: PinState, blue: PinState) { pub fn set_all(&mut self, red: PinState, green: PinState, orange: PinState, blue: PinState) {
let _ = self.red.set(red); let _ = self.red.set(red);
let _ = self.blue.set(blue); let _ = self.orange.set(orange);
let _ = self.green.set(green); let _ = self.green.set(green);
let _ = self.blue.set(blue);
} }
} }

View File

@@ -3,6 +3,7 @@
#![no_main] #![no_main]
#![no_std] #![no_std]
use embedded_hal::digital::PinState;
// Halt on panic // Halt on panic
use panic_halt as _; // panic handler use panic_halt as _; // panic handler
@@ -27,11 +28,16 @@ fn main() -> ! {
//led pinnen uphalen //led pinnen uphalen
let mut green_pin = &mut gpiod.pd12.into_push_pull_output(); let mut green_pin = &mut gpiod.pd12.into_push_pull_output();
let mut red_pin = &mut gpiod.pd14.into_push_pull_output(); let mut red_pin = &mut gpiod.pd14.into_push_pull_output();
let mut orange_pin = &mut gpiod.pd13.into_push_pull_output();
let mut blue_pin = &mut gpiod.pd15.into_push_pull_output(); let mut blue_pin = &mut gpiod.pd15.into_push_pull_output();
let mut green = ToggleLed::new(&mut green_pin).expect("faild to set green led"); let mut green = ToggleLed::new(&mut green_pin).expect("faild to set green led");
let mut red = ToggleLed::new(&mut red_pin).expect("faild to set red led"); let mut red = ToggleLed::new(&mut red_pin).expect("faild to set red led");
let mut orange = ToggleLed::new(&mut orange_pin).expect("faild to set orange led");
let mut blue = ToggleLed::new(&mut blue_pin).expect("faild to set blue led"); let mut blue = ToggleLed::new(&mut blue_pin).expect("faild to set blue led");
let mut leds = Leds::new(&mut red, &mut green, &mut blue); let mut leds = Leds::new(&mut red, &mut green, &mut orange, &mut blue);
//user knop
let gpioa = dp.GPIOA.split();
let button = &mut gpioa.pa0.into_floating_input();
//leds struct en state machine maken //leds struct en state machine maken
let mut state_machine = StateMachine::new(&mut leds); let mut state_machine = StateMachine::new(&mut leds);
@@ -41,9 +47,20 @@ fn main() -> ! {
// Create a delay abstraction based on SysTick // Create a delay abstraction based on SysTick
let mut delay = cp.SYST.delay(&clocks); let mut delay = cp.SYST.delay(&clocks);
let mut button_high = button.is_high();
loop { loop {
let _ = state_machine.second_passed(); let _ = state_machine.second_passed();
delay.delay_ms(1000_u32); for _ in 0..99 {
if button_high != button.is_high() {
button_high = button.is_high();
if button_high {
state_machine.button_press();
} else {
state_machine.button_release();
}
}
delay.delay_ms(10_u32);
}
} }
} }

View File

@@ -4,44 +4,67 @@ use crate::leds::{Leds, Toggle};
enum States { enum States {
Red(StateRed), Red(StateRed),
Blue(StateBlue), Orange(StateOrange),
Green(StateGreen), Green(StateGreen),
BridgeOpen(StateBridgeOpen)
} }
trait State< trait State<
RP: OutputPin, RT: Toggle<RP>, RP: OutputPin, RT: Toggle<RP>,
GP: OutputPin, GT: Toggle<GP>, GP: OutputPin, GT: Toggle<GP>,
OP: OutputPin, OT: Toggle<OP>,
BP: OutputPin, BT: Toggle<BP> BP: OutputPin, BT: Toggle<BP>
> { > {
fn new(leds: &mut Leds<RP, RT, GP, GT, BP, BT>) -> Self; fn new(leds: &mut Leds<RP, RT, GP, GT, OP, OT, BP, BT>) -> Self;
fn second_passed(&self, leds: &mut Leds<RP, RT, GP, GT, BP, BT>) -> States; fn second_passed(&self, leds: &mut Leds<RP, RT, GP, GT, OP, OT, BP, BT>) -> States;
fn button_press(&self, leds: &mut Leds<RP, RT, GP, GT, OP, OT, BP, BT>) -> States;
fn button_release(&self, leds: &mut Leds<RP, RT, GP, GT, OP, OT, BP, BT>) -> States;
} }
pub struct StateMachine<'a, pub struct StateMachine<'a,
RP: OutputPin, RT: Toggle<RP>, RP: OutputPin, RT: Toggle<RP>,
GP: OutputPin, GT: Toggle<GP>, GP: OutputPin, GT: Toggle<GP>,
OP: OutputPin, OT: Toggle<OP>,
BP: OutputPin, BT: Toggle<BP> BP: OutputPin, BT: Toggle<BP>
> { > {
state: States, state: States,
leds: &'a mut Leds<'a, RP, RT, GP, GT, BP, BT>, leds: &'a mut Leds<'a, RP, RT, GP, GT, OP, OT, BP, BT>
} }
impl<'a, impl<'a,
RP: OutputPin, RT: Toggle<RP>, RP: OutputPin, RT: Toggle<RP>,
GP: OutputPin, GT: Toggle<GP>, GP: OutputPin, GT: Toggle<GP>,
OP: OutputPin, OT: Toggle<OP>,
BP: OutputPin, BT: Toggle<BP> BP: OutputPin, BT: Toggle<BP>
> StateMachine<'a, RP, RT, GP, GT, BP, BT> > StateMachine<'a, RP, RT, GP, GT, OP, OT, BP, BT>
{ {
pub fn new(leds: &'a mut Leds<'a, RP, RT, GP, GT, BP, BT>) -> Self { pub fn new(leds: &'a mut Leds<'a, RP, RT, GP, GT, OP, OT, BP, BT>) -> Self {
Self { Self {
state: States::Red(StateRed::new(leds)), state: States::Red(StateRed::new(leds)),
leds, leds
} }
} }
pub fn second_passed(&mut self) { pub fn second_passed(&mut self) {
self.state = match &self.state { self.state = match &self.state {
States::Red(state) => state.second_passed(self.leds), States::Red(state) => state.second_passed(self.leds),
States::Blue(state) => state.second_passed(self.leds), States::Orange(state) => state.second_passed(self.leds),
States::Green(state) => state.second_passed(self.leds), States::Green(state) => state.second_passed(self.leds),
States::BridgeOpen(state) => state.second_passed(self.leds),
}
}
pub fn button_press(&mut self) {
self.state = match &self.state {
States::Red(state) => state.button_press(self.leds),
States::Orange(state) => state.button_press(self.leds),
States::Green(state) => state.button_press(self.leds),
States::BridgeOpen(state) => state.button_press(self.leds),
}
}
pub fn button_release(&mut self) {
self.state = match &self.state {
States::Red(state) => state.button_release(self.leds),
States::Orange(state) => state.button_release(self.leds),
States::Green(state) => state.button_release(self.leds),
States::BridgeOpen(state) => state.button_release(self.leds),
} }
} }
} }
@@ -56,15 +79,16 @@ struct StateRed {
impl< impl<
RP: OutputPin, RT: Toggle<RP>, RP: OutputPin, RT: Toggle<RP>,
GP: OutputPin, GT: Toggle<GP>, GP: OutputPin, GT: Toggle<GP>,
OP: OutputPin, OT: Toggle<OP>,
BP: OutputPin, BT: Toggle<BP> BP: OutputPin, BT: Toggle<BP>
> State<RP, RT, GP, GT, BP, BT> for StateRed { > State<RP, RT, GP, GT, OP, OT, BP, BT> for StateRed {
fn new(leds: &mut Leds<RP, RT, GP, GT, BP, BT>) -> Self { fn new(leds: &mut Leds<RP, RT, GP, GT, OP, OT, BP, BT>) -> Self {
leds.set_all(PinState::High, PinState::Low, PinState::Low); leds.set_all(PinState::High, PinState::Low, PinState::Low, PinState::Low);
Self { Self {
time_passed: 0 time_passed: 0
} }
} }
fn second_passed(&self, leds: &mut Leds<RP, RT, GP, GT, BP, BT>) -> States { fn second_passed(&self, leds: &mut Leds<RP, RT, GP, GT, OP, OT, BP, BT>) -> States {
if self.time_passed + 1 >= 4 { if self.time_passed + 1 >= 4 {
States::Green(StateGreen::new(leds)) States::Green(StateGreen::new(leds))
} else { } else {
@@ -73,6 +97,15 @@ impl<
}) })
} }
} }
fn button_press(&self, leds: &mut Leds<RP, RT, GP, GT, OP, OT, BP, BT>) -> States {
States::BridgeOpen(StateBridgeOpen::new(leds))
}
fn button_release(&self, _leds: &mut Leds<RP, RT, GP, GT, OP, OT, BP, BT>) -> States {
States::Red(Self {
time_passed: self.time_passed
})
}
} }
// #################################################### // ####################################################
@@ -85,40 +118,107 @@ struct StateGreen {
impl< impl<
RP: OutputPin, RT: Toggle<RP>, RP: OutputPin, RT: Toggle<RP>,
GP: OutputPin, GT: Toggle<GP>, GP: OutputPin, GT: Toggle<GP>,
OP: OutputPin, OT: Toggle<OP>,
BP: OutputPin, BT: Toggle<BP> BP: OutputPin, BT: Toggle<BP>
> State<RP, RT, GP, GT, BP, BT> for StateGreen { > State<RP, RT, GP, GT, OP, OT, BP, BT> for StateGreen {
fn new(leds: &mut Leds<RP, RT, GP, GT, BP, BT>) -> Self { fn new(leds: &mut Leds<RP, RT, GP, GT, OP, OT, BP, BT>) -> Self {
leds.set_all(PinState::Low, PinState::High, PinState::Low); leds.set_all(PinState::Low, PinState::High, PinState::Low, PinState::Low);
Self { Self {
time_passed: 0 time_passed: 0
} }
} }
fn second_passed(&self, leds: &mut Leds<RP, RT, GP, GT, BP, BT>) -> States { fn second_passed(&self, leds: &mut Leds<RP, RT, GP, GT, OP, OT, BP, BT>) -> States {
if self.time_passed + 1 >= 3 { if self.time_passed + 1 >= 3 {
States::Blue(StateBlue::new(leds)) States::Orange(StateOrange::new(leds))
} else { } else {
States::Green(Self { States::Green(Self {
time_passed: self.time_passed + 1 time_passed: self.time_passed + 1
}) })
} }
} }
fn button_press(&self, _leds: &mut Leds<RP, RT, GP, GT, OP, OT, BP, BT>) -> States {
States::Green(Self {
time_passed: self.time_passed
})
}
fn button_release(&self, _leds: &mut Leds<RP, RT, GP, GT, OP, OT, BP, BT>) -> States {
States::Green(Self {
time_passed: self.time_passed
})
}
} }
// #################################################### // ####################################################
// ## BLUE ############################################ // ## ORANGE ############################################
// #################################################### // ####################################################
struct StateBlue {} struct StateOrange {}
impl< impl<
RP: OutputPin, RT: Toggle<RP>, RP: OutputPin, RT: Toggle<RP>,
GP: OutputPin, GT: Toggle<GP>, GP: OutputPin, GT: Toggle<GP>,
OP: OutputPin, OT: Toggle<OP>,
BP: OutputPin, BT: Toggle<BP> BP: OutputPin, BT: Toggle<BP>
> State<RP, RT, GP, GT, BP, BT> for StateBlue { > State<RP, RT, GP, GT, OP, OT, BP, BT> for StateOrange {
fn new(leds: &mut Leds<RP, RT, GP, GT, BP, BT>) -> Self { fn new(leds: &mut Leds<RP, RT, GP, GT, OP, OT, BP, BT>) -> Self {
leds.set_all(PinState::Low, PinState::Low, PinState::High); leds.set_all(PinState::Low, PinState::Low, PinState::High, PinState::Low);
Self {} Self {}
} }
fn second_passed(&self, leds: &mut Leds<RP, RT, GP, GT, BP, BT>) -> States { fn second_passed(&self, leds: &mut Leds<RP, RT, GP, GT, OP, OT, BP, BT>) -> States {
States::Red(StateRed::new(leds))
}
fn button_press(&self, _leds: &mut Leds<RP, RT, GP, GT, OP, OT, BP, BT>) -> States {
States::Orange(Self {})
}
fn button_release(&self, _leds: &mut Leds<RP, RT, GP, GT, OP, OT, BP, BT>) -> States {
States::Orange(Self {})
}
}
// ####################################################
// ## BRIDGE_OPEN #####################################
// ####################################################
struct StateBridgeOpen {
time_passed: u32
}
impl<
RP: OutputPin, RT: Toggle<RP>,
GP: OutputPin, GT: Toggle<GP>,
OP: OutputPin, OT: Toggle<OP>,
BP: OutputPin, BT: Toggle<BP>
> State<RP, RT, GP, GT, OP, OT, BP, BT> for StateBridgeOpen {
fn new(leds: &mut Leds<RP, RT, GP, GT, OP, OT, BP, BT>) -> Self {
leds.set_all(PinState::Low, PinState::Low, PinState::Low, PinState::High);
Self {
time_passed: 0
}
}
fn second_passed(&self, leds: &mut Leds<RP, RT, GP, GT, OP, OT, BP, BT>) -> States {
if self.time_passed + 1 == 2 {
let _ = leds.blue.low();
States::BridgeOpen(Self {
time_passed: self.time_passed + 1
})
} else if self.time_passed + 1 >= 3 {
let _ = leds.blue.high();
States::BridgeOpen(Self {
time_passed: 0
})
} else {
States::BridgeOpen(Self {
time_passed: self.time_passed + 1
})
}
}
fn button_press(&self, _leds: &mut Leds<RP, RT, GP, GT, OP, OT, BP, BT>) -> States {
States::BridgeOpen(Self {
time_passed: self.time_passed
})
}
fn button_release(&self, leds: &mut Leds<RP, RT, GP, GT, OP, OT, BP, BT>) -> States {
States::Red(StateRed::new(leds)) States::Red(StateRed::new(leds))
} }
} }

View File

@@ -14,46 +14,46 @@ auther:
> Maak een toestandsmachine volgens de State Pattern methode zoals beschreven in > Maak een toestandsmachine volgens de State Pattern methode zoals beschreven in
> het boek. Er zijn drie toestanden: rood, groen en oranje. Tussen de toestanden > het boek. Er zijn drie toestanden: rood, groen en oranje. Tussen de toestanden
> wordt geschakeld op basis van tijd: respectievelijk $4s&, &3s& en &1s&. > wordt geschakeld op basis van tijd: respectievelijk $4s$, $3s$ en $1s$.
De State Pattern methode in rust maakt gebuik van structs en traits. Om dit De State Pattern methode in rust maakt gebruik van structs en traits. Om dit
mognelijk te maken moet er een struct zijn die de leds kan aansturen. Hiervoor mogelijk te maken moet er een struct zijn die de leds kan aansturen. Hiervoor
is het de Pin struct van de stm32f4xx-hal nodig in in struct. Om mijn is het de Pin struct van de stm32f4xx-hal nodig in in struct. Om mijn
implementatie makkelijker onderhoudbaar te maken worden de Pin structs implementatie makkelijker onderhoudbaar te maken worden de Pin structs
doorgegeven aan de state machine struct. Hiervoor is een triad nodig die doorgegeven aan de state machine struct. Hiervoor is een triad nodig die
functions voor het aanpassen van de led status beschijft. De `toggle` functie functions voor het aanpassen van de led status beschrijft. De `toggle` functie
die gebruikt wordt in het voorbeeld is niet geimplementeerd via een trait. die gebruikt wordt in het voorbeeld is niet geïmplementeerd via een trait.
Deze kan dus niet gebruikt worden zonder de hal aan te passen. In de Deze kan dus niet gebruikt worden zonder de hal aan te passen. In de
documentatie van de pin struct implementeerd die de OutputPin trait van de documentatie van de pin struct implementeert die de OutputPin trait van de
embedded_hal crate^[https://docs.rs/stm32f4xx-hal/0.22.0/stm32f4xx_hal/gpio/struct.Pin.html#impl-OutputPin-for-Pin%3CP,+N,+Output%3CMODE%3E%3E-1]. Dus deze crate is toegevoed aan het project zodat hier embedded_hal crate^[https://docs.rs/stm32f4xx-hal/0.22.0/stm32f4xx_hal/gpio/struct.Pin.html#impl-OutputPin-for-Pin%3CP,+N,+Output%3CMODE%3E%3E-1]. Dus deze crate is toegevoegd aan het project zodat hier
gebruik van gemaakt kan worden. gebruik van gemaakt kan worden.
Om te testen of dit werkt is er een stuct aangemaakt met een simple toggle Om te testen of dit werkt is er een struct aangemaakt met een simple toggle
functie en de embeded_hal geimporteerd. Dit is gedaan met de volgende code: functie en de embeded_hal geïmporteerd. Dit is gedaan met de volgende code:
```rust ```rust
use embedded_hal::digital::{ErrorType as DigitalErrorType, OutputPin, PinState}; use embedded_hal::digital::{ErrorType as DigitalErrorType, OutputPin, PinState};
struct Leds<'a, Red: OutputPin, Green: OutputPin, Blue: OutputPin> { struct Leds<'a, Red: OutputPin, Green: OutputPin, Orange: OutputPin> {
red: &'a mut Red, red: &'a mut Red,
red_state: PinState, red_state: PinState,
green: &'a mut Green, green: &'a mut Green,
green_state: PinState, green_state: PinState,
blue: &'a mut Blue, orange: &'a mut Orange,
blue_state: PinState, orange_state: PinState,
} }
impl<'a, Red: OutputPin, Green: OutputPin, Blue: OutputPin> Leds<'a, Red, Green, Blue> { impl<'a, Red: OutputPin, Green: OutputPin, Orange: OutputPin> Leds<'a, Red, Green, Orange> {
pub fn new(red: &'a mut Red, green: &'a mut Green, blue: &'a mut Blue) -> Self { pub fn new(red: &'a mut Red, green: &'a mut Green, orange: &'a mut Orange) -> Self {
let _ = red.set_low(); let _ = red.set_low();
let _ = green.set_low(); let _ = green.set_low();
let _ = blue.set_low(); let _ = orange.set_low();
Self { Self {
red, red,
red_state: PinState::Low, red_state: PinState::Low,
green, green,
green_state: PinState::Low, green_state: PinState::Low,
blue, orange,
blue_state: PinState::Low, orange_state: PinState::Low,
} }
} }
@@ -82,9 +82,9 @@ fn main() -> ! {
// create structs for pins // create structs for pins
let mut green = gpiod.pd12.into_push_pull_output(); let mut green = gpiod.pd12.into_push_pull_output();
let mut red = gpiod.pd14.into_push_pull_output(); let mut red = gpiod.pd14.into_push_pull_output();
let mut blue = gpiod.pd15.into_push_pull_output(); let mut orange = gpiod.pd13.into_push_pull_output();
// create leds struct // create leds struct
let mut leds = Leds::new(&mut red, &mut green, &mut blue); let mut leds = Leds::new(&mut red, &mut green, &mut orange);
//Klok instellen //Klok instellen
let rcc = dp.RCC.constrain(); let rcc = dp.RCC.constrain();
@@ -124,34 +124,34 @@ use crate::leds::{Leds, Toggle};
enum States { enum States {
Red(StateRed), Red(StateRed),
Blue(StateBlue), Orange(StateOrange),
Green(StateGreen), Green(StateGreen),
} }
trait State< trait State<
RP: OutputPin, RT: Toggle<RP>, RP: OutputPin, RT: Toggle<RP>,
GP: OutputPin, GT: Toggle<GP>, GP: OutputPin, GT: Toggle<GP>,
BP: OutputPin, BT: Toggle<BP> OP: OutputPin, OT: Toggle<OP>
> { > {
fn new(leds: &mut Leds<RP, RT, GP, GT, BP, BT>) -> Self; fn new(leds: &mut Leds<RP, RT, GP, GT, OP, OT>) -> Self;
fn second_passed(&self, leds: &mut Leds<RP, RT, GP, GT, BP, BT>) -> States; fn second_passed(&self, leds: &mut Leds<RP, RT, GP, GT, OP, OT>) -> States;
} }
pub struct StateMachine<'a, pub struct StateMachine<'a,
RP: OutputPin, RT: Toggle<RP>, RP: OutputPin, RT: Toggle<RP>,
GP: OutputPin, GT: Toggle<GP>, GP: OutputPin, GT: Toggle<GP>,
BP: OutputPin, BT: Toggle<BP> OP: OutputPin, OT: Toggle<OP>
> { > {
state: States, state: States,
leds: &'a mut Leds<'a, RP, RT, GP, GT, BP, BT>, leds: &'a mut Leds<'a, RP, RT, GP, GT, OP, OT>,
} }
impl<'a, impl<'a,
RP: OutputPin, RT: Toggle<RP>, RP: OutputPin, RT: Toggle<RP>,
GP: OutputPin, GT: Toggle<GP>, GP: OutputPin, GT: Toggle<GP>,
BP: OutputPin, BT: Toggle<BP> OP: OutputPin, OT: Toggle<OP>
> StateMachine<'a, RP, RT, GP, GT, BP, BT> > StateMachine<'a, RP, RT, GP, GT, OP, OT>
{ {
pub fn new(leds: &'a mut Leds<'a, RP, RT, GP, GT, BP, BT>) -> Self { pub fn new(leds: &'a mut Leds<'a, RP, RT, GP, GT, OP, OT>) -> Self {
Self { Self {
state: States::Red(StateRed::new(leds)), state: States::Red(StateRed::new(leds)),
leds, leds,
@@ -160,7 +160,7 @@ impl<'a,
pub fn second_passed(&mut self) { pub fn second_passed(&mut self) {
self.state = match &self.state { self.state = match &self.state {
States::Red(state) => state.second_passed(self.leds), States::Red(state) => state.second_passed(self.leds),
States::Blue(state) => state.second_passed(self.leds), States::Orange(state) => state.second_passed(self.leds),
States::Green(state) => state.second_passed(self.leds), States::Green(state) => state.second_passed(self.leds),
} }
} }
@@ -238,27 +238,27 @@ Met deze workaround toegepast de `struct Leds` is als volgt geïmplementeerd in
pub struct Leds<'a, pub struct Leds<'a,
RP: OutputPin, RT: Toggle<RP>, RP: OutputPin, RT: Toggle<RP>,
GP: OutputPin, GT: Toggle<GP>, GP: OutputPin, GT: Toggle<GP>,
BP: OutputPin, BT: Toggle<BP> OP: OutputPin, OT: Toggle<OP>
> { > {
pub red: &'a mut RT, pub red: &'a mut RT,
pub green: &'a mut GT, pub green: &'a mut GT,
pub blue: &'a mut BT, pub orange: &'a mut OT,
// phantom data to convince rustc the generics RP, GP and BP are used. // phantom data to convince rustc the generics RP, GP and OP are used.
_r: PhantomData<RP>, _r: PhantomData<RP>,
_g: PhantomData<GP>, _g: PhantomData<GP>,
_b: PhantomData<BP>, _b: PhantomData<OP>,
} }
impl<'a, impl<'a,
RP: OutputPin, RT: Toggle<RP>, RP: OutputPin, RT: Toggle<RP>,
GP: OutputPin, GT: Toggle<GP>, GP: OutputPin, GT: Toggle<GP>,
BP: OutputPin, BT: Toggle<BP> OP: OutputPin, OT: Toggle<OP>
> Leds<'a, RP, RT, GP, GT, BP, BT> { > Leds<'a, RP, RT, GP, GT, OP, OT> {
pub fn new(red: &'a mut RT, green: &'a mut GT, blue: &'a mut BT) -> Self { pub fn new(red: &'a mut RT, green: &'a mut GT, orange: &'a mut OT) -> Self {
Self { Self {
red, red,
green, green,
blue, orange,
_r: PhantomData, _r: PhantomData,
_g: PhantomData, _g: PhantomData,
@@ -266,9 +266,9 @@ impl<'a,
} }
} }
pub fn set_all(&mut self, red: PinState, green: PinState, blue: PinState) { pub fn set_all(&mut self, red: PinState, green: PinState, orange: PinState) {
let _ = self.red.set(red); let _ = self.red.set(red);
let _ = self.blue.set(blue); let _ = self.orange.set(orange);
let _ = self.green.set(green); let _ = self.green.set(green);
} }
} }
@@ -291,15 +291,15 @@ struct StateRed {
impl< impl<
RP: OutputPin, RT: Toggle<RP>, RP: OutputPin, RT: Toggle<RP>,
GP: OutputPin, GT: Toggle<GP>, GP: OutputPin, GT: Toggle<GP>,
BP: OutputPin, BT: Toggle<BP> OP: OutputPin, OT: Toggle<OP>
> State<RP, RT, GP, GT, BP, BT> for StateRed { > State<RP, RT, GP, GT, OP, OT> for StateRed {
fn new(leds: &mut Leds<RP, RT, GP, GT, BP, BT>) -> Self { fn new(leds: &mut Leds<RP, RT, GP, GT, OP, OT>) -> Self {
leds.set_all(PinState::High, PinState::Low, PinState::Low); leds.set_all(PinState::High, PinState::Low, PinState::Low);
Self { Self {
time_passed: 0 time_passed: 0
} }
} }
fn second_passed(&self, leds: &mut Leds<RP, RT, GP, GT, BP, BT>) -> States { fn second_passed(&self, leds: &mut Leds<RP, RT, GP, GT, OP, OT>) -> States {
if self.time_passed + 1 >= 4 { if self.time_passed + 1 >= 4 {
States::Green(StateGreen::new(leds)) States::Green(StateGreen::new(leds))
} else { } else {
@@ -320,17 +320,17 @@ struct StateGreen {
impl< impl<
RP: OutputPin, RT: Toggle<RP>, RP: OutputPin, RT: Toggle<RP>,
GP: OutputPin, GT: Toggle<GP>, GP: OutputPin, GT: Toggle<GP>,
BP: OutputPin, BT: Toggle<BP> OP: OutputPin, OT: Toggle<OP>
> State<RP, RT, GP, GT, BP, BT> for StateGreen { > State<RP, RT, GP, GT, OP, OT> for StateGreen {
fn new(leds: &mut Leds<RP, RT, GP, GT, BP, BT>) -> Self { fn new(leds: &mut Leds<RP, RT, GP, GT, OP, OT>) -> Self {
leds.set_all(PinState::Low, PinState::High, PinState::Low); leds.set_all(PinState::Low, PinState::High, PinState::Low);
Self { Self {
time_passed: 0 time_passed: 0
} }
} }
fn second_passed(&self, leds: &mut Leds<RP, RT, GP, GT, BP, BT>) -> States { fn second_passed(&self, leds: &mut Leds<RP, RT, GP, GT, OP, OT>) -> States {
if self.time_passed + 1 >= 3 { if self.time_passed + 1 >= 3 {
States::Blue(StateBlue::new(leds)) States::Orange(StateOrange::new(leds))
} else { } else {
States::Green(Self { States::Green(Self {
time_passed: self.time_passed + 1 time_passed: self.time_passed + 1
@@ -340,20 +340,20 @@ impl<
} }
// #################################################### // ####################################################
// ## BLUE ############################################ // ## ORANGE ############################################
// #################################################### // ####################################################
struct StateBlue {} struct StateOrange {}
impl< impl<
RP: OutputPin, RT: Toggle<RP>, RP: OutputPin, RT: Toggle<RP>,
GP: OutputPin, GT: Toggle<GP>, GP: OutputPin, GT: Toggle<GP>,
BP: OutputPin, BT: Toggle<BP> OP: OutputPin, OT: Toggle<OP>
> State<RP, RT, GP, GT, BP, BT> for StateBlue { > State<RP, RT, GP, GT, OP, OT> for StateOrange {
fn new(leds: &mut Leds<RP, RT, GP, GT, BP, BT>) -> Self { fn new(leds: &mut Leds<RP, RT, GP, GT, OP, OT>) -> Self {
leds.set_all(PinState::Low, PinState::Low, PinState::High); leds.set_all(PinState::Low, PinState::Low, PinState::High);
Self {} Self {}
} }
fn second_passed(&self, leds: &mut Leds<RP, RT, GP, GT, BP, BT>) -> States { fn second_passed(&self, leds: &mut Leds<RP, RT, GP, GT, OP, OT>) -> States {
States::Red(StateRed::new(leds)) States::Red(StateRed::new(leds))
} }
} }
@@ -392,11 +392,11 @@ fn main() -> ! {
//led pinnen uphalen //led pinnen uphalen
let mut green_pin = &mut gpiod.pd12.into_push_pull_output(); let mut green_pin = &mut gpiod.pd12.into_push_pull_output();
let mut red_pin = &mut gpiod.pd14.into_push_pull_output(); let mut red_pin = &mut gpiod.pd14.into_push_pull_output();
let mut blue_pin = &mut gpiod.pd15.into_push_pull_output(); let mut orange_pin = &mut gpiod.pd15.into_push_pull_output();
let mut green = ToggleLed::new(&mut green_pin).expect("faild to set green led"); let mut green = ToggleLed::new(&mut green_pin).expect("faild to set green led");
let mut red = ToggleLed::new(&mut red_pin).expect("faild to set red led"); let mut red = ToggleLed::new(&mut red_pin).expect("faild to set red led");
let mut blue = ToggleLed::new(&mut blue_pin).expect("faild to set blue led"); let mut orange = ToggleLed::new(&mut orange_pin).expect("faild to set orange led");
let mut leds = Leds::new(&mut red, &mut green, &mut blue); let mut leds = Leds::new(&mut red, &mut green, &mut orange);
//leds struct en state machine maken //leds struct en state machine maken
let mut state_machine = StateMachine::new(&mut leds); let mut state_machine = StateMachine::new(&mut leds);
@@ -415,3 +415,424 @@ fn main() -> ! {
loop {} loop {}
} }
``` ```
## opdracht 8.3
> Voeg nu een toestand toe waarbij de blauwe “User” knop aangeeft dat de brug open wilt gaan. Vanuit de rode toestand moet dan naar een andere toestand (brug-open?) worden gesprongen. Wanneer de knop wordt losgelaten springt brug-open naar de rode toestand. In de brug-open-toestand moet de rode led knipperen. Dit knipperen moet elke met een periodetijd van $2s$ ($2s$ aan, $1s$ uit).
Om deze aanpassing te doen motten de volgende onderdelen aangepast worden:
- blue led initialiseren en toevoegen aan `struct Leds` en alle plekken waar deze gebuikt wordt
- knop initialiseren
- functies toevoegen voor de knop `trait State` en alle implementaties ervan
- de state `BridgeOpen` toevoegen aan:
- `enum States`
- de tussen functies in `struct StateMachine`
- nieuwe `struct StateBridgeOpen`
- uitlezen van de knop een aanroepen van de nieuwe functies in `trait State`
- de `struct StateRed` aanpassen voor de nieuwe logica
- logica toevoegen aan `struct StateBridgeOpen`
### resultaat
#### leds.rs
```rust
use core::marker::PhantomData;
use embedded_hal::digital::{OutputPin, PinState};
pub trait Toggle<T: OutputPin> {
fn toggle(&mut self) -> Result<(), T::Error>;
fn set(&mut self, state: PinState) -> Result<(), T::Error>;
fn get(&self) -> PinState;
fn high(&mut self) -> Result<(), T::Error> {
self.set(PinState::High)
}
fn low(&mut self) -> Result<(), T::Error> {
self.set(PinState::Low)
}
}
pub struct ToggleLed<'a, T: OutputPin> {
pin: &'a mut T,
state: PinState
}
impl<'a, T: OutputPin> ToggleLed<'a, T> {
pub fn new(pin: &'a mut T) -> Result<Self, T::Error> {
match pin.set_low() {
Ok(_) => Ok(Self { pin, state: PinState::Low }),
Err(e) => Err(e)
}
}
}
impl<'a, T: OutputPin> Toggle<T> for ToggleLed<'a, T> {
fn toggle(&mut self) -> Result<(), T::Error> {
if self.state == PinState::High {
self.state = PinState::Low;
} else {
self.state = PinState::Low;
}
self.pin.set_state(self.state)
}
fn set(&mut self, state: PinState) -> Result<(), T::Error> {
if state != self.state {
self.state = state;
self.pin.set_state(self.state)
} else {
Ok(())
}
}
fn get(&self) -> PinState {
self.state
}
}
pub struct Leds<'a,
RP: OutputPin, RT: Toggle<RP>,
GP: OutputPin, GT: Toggle<GP>,
OP: OutputPin, OT: Toggle<OP>,
BP: OutputPin, BT: Toggle<BP>
> {
pub red: &'a mut RT,
pub green: &'a mut GT,
pub orange: &'a mut OT,
pub blue: &'a mut BT,
// phantom data to convince rustc the generics RP, GP and BP are used.
_r: PhantomData<RP>,
_g: PhantomData<GP>,
_o: PhantomData<OP>,
_b: PhantomData<BP>,
}
impl<'a,
RP: OutputPin, RT: Toggle<RP>,
GP: OutputPin, GT: Toggle<GP>,
OP: OutputPin, OT: Toggle<OP>,
BP: OutputPin, BT: Toggle<BP>
> Leds<'a, RP, RT, GP, GT, OP, OT, BP, BT> {
pub fn new(red: &'a mut RT, green: &'a mut GT, orange: &'a mut OT, blue: &'a mut BT) -> Self {
Self {
red,
green,
orange,
blue,
_r: PhantomData,
_g: PhantomData,
_o: PhantomData,
_b: PhantomData,
}
}
pub fn set_all(&mut self, red: PinState, green: PinState, orange: PinState, blue: PinState) {
let _ = self.red.set(red);
let _ = self.orange.set(orange);
let _ = self.green.set(green);
let _ = self.blue.set(blue);
}
}
```
#### state_machine.rs
```rust
use embedded_hal::digital::{OutputPin, PinState};
use crate::leds::{Leds, Toggle};
enum States {
Red(StateRed),
Orange(StateOrange),
Green(StateGreen),
BridgeOpen(StateBridgeOpen)
}
trait State<
RP: OutputPin, RT: Toggle<RP>,
GP: OutputPin, GT: Toggle<GP>,
OP: OutputPin, OT: Toggle<OP>,
BP: OutputPin, BT: Toggle<BP>
> {
fn new(leds: &mut Leds<RP, RT, GP, GT, OP, OT, BP, BT>) -> Self;
fn second_passed(&self, leds: &mut Leds<RP, RT, GP, GT, OP, OT, BP, BT>) -> States;
fn button_press(&self, leds: &mut Leds<RP, RT, GP, GT, OP, OT, BP, BT>) -> States;
fn button_release(&self, leds: &mut Leds<RP, RT, GP, GT, OP, OT, BP, BT>) -> States;
}
pub struct StateMachine<'a,
RP: OutputPin, RT: Toggle<RP>,
GP: OutputPin, GT: Toggle<GP>,
OP: OutputPin, OT: Toggle<OP>,
BP: OutputPin, BT: Toggle<BP>
> {
state: States,
leds: &'a mut Leds<'a, RP, RT, GP, GT, OP, OT, BP, BT>
}
impl<'a,
RP: OutputPin, RT: Toggle<RP>,
GP: OutputPin, GT: Toggle<GP>,
OP: OutputPin, OT: Toggle<OP>,
BP: OutputPin, BT: Toggle<BP>
> StateMachine<'a, RP, RT, GP, GT, OP, OT, BP, BT>
{
pub fn new(leds: &'a mut Leds<'a, RP, RT, GP, GT, OP, OT, BP, BT>) -> Self {
Self {
state: States::Red(StateRed::new(leds)),
leds
}
}
pub fn second_passed(&mut self) {
self.state = match &self.state {
States::Red(state) => state.second_passed(self.leds),
States::Orange(state) => state.second_passed(self.leds),
States::Green(state) => state.second_passed(self.leds),
States::BridgeOpen(state) => state.second_passed(self.leds),
}
}
pub fn button_press(&mut self) {
self.state = match &self.state {
States::Red(state) => state.button_press(self.leds),
States::Orange(state) => state.button_press(self.leds),
States::Green(state) => state.button_press(self.leds),
States::BridgeOpen(state) => state.button_press(self.leds),
}
}
pub fn button_release(&mut self) {
self.state = match &self.state {
States::Red(state) => state.button_release(self.leds),
States::Orange(state) => state.button_release(self.leds),
States::Green(state) => state.button_release(self.leds),
States::BridgeOpen(state) => state.button_release(self.leds),
}
}
}
// ####################################################
// ## RED #############################################
// ####################################################
struct StateRed {
time_passed: u32
}
impl<
RP: OutputPin, RT: Toggle<RP>,
GP: OutputPin, GT: Toggle<GP>,
OP: OutputPin, OT: Toggle<OP>,
BP: OutputPin, BT: Toggle<BP>
> State<RP, RT, GP, GT, OP, OT, BP, BT> for StateRed {
fn new(leds: &mut Leds<RP, RT, GP, GT, OP, OT, BP, BT>) -> Self {
leds.set_all(PinState::High, PinState::Low, PinState::Low, PinState::Low);
Self {
time_passed: 0
}
}
fn second_passed(&self, leds: &mut Leds<RP, RT, GP, GT, OP, OT, BP, BT>) -> States {
if self.time_passed + 1 >= 4 {
States::Green(StateGreen::new(leds))
} else {
States::Red(Self {
time_passed: self.time_passed + 1
})
}
}
fn button_press(&self, leds: &mut Leds<RP, RT, GP, GT, OP, OT, BP, BT>) -> States {
States::BridgeOpen(StateBridgeOpen::new(leds))
}
fn button_release(&self, _leds: &mut Leds<RP, RT, GP, GT, OP, OT, BP, BT>) -> States {
States::Red(Self {
time_passed: self.time_passed
})
}
}
// ####################################################
// ## GREEN ###########################################
// ####################################################
struct StateGreen {
time_passed: u32
}
impl<
RP: OutputPin, RT: Toggle<RP>,
GP: OutputPin, GT: Toggle<GP>,
OP: OutputPin, OT: Toggle<OP>,
BP: OutputPin, BT: Toggle<BP>
> State<RP, RT, GP, GT, OP, OT, BP, BT> for StateGreen {
fn new(leds: &mut Leds<RP, RT, GP, GT, OP, OT, BP, BT>) -> Self {
leds.set_all(PinState::Low, PinState::High, PinState::Low, PinState::Low);
Self {
time_passed: 0
}
}
fn second_passed(&self, leds: &mut Leds<RP, RT, GP, GT, OP, OT, BP, BT>) -> States {
if self.time_passed + 1 >= 3 {
States::Orange(StateOrange::new(leds))
} else {
States::Green(Self {
time_passed: self.time_passed + 1
})
}
}
fn button_press(&self, _leds: &mut Leds<RP, RT, GP, GT, OP, OT, BP, BT>) -> States {
States::Green(Self {
time_passed: self.time_passed
})
}
fn button_release(&self, _leds: &mut Leds<RP, RT, GP, GT, OP, OT, BP, BT>) -> States {
States::Green(Self {
time_passed: self.time_passed
})
}
}
// ####################################################
// ## ORANGE ############################################
// ####################################################
struct StateOrange {}
impl<
RP: OutputPin, RT: Toggle<RP>,
GP: OutputPin, GT: Toggle<GP>,
OP: OutputPin, OT: Toggle<OP>,
BP: OutputPin, BT: Toggle<BP>
> State<RP, RT, GP, GT, OP, OT, BP, BT> for StateOrange {
fn new(leds: &mut Leds<RP, RT, GP, GT, OP, OT, BP, BT>) -> Self {
leds.set_all(PinState::Low, PinState::Low, PinState::High, PinState::Low);
Self {}
}
fn second_passed(&self, leds: &mut Leds<RP, RT, GP, GT, OP, OT, BP, BT>) -> States {
States::Red(StateRed::new(leds))
}
fn button_press(&self, _leds: &mut Leds<RP, RT, GP, GT, OP, OT, BP, BT>) -> States {
States::Orange(Self {})
}
fn button_release(&self, _leds: &mut Leds<RP, RT, GP, GT, OP, OT, BP, BT>) -> States {
States::Orange(Self {})
}
}
// ####################################################
// ## BRIDGE_OPEN #####################################
// ####################################################
struct StateBridgeOpen {
time_passed: u32
}
impl<
RP: OutputPin, RT: Toggle<RP>,
GP: OutputPin, GT: Toggle<GP>,
OP: OutputPin, OT: Toggle<OP>,
BP: OutputPin, BT: Toggle<BP>
> State<RP, RT, GP, GT, OP, OT, BP, BT> for StateBridgeOpen {
fn new(leds: &mut Leds<RP, RT, GP, GT, OP, OT, BP, BT>) -> Self {
leds.set_all(PinState::Low, PinState::Low, PinState::Low, PinState::High);
Self {
time_passed: 0
}
}
fn second_passed(&self, leds: &mut Leds<RP, RT, GP, GT, OP, OT, BP, BT>) -> States {
if self.time_passed + 1 == 2 {
let _ = leds.blue.low();
States::BridgeOpen(Self {
time_passed: self.time_passed + 1
})
} else if self.time_passed + 1 >= 3 {
let _ = leds.blue.high();
States::BridgeOpen(Self {
time_passed: 0
})
} else {
States::BridgeOpen(Self {
time_passed: self.time_passed + 1
})
}
}
fn button_press(&self, _leds: &mut Leds<RP, RT, GP, GT, OP, OT, BP, BT>) -> States {
States::BridgeOpen(Self {
time_passed: self.time_passed
})
}
fn button_release(&self, leds: &mut Leds<RP, RT, GP, GT, OP, OT, BP, BT>) -> States {
States::Red(StateRed::new(leds))
}
}
```
#### main.rs
```rust
#![deny(unsafe_code)]
#![allow(clippy::empty_loop)]
#![no_main]
#![no_std]
use embedded_hal::digital::PinState;
// Halt on panic
use panic_halt as _; // panic handler
use cortex_m_rt::entry;
use stm32f4xx_hal::{self as hal};
use crate::hal::{pac, prelude::*};
mod leds;
use crate::leds::{Leds, ToggleLed};
mod state_machine;
use crate::state_machine::StateMachine;
#[entry]
fn main() -> ! {
if let (Some(dp), Some(cp)) = (
pac::Peripherals::take(),
cortex_m::peripheral::Peripherals::take(),
) {
//GPIOD ophalen
let gpiod = dp.GPIOD.split();
//led pinnen uphalen
let mut green_pin = &mut gpiod.pd12.into_push_pull_output();
let mut red_pin = &mut gpiod.pd14.into_push_pull_output();
let mut orange_pin = &mut gpiod.pd13.into_push_pull_output();
let mut blue_pin = &mut gpiod.pd15.into_push_pull_output();
let mut green = ToggleLed::new(&mut green_pin).expect("faild to set green led");
let mut red = ToggleLed::new(&mut red_pin).expect("faild to set red led");
let mut orange = ToggleLed::new(&mut orange_pin).expect("faild to set orange led");
let mut blue = ToggleLed::new(&mut blue_pin).expect("faild to set blue led");
let mut leds = Leds::new(&mut red, &mut green, &mut orange, &mut blue);
//user knop
let gpioa = dp.GPIOA.split();
let button = &mut gpioa.pa0.into_floating_input();
//leds struct en state machine maken
let mut state_machine = StateMachine::new(&mut leds);
//Klok instellen
let rcc = dp.RCC.constrain();
let clocks = rcc.cfgr.sysclk(48.MHz()).freeze();
// Create a delay abstraction based on SysTick
let mut delay = cp.SYST.delay(&clocks);
let mut button_high = button.is_high();
loop {
let _ = state_machine.second_passed();
for _ in 0..99 {
if button_high != button.is_high() {
button_high = button.is_high();
if button_high {
state_machine.button_press();
} else {
state_machine.button_release();
}
}
delay.delay_ms(10_u32);
}
}
}
loop {}
}
```