diff --git a/Cargo.lock b/Cargo.lock index 29a114089cccbe484e713a2240315bd30afa5f3f..bd630dc800cc16480b09b3343da65f6858bb2613 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -109,6 +109,7 @@ dependencies = [ "cortex-m-rt", "defmt", "defmt-rtt", + "embedded-hal 0.2.7", "panic-probe", "rtic", "rtic-monotonics", diff --git a/Cargo.toml b/Cargo.toml index e9eb2873533e2e9585a50387503c0e536237fcf5..3f40ff7e42963f89bf32846bd1ca2cdb73e31af8 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -9,6 +9,7 @@ cortex-m = { version = "0.7.7", features = ["critical-section-single-core"] } cortex-m-rt = "0.7.3" defmt = "0.3.5" defmt-rtt = "0.4.0" +embedded-hal = "0.2.7" panic-probe = { version = "0.3.1", features = ["print-defmt"] } rtic = { version = "2.0.1", features = ["thumbv7-backend"] } rtic-monotonics = { version = "1.5.0", features = ["cortex-m-systick"] } diff --git a/README.org b/README.org index 951b97a49fe3b44e5b2c47ccdd89f0b31e730cbc..b5bed3dc644aea9b80c4d54f16b01ad728855b81 100644 --- a/README.org +++ b/README.org @@ -15,3 +15,7 @@ ** Driver IC TB6612FNG for dual DC motor - [[https://www.sparkfun.com/datasheets/Robotics/TB6612FNG.pdf][Datasheet]] + +** Encoders FIT0450 + +- [[https://wiki.dfrobot.com/Micro_DC_Motor_with_Encoder-SJ01_SKU__FIT0450][Wiki]] diff --git a/src/encoders.rs b/src/encoders.rs new file mode 100644 index 0000000000000000000000000000000000000000..289903a4b9770028ff48d268a6ebafe1090dafb5 --- /dev/null +++ b/src/encoders.rs @@ -0,0 +1,79 @@ +use cortex_m::prelude::_embedded_hal_Qei; +pub use embedded_hal::Direction; +use stm32f1xx_hal::{ + afio::MAPR, + gpio::{PA0, PA1, PA6, PA7}, + pac::{TIM2, TIM3}, + qei::{Qei, QeiOptions}, + rcc::Clocks, + timer::{Tim2NoRemap, Tim3NoRemap, Timer}, +}; + +pub struct Encoders { + left: Qei<TIM3, Tim3NoRemap, (PA6, PA7)>, + right: Qei<TIM2, Tim2NoRemap, (PA0, PA1)>, + count_left: u16, + count_right: u16, +} + +#[derive(Debug)] +pub struct EncoderValue { + count: u16, + direction: Direction, +} + +impl Encoders { + pub fn new( + pa0: PA0, + pa1: PA1, + pa6: PA6, + pa7: PA7, + tim2: TIM2, + tim3: TIM3, + mapr: &mut MAPR, + clocks: &Clocks, + ) -> Self { + let options = QeiOptions::default(); + let qei = Self { + left: Timer::new(tim3, clocks).qei((pa6, pa7), mapr, options), + right: Timer::new(tim2, clocks).qei((pa0, pa1), mapr, options), + count_left: 0, + count_right: 0, + }; + // Unsafe needed, see <https://github.com/stm32-rs/stm32f1xx-hal/issues/478> + unsafe { + stm32f1xx_hal::pac::Peripherals::steal() + .TIM2 + .ccer + .modify(|_, w| w.cc2p().set_bit()); + } + qei + } + + pub fn read(&self) -> (EncoderValue, EncoderValue) { + ( + EncoderValue { + count: self.left.count(), + direction: self.left.direction(), + }, + EncoderValue { + count: self.right.count(), + direction: self.right.direction(), + }, + ) + } + + pub fn ticks(&mut self) -> (i16, i16) { + let (left, right) = (self.left.count(), self.right.count()); + ( + ticks_since(&mut self.count_left, left), + ticks_since(&mut self.count_right, right), + ) + } +} + +fn ticks_since(old: &mut u16, new: u16) -> i16 { + let diff = (new - *old) as i16; + *old = new; + diff +} diff --git a/src/main.rs b/src/main.rs index 0ee0776052249acc347b469845972a8d457d2f6f..17d9c18c3b6c458f1e313cf1ac1cbd3152416112 100644 --- a/src/main.rs +++ b/src/main.rs @@ -2,10 +2,12 @@ #![no_main] #![feature(type_alias_impl_trait)] +mod encoders; mod tb6612fng; #[rtic::app(device = pac, dispatchers = [])] mod app { + use crate::encoders::Encoders; use crate::tb6612fng::{Movement, Tb6612fng}; use defmt_rtt as _; use panic_probe as _; @@ -81,6 +83,18 @@ mod app { ); serial.tx.bwrite_all(b"Hello, world\r\n").unwrap(); + let encoders = Encoders::new( + gpioa.pa0, + gpioa.pa1, + gpioa.pa6, + gpioa.pa7, + dp.TIM2, + dp.TIM3, + &mut afio.mapr, + &clocks, + ); + debug_encoders::spawn(encoders).ok().unwrap(); + (Shared {}, Local {}) } @@ -125,4 +139,18 @@ mod app { defmt::info!("Returning to standby mode"); motors.standby_enter(); } + + #[task] + async fn debug_encoders(_cx: debug_encoders::Context, mut encoders: Encoders) { + loop { + let (left, right) = encoders.read(); + defmt::info!( + "left = {:?}, right = {:?}", + defmt::Debug2Format(&left), + defmt::Debug2Format(&right) + ); + defmt::info!("ticks = {:?}", encoders.ticks()); + Systick::delay(100.millis()).await; + } + } }