Skip to content

Commit

Permalink
50 create appsline follower with the main state machine (#55)
Browse files Browse the repository at this point in the history
* Complete FSM navigation
  • Loading branch information
punkto authored Aug 10, 2024
1 parent a9b8f1f commit 9eebac6
Show file tree
Hide file tree
Showing 38 changed files with 753 additions and 77 deletions.
1 change: 1 addition & 0 deletions Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@ members = [
"libs/hal_button",
"libs/hal_encoder_stm32f1xx",
"apps/hello_world",
"apps/line_follower",
]

resolver = "2"
59 changes: 33 additions & 26 deletions apps/hello_world/src/main.rs
Original file line number Diff line number Diff line change
Expand Up @@ -12,9 +12,9 @@ use mightybuga_bsc::timer_based_buzzer::TimerBasedBuzzer;
use mightybuga_bsc::timer_based_buzzer::TimerBasedBuzzerInterface;
use mightybuga_bsc::EncoderController;

use battery_sensor_controller::BatterySensorController;
use engine::engine::EngineController;
use light_sensor_array_controller::LightSensorArrayController;
use battery_sensor_controller::BatterySensorController;

use nb::block;

Expand Down Expand Up @@ -117,7 +117,10 @@ fn main() -> ! {
b'h' => {
// Read the battery sensor
logger.log("Battery sensor value: ");
print_number(battery_sensor.get_battery_millivolts() as isize, &mut logger);
print_number(
battery_sensor.get_battery_millivolts() as isize,
&mut logger,
);
logger.log(" milli Volts\r\n");
}
_ => {
Expand Down Expand Up @@ -187,14 +190,18 @@ fn play_notes(logger: &mut Logger, buzzer: &mut TimerBasedBuzzer, delay: &mut Sy
buzzer.turn_off();
}

fn read_encoder(encoder: &mut mightybuga_bsc::IncrementalEncoder, logger: &mut Logger, delay: &mut SysDelay) {
fn read_encoder(
encoder: &mut mightybuga_bsc::IncrementalEncoder,
logger: &mut Logger,
delay: &mut SysDelay,
) {
encoder.enable();
logger.log("move the encoder! (and reset MCU to exit)\r\n");

let mut last = 0;
loop {
let (delta, steps) = encoder.delta();
if last != steps{
if last != steps {
logger.log("(steps,delta): (");
print_number(steps, logger);
logger.log(",");
Expand All @@ -210,27 +217,27 @@ fn read_encoder(encoder: &mut mightybuga_bsc::IncrementalEncoder, logger: &mut L

fn print_number(n: isize, logger: &mut Logger) {
let mut len = 0;
let mut digits = [0_u8; 20];
let mut d = 0;
let mut binary = n.abs();
while binary > 0 {
digits[d] = (binary % 10) as u8;
d += 1;
binary /= 10;
}
if d == 0 {
d = 1;
}
let mut ascii = [0_u8; 20];
if n < 0 {
ascii[0] = b'-';
len = 1;
}
while d > 0 {
d -= 1;
ascii[len] = digits[d] + b'0';
len += 1;
}
let mut digits = [0_u8; 20];
let mut d = 0;
let mut binary = n.abs();
while binary > 0 {
digits[d] = (binary % 10) as u8;
d += 1;
binary /= 10;
}
if d == 0 {
d = 1;
}
let mut ascii = [0_u8; 20];
if n < 0 {
ascii[0] = b'-';
len = 1;
}
while d > 0 {
d -= 1;
ascii[len] = digits[d] + b'0';
len += 1;
}
let s = core::str::from_utf8(ascii[0..len].as_ref()).unwrap();
logger.log(s);
}
}
28 changes: 28 additions & 0 deletions apps/line_follower/.cargo/config
Original file line number Diff line number Diff line change
@@ -0,0 +1,28 @@
[target.thumbv7m-none-eabi]
# uncomment ONE of these three option to make `cargo run` start a GDB session
# which option to pick depends on your system
# runner = "arm-none-eabi-gdb -q -x openocd.gdb"
#runner = "gdb-multiarch -q -x openocd.gdb"
#runner = "gdb-multiarch -q -x openocd_just_flash_and_run.gdb"
#runner = "./flash.sh"

runner = "../../tools/upload.sh"

rustflags = [
# LLD (shipped with the Rust toolchain) is used as the default linker
"-C", "link-arg=-Tlink.x",

# if you run into problems with LLD switch to the GNU linker by commenting out
# this line
# "-C", "linker=arm-none-eabi-ld",

# if you need to link to pre-compiled C libraries provided by a C toolchain
# use GCC as the linker by commenting out both lines above and then
# uncommenting the three lines below
# "-C", "linker=arm-none-eabi-gcc",
# "-C", "link-arg=-Wl,-Tlink.x",
# "-C", "link-arg=-nostartfiles",
]

[build]
target = "thumbv7m-none-eabi" # Cortex-M3
17 changes: 17 additions & 0 deletions apps/line_follower/.gitignore
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
# Generated by Cargo
# will have compiled files and executables
debug/
target/

# Remove Cargo.lock from gitignore if creating an executable, leave it for libraries
# More information here https://doc.rust-lang.org/cargo/guide/cargo-toml-vs-cargo-lock.html
Cargo.lock

# These are backup files generated by rustfmt
**/*.rs.bk

# MSVC Windows builds of rustc generate these, which store debugging information
*.pdb


.vscode/
24 changes: 24 additions & 0 deletions apps/line_follower/Cargo.toml
Original file line number Diff line number Diff line change
@@ -0,0 +1,24 @@
[package]
name = "line_follower"
version = "0.1.0"
authors = ["Jorge Muñoz <[email protected]>"]
description = "Line follower application"
categories = ["embedded", "no-std"]
edition = "2021"

[dependencies]
mightybuga_bsc = { path = "../../mightybuga_bsc" }
panic-halt = "0.2.0"
nb = "1.1.0"

embedded-alloc = "0.5.1"

logging = { path = "../../libs/logging" }
engine = { path = "../../libs/engine" }
battery_sensor_controller = { path = "../../libs/battery_sensor_controller" }
hal_button = { path = "../../libs/hal_button" }

[profile.release]
codegen-units = 1 # better optimizations
debug = true # symbols are nice and they don't increase the size on Flash
lto = true # better optimizations
6 changes: 6 additions & 0 deletions apps/line_follower/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
# Line Follower


´´´

´´´
7 changes: 7 additions & 0 deletions apps/line_follower/flash.sh
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
# Uses openocd to flash the firmware.
# This script is used from `cargo run` when used the apropiate option in .cargo/config (parameter: runner)

echo "Flashing $1"

killall openocd
openocd -f openocd.cfg -c init -c halt -c "flash write_image erase $1" -c reset -c shutdown
7 changes: 7 additions & 0 deletions apps/line_follower/flash_semihosting.sh
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
# Uses openocd to flash the firmware.
# This script is used from `cargo run` when used the apropiate option in .cargo/config (parameter: runner)

echo "Flashing $1"

killall openocd
openocd -f openocd.cfg -c init -c halt -c "arm semihosting enable" -c "flash write_image erase $1" -c reset # -c shutdown
18 changes: 18 additions & 0 deletions apps/line_follower/openocd.cfg
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
# Sample OpenOCD configuration for the blue pill board

# Some microcontrollers have a different CPU ID; uncomment what you have:
# This is for the STM32F103C8T6
#set CPUTAPID 0x2ba01477
# This is for the CS32F103C8T6 clone
set CPUTAPID 0x1ba01477

# Depending on the hardware revision you got you'll have to pick ONE of these
# interfaces. At any time only one interface should be commented out.

# Revision C (newer revision)
# source [find interface/stlink-v2-1.cfg]

# Revision A and B (older revisions)
source [find interface/stlink-v2.cfg]

source [find target/stm32f1x.cfg]
43 changes: 43 additions & 0 deletions apps/line_follower/openocd_debug.gdb
Original file line number Diff line number Diff line change
@@ -0,0 +1,43 @@
target extended-remote :3333

# print demangled symbols
set print asm-demangle on

# set backtrace limit to not have infinite backtrace loops
set backtrace limit 32

# detect unhandled exceptions, hard faults and panics
break DefaultHandler
break HardFault
break rust_begin_unwind
# # run the next few lines so the panic message is printed immediately
# # the number needs to be adjusted for your panic handler
# commands $bpnum
# next 4
# end

# *try* to stop at the user entry point (it might be gone due to inlining)
# break main

monitor arm semihosting enable

# # send captured ITM to the file itm.fifo
# # (the microcontroller SWO pin must be connected to the programmer SWO pin)
# # 8000000 must match the core clock frequency
# monitor tpiu config internal itm.txt uart off 8000000

# # OR: make the microcontroller SWO pin output compatible with UART (8N1)
# # 8000000 must match the core clock frequency
# # 2000000 is the frequency of the SWO pin
# monitor tpiu config external uart off 8000000 2000000

# # enable ITM port 0
# monitor itm port 0 on

load

# start the process but immediately halt the processor
stepi

# or run the app!
#run
43 changes: 43 additions & 0 deletions apps/line_follower/openocd_just_flash_and_run.gdb
Original file line number Diff line number Diff line change
@@ -0,0 +1,43 @@
target extended-remote :3333

# print demangled symbols
set print asm-demangle on

# set backtrace limit to not have infinite backtrace loops
set backtrace limit 32

# detect unhandled exceptions, hard faults and panics
#break DefaultHandler
#break HardFault
#break rust_begin_unwind
# # run the next few lines so the panic message is printed immediately
# # the number needs to be adjusted for your panic handler
# commands $bpnum
# next 4
# end

# *try* to stop at the user entry point (it might be gone due to inlining)
# break main

monitor arm semihosting enable

# # send captured ITM to the file itm.fifo
# # (the microcontroller SWO pin must be connected to the programmer SWO pin)
# # 8000000 must match the core clock frequency
# monitor tpiu config internal itm.txt uart off 8000000

# # OR: make the microcontroller SWO pin output compatible with UART (8N1)
# # 8000000 must match the core clock frequency
# # 2000000 is the frequency of the SWO pin
# monitor tpiu config external uart off 8000000 2000000

# # enable ITM port 0
# monitor itm port 0 on

load

# start the process but immediately halt the processor
#stepi

# or run the app!
run
64 changes: 64 additions & 0 deletions apps/line_follower/src/fsm.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,64 @@
use crate::LineFollowerStatus;
use logging::Logger;

use crate::fsm_states;

pub enum FSMState {
Idle,
HardwareCheck,
Calibration,
LineFollowing,
BatteryLow,
}

pub trait Runnable {
fn run(&self, status: &mut LineFollowerStatus) -> FSMEvent;
}

#[derive(Clone, Copy)]
pub enum FSMEvent {
NothingHappend,
Button1Pressed,
Button2Pressed,
BatteryIsLow,
}

impl FSMState {
pub fn next(
self,
event: FSMEvent,
status: &mut LineFollowerStatus,
) -> FSMState {
match (self, event) {
(FSMState::Idle, FSMEvent::Button1Pressed) => FSMState::HardwareCheck,
(FSMState::Idle, FSMEvent::Button2Pressed) => FSMState::Calibration,
(FSMState::Idle, FSMEvent::BatteryIsLow) => FSMState::BatteryLow,

(FSMState::HardwareCheck, FSMEvent::NothingHappend) => FSMState::Idle,
(FSMState::HardwareCheck, FSMEvent::BatteryIsLow) => FSMState::BatteryLow,

(FSMState::Calibration, FSMEvent::Button1Pressed) => FSMState::LineFollowing,
(FSMState::Calibration, FSMEvent::Button2Pressed) => FSMState::Idle,
(FSMState::Calibration, FSMEvent::BatteryIsLow) => FSMState::BatteryLow,

(FSMState::LineFollowing, FSMEvent::Button2Pressed) => FSMState::Idle,
(FSMState::LineFollowing, FSMEvent::BatteryIsLow) => FSMState::BatteryLow,

(_s, _e) => {
Logger::new(&mut status.board.serial.tx).log("default to idle state\r\n");
FSMState::Idle
}
}
}

pub fn run<'a>(&self, status: &mut LineFollowerStatus) -> FSMEvent {
let mut logger = Logger::new(&mut status.board.serial.tx);
match *self {
FSMState::Idle {} => fsm_states::idle::run(status),
FSMState::HardwareCheck {} => fsm_states::hardware_check::run(status),
FSMState::Calibration {} => fsm_states::calibration::run(status),
FSMState::LineFollowing {} => fsm_states::line_following::run(status),
FSMState::BatteryLow {} => fsm_states::battery_low::run(status),
}
}
}
Loading

0 comments on commit 9eebac6

Please sign in to comment.