-
Notifications
You must be signed in to change notification settings - Fork 254
-
Beta Was this translation helpful? Give feedback.
All reactions
Replies: 1 comment · 2 replies
-
|
Hi! First of all, welcome here :) You've taken up quite the challenge, these generic safety-through-typing abstractions are really hard to get right and require a lot of Rust and Rust macro wizardry... If you just care about your specific application, I think it would be entirely reasonable to just wrap your code into a struct and be done with it: pub struct PwmServoMotor {
pin: Pin<Output, PB5>,
timer: TC1,
}The next step up is making this work for all timers and output pins. The code skeleton you've shown in your second method goes into the right direction. But you will need to implement this for a ton of timer/pin combinations so there really isn't much choice but to write a macro for it. And this is where things start to get unwieldy... Essentially you have to do what was done in the avr-hal/mcu/atmega-hal/src/simple_pwm.rs Lines 1 to 1193 in e5c8f37
Regarding your first method: I wouldn't extend the // With explicit driver struct
let servo_driver = avr_servo_driver::PwmServoMotor::new(
dp.TC1,
pins.pb5.into_output(),
);
// With extension trait, which you explicitly have to import
use avr_servo_driver::PinExt as _;
let servo_driver = pins.pb5.into_pwm_servo(dp.TC1);I think the first option is much easier to read and understand. With all that out of the way, one more thing: Using a timer for servo control is nice because it happens entirely off-cpu. But it limits you to how many servos you can control. That's why, for example, the official Arduino C++ servo library instead just uses a timer to schedule an interrupt for updating an arbitrary number of GPIO output pins. This allows creating as many servos as you want from a single timer peripheral. At the cost of a bit more CPU time, of course. |
Beta Was this translation helpful? Give feedback.
All reactions
-
|
Many thanks for all the information! It's quite a challenge yes, but a good opportunity to go in depth on how embedded systems work. Since I'm putting in the effort and I'm using so much of community info and tools, I figured that turning it into a crate may be a nice return to the community if it ends up being used 😃 I think I'll go with the explicit struct method and then indeed go on and write a macro for it. I may be back for more questions later on in the process. Let's see where I get first 😄 There may be a first question though: If I want to test on different chipsets, I suppose QEMU is the way to go. But do you have a reference on how to test PWM signal output when using QEMU? I'm googling but haven't found something useful yet (which surprises me, so it may be that I'm using the wrong terminology) |
Beta Was this translation helpful? Give feedback.
All reactions
-
|
For simulation, I've always used You may find @Patryk27's https://codeberg.org/pwy/avr-tester interesting. But to be honest, I would not try simulating hardware interaction too much. There are too many variables, making simulation results an unreliable indicator of whether the real hardware works. I would always test with real hardware and rather build a test-harness around a real board than to use simulation. |
Beta Was this translation helpful? Give feedback.
All reactions
-
👍 1
Hi! First of all, welcome here :)
You've taken up quite the challenge, these generic safety-through-typing abstractions are really hard to get right and require a lot of Rust and Rust macro wizardry...
If you just care about your specific application, I think it would be entirely reasonable to just wrap your code into a struct and be done with it:
The next step up is making this work for all timers and output pins. The code skeleton you've shown in your second method goes into the right direction. But you will need to implement this for a ton of timer/pin combinations so there really isn't much choice but to write a m…