1
Fork 0

servo control

This commit is contained in:
Andy Killorin 2024-05-01 15:58:00 -05:00
parent 54ab1ba86d
commit bc920907bd
Signed by: ank
GPG key ID: 23F9463ECB67FE8C
3 changed files with 77 additions and 16 deletions

View file

@ -12,12 +12,14 @@ bench = false
[dependencies] [dependencies]
panic-halt = "0.2.0" panic-halt = "0.2.0"
ufmt = "0.2.0" ufmt = "0.2.0"
nb = "0.1.2" nb = "1"
embedded-hal = "0.2.3" embedded-hal = "1"
[dependencies.avr-hal-generic]
git = "https://github.com/rahix/avr-hal"
[dependencies.arduino-hal] [dependencies.arduino-hal]
git = "https://github.com/rahix/avr-hal" git = "https://github.com/rahix/avr-hal"
rev = "3e362624547462928a219c40f9ea8e3a64f21e5f"
features = ["arduino-uno"] features = ["arduino-uno"]
# The latest releases of `proc-macro2` do not support the rust toolchain that # The latest releases of `proc-macro2` do not support the rust toolchain that

View file

@ -1,27 +1,28 @@
#![no_std] #![cfg_attr(not(test), no_std)]
#![no_main] #![no_main]
use panic_halt as _; use panic_halt as _;
mod servo;
use servo::Servo;
#[arduino_hal::entry] #[arduino_hal::entry]
fn main() -> ! { fn main() -> ! {
let dp = arduino_hal::Peripherals::take().unwrap(); let dp = arduino_hal::Peripherals::take().unwrap();
let pins = arduino_hal::pins!(dp); let pins = arduino_hal::pins!(dp);
/* // configure timer for servos
* For examples (and inspiration), head to pins.d9.into_output();
* pins.d10.into_output();
* https://github.com/Rahix/avr-hal/tree/main/examples let tc1 = dp.TC1; // 250kHz
* tc1.icr1.write(|w| w.bits(4999)); // 250kHz/5000 = 50Hz
* NOTE: Not all examples were ported to all boards! There is a good chance though, that code tc1.tccr1a.write(|w| w.wgm1().bits(0b10).com1a().match_clear());
* for a different board can be adapted for yours. The Arduino Uno currently has the most tc1.tccr1b.write(|w| w.wgm1().bits(0b11).cs1().prescale_64());
* examples available.
*/
let mut led = pins.d13.into_output(); let carriage = &tc1.ocr1a; // pin 9
let claw = &tc1.ocr1b; // pin 10
loop { loop {
led.toggle(); carriage.set_speed(1.0);
arduino_hal::delay_ms(1000); arduino_hal::delay_ms(20);
} }
} }

58
src/servo.rs Normal file
View file

@ -0,0 +1,58 @@
use arduino_hal::pac::tc1::OCR1B;
use arduino_hal::pac::tc1::OCR1A;
const MIN: u16 = 100; // *4us = .4ms
const MAX: u16 = 700; // *4us = 2.8ms
const RANGE: u16 = MAX-MIN;
pub(crate) trait Servo {
/// -1.0 full reverse, 1.0 full forward
fn set_speed(&self, speed: f32) {
self.set_duty(calculate_duty(speed));
}
fn set_duty(&self, duty: u16);
}
#[inline(always)]
/// -1.0 full reverse, 1.0 full forward
fn calculate_duty(speed: f32) -> u16 {
let speed = speed / 2.0 + 0.5;
let duty = speed * RANGE as f32 + MIN as f32;
duty as u16
}
impl Servo for OCR1A { // pin 9
fn set_duty(&self, duty: u16) {
self.write(|w| w.bits(duty));
}
}
impl Servo for OCR1B { // pin 10
fn set_duty(&self, duty: u16) {
self.write(|w| w.bits(duty));
}
}
#[cfg(test)]
mod tests {
// unit tests don't run on avr-hal-template projects, could be due to target rules, could be
// no_std. to troubleshoot later
extern crate std;
use crate::servo::calculate_duty;
#[test]
fn forward() {
assert_eq!(MAX, calculate_duty(1.0));
}
#[test]
fn reverse() {
assert_eq!(MIN, calculate_duty(-1.0));
}
#[test]
fn stopped() {
assert_eq!(MIN+RANGE/2, calculate_duty(0.0));
}
}