Help - Raspberry Pi Pico - Stepper motor A4988/DRV8825

Hello fellow rustaceans to be.

I am coming from Python and Micropython and have no previous knowledge of C/C++ or smilar compiled languages.

I have previously used stepper motors and digital servos using Pi Pico and Micropython, lately trying PIO for smoother operation. However PIO seems to be quite a steep curve, and for what i want to do with Micro controllers, i think a faster language like Rust would be better to learn in the long term.

But as i said, i am a complete beginner at this, so please be patient with me, and i will try my best to provide enough information and the correct information.

My goal:
Make a program in rust that is being run on a Pi Pico, that controls two steppers (semingly) simultaneously, but actual simultaneous operation would be even better.
I want to be able to have a list or tuple (or what blazingly fast method Rust uses), with sets of coordinates, so that the two motors can either move in 2D x/y plane or control two joints. At a later stage, i want to have used input, like buttons, to control all 4 motions to set joint angels to make "way points" which are then stored. (With Micropython i store lists i a separate file which is read at boot) Finally, once booted, the device should listen for interrupt via either button or handshake from a robot, passing the handshake along to a third device once operation is completed.

Progress:
I have started reading The Rust Programming Language and have just finished the Guessing game. It's not to hard, but i wont be finishing the book anytime soon.
After finishing chapter 2 i configured github rp-rs/rp-hal and used cargo to load pico_blinky_pwm onto one of my board successfully.
After this i set up vscode with rust-analyzer and tried loading wiggly_mouse to the pi pico to make sure everything was working there as well.

Where I am at...:
I started to search for a complete library to use, which i didn't find, so i went this route:
Use a working template --> Add a stepper library.

With Python this would be as easy as 1 - 2 - 3, i realize this isn't the case for Rust, not at my skill level anyways.

I started a project based on: rp-hal/pico_gpio_in_out.rs at main · rp-rs/rp-hal · GitHub to try and figure out how to control gpio's.

Then i started to try and add stuff from Stepper in stepper - Rust. Now, as you can imagine, I am flooded with errors which i have no clue what they are, and as this is sort of uncharted waters, i can't be saved by the grace of google.

Now i am hoping that this forum can help me with the errors I have obtained, clean up the code, put things in the correct order and help me get better.

As mentioned, i am using a Pi Pico connected to a working setup of a A4988 and Nema17 stepper motor. Controlling them with Step and Dir only.

After getting rid of all errors, the next step will be to just see if the motor turns when the pico is booted. A simple start/stop loop would suffice.

The code (abomination):

#![no_std]
#![no_main]

// The macro for our start-up function
use rp_pico::entry;

// GPIO traits - Add output and input pins. Will use button to execute.
use embedded_hal::digital::v2::{InputPin, OutputPin};

// Ensure we halt the program on panic (if we don't mention this crate it won't
// be linked)
use panic_halt as _;

// Pull in any important traits
use rp_pico::hal::prelude::*;

// A shorter alias for the Peripheral Access Crate, which provides low-level
// register access
use rp_pico::hal::pac;

// A shorter alias for the Hardware Abstraction Layer, which provides
// higher-level drivers.
use rp_pico::hal;

// Adding a suggested timer and countdown...
use rp2040_hal::Timer;
use embedded_hal::timer::CountDown;
// Adding stepper driver???
use stepper::drivers::drv8825::DRV8825;

/// Entry point to our bare-metal application.
///
/// The `#[entry]` macro ensures the Cortex-M start-up code calls this function
/// as soon as all global variables are initialised.

#[entry]
fn main() -> ! {
    // Grab our singleton objects
    let mut pac = pac::Peripherals::take().unwrap();

    // Note - we don't do any clock set-up in this example. The RP2040 will run
    // at it's default clock speed.

    // The single-cycle I/O block controls our GPIO pins
    let sio = hal::Sio::new(pac.SIO);

    // Set the pins up according to their function on this particular board
    let pins = rp_pico::Pins::new(
        pac.IO_BANK0,
        pac.PADS_BANK0,
        sio.gpio_bank0,
        &mut pac.RESETS,
    );

    // STEPPER PROGRAM STARTS HERE!?
    use stepper::{
        fugit::NanosDurationU32 as Nanoseconds,
        motion_control, ramp_maker,
        Direction, Stepper,
    };

    // We need some `embedded_hal::digital::OutputPin` implementations connected
    // to the STEP and DIR signals of our driver chip. How you acquire those
    // depends on the platform you run on. Here, we'll use a mock implementation
    // for the sake of demonstration.
    // let step = Pin;
    //let dir = Pin;
    let mut step = pins.gpio0.into_push_pull_output();
    let mut dir = pins.gpio1.into_push_pull_output();
    //    // Our button input
    //let button_pin = pins.gpio15.into_pull_up_input();

    // We also need a timer (that implements `embedded_hal::timer::CountDown`),
    // since there are time-critical aspects to communicating with the driver
    // chip. Again, how you acquire one depends on your target platform, and
    // again, we'll use a mock here for the sake of demonstration.
    let mut timer = <dyn embedded_hal::timer::CountDown::<1_000_000>>::new();//Timer

    // Define the numeric type we're going to use. We'll use a fixed-point type
    // here, as that's the most widely supported. If your target hardware has
    // support for floating point, it might be more convenient (and possibly
    // efficient) to use that instead.
    type Num = fixed::FixedI64<typenum::U32>;//fixed/floating

    // Define the target acceleration and maximum speed using timer ticks as the
    // unit of time. We could also use seconds or any other unit of time
    // (Stepper doesn't care), but then we'd need to provide a conversion from
    // seconds to timer ticks. This way, we save that conversion.
    //
    // These values assume a 1 MHz timer, but that depends on the timer you're
    // using, of course.
    let target_accel = Num::from_num(0.001); // steps / tick^2; 1000 steps / s^2
    let max_speed = Num::from_num(0.001); // steps / tick; 1000 steps / s

    // We want to use the high-level motion control API (see below), but let's
    // assume the driver we use for this example doesn't provide hardware
    // support for that. Let's instantiate a motion profile from the RampMaker
    // library to provide a software fallback.
    let profile = ramp_maker::Trapezoidal::new(target_accel);

    // Now we need to initialize the stepper API. We do this by initializing a
    // driver (`MyDriver`), then wrapping that into the generic API (`Stepper`).
    // `MyDriver` is a placeholder. In a real use-case, you'd typically use one
    // of the drivers from the `stepper::drivers` module, but any driver that
    // implements the traits from `stepper::traits` will do.
    //
    // By default, drivers can't do anything after being initialized. This means
    // they also don't require any hardware resources, which makes them easier
    // to use when you don't need all features.
    let mut stepper = Stepper::drivers(DRV8825::new())// let mut stepper = Stepper::from_driver(MyDriver::new())
        // Enable direction control
        .enable_direction_control(dir, Direction::Forward, &mut timer)?
        // Enable step control
        .enable_step_control(step)
        // Enable motion control using the software fallback
        .enable_motion_control((timer, profile, DelayToTicks));

    // Tell the motor to move 2000 steps (10 revolutions on a typical stepper
    // motor), while respecting the maximum speed. Since we selected a
    // trapezoidal motion profile above, this will result in a controlled
    // acceleration to the maximum speed, and a controlled deceleration after.
    let target_step = 2000;
    stepper
        .move_to_position(max_speed, target_step)
        .wait()?;

    // Here's the converter that Stepper is going to use internally, to convert
    // from the computed delay value to timer ticks. Since we chose to use timer
    // ticks as the unit of time for velocity and acceleration, this conversion
    // is pretty simple (and cheap).
    use num_traits::cast::ToPrimitive;
    pub struct DelayToTicks;
    impl<const TIMER_HZ: u32> motion_control::DelayToTicks<Num, TIMER_HZ> for DelayToTicks {
        type Error = core::convert::Infallible;

        fn delay_to_ticks(&self, delay: Num)
            -> Result<fugit::TimerDurationU32<TIMER_HZ>, Self::Error>
        {
            Ok(fugit::TimerDurationU32::<TIMER_HZ>::from_ticks(Num::to_u32(&delay).expect("the delay to convert")))
        }
    }
}

Cargo.TOML:
Here i have tried adding dependencies that where missing as they where presented by the terminal.
From what i can tell, this is a way to point at libraries so that when imported using "use", there is a target?

Summary
name = "rp-pico"
version = "0.4.1"
authors = ["evan <evanmolder@gmail.com>", "The rp-rs Developers"]
edition = "2018"
homepage = "https://github.com/rp-rs/rp-hal/tree/main/boards/rp-pico"
description = "Board Support Package for the Raspberry Pi Pico"
license = "MIT OR Apache-2.0"
repository = "https://github.com/rp-rs/rp-hal.git"

#See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html

[dependencies]
cortex-m = "0.7.2"
rp2040-boot2 = { version = "0.2.0", optional = true }
rp2040-hal = { path = "../../rp2040-hal", version = "0.5.0" }
cortex-m-rt = { version = "0.7", optional = true }
embedded-time = "0.12.0"
usb-device= "0.2.9"
usbd-serial = "0.1.1"
usbd-hid = "0.5.1"
futures = { version = "0.3", default-features = false, optional = true }
stepper = "0.6.0"
fugit = "0.3.6"
fixed = "0.3.2"
typenum = "1.15.0"


[dependencies.num-traits]
version = "0.2"
default-features = false
features = ["libm"]    # <--- Uncomment if you wish to use `Float` and `Real` without `std`

[dev-dependencies]
panic-halt= "0.2.0"
embedded-hal ="0.2.5"
cortex-m-rtic = "1.1.2"
nb = "1.0"
i2c-pio = "0.3.0"
heapless = "0.7.9"
embedded-sdmmc = { git = "https://github.com/rust-embedded-community/embedded-sdmmc-rs.git" }
smart-leds = "0.3.0"
ws2812-pio = "0.3.0"
ssd1306 = "0.7.0"
embedded-graphics = "0.7.1"
hd44780-driver = "0.4.0"
pio = "0.2.0"
pio-proc = "0.2.1"

defmt = "0.3.0"
defmt-rtt = "0.3.0"

[features]
default = ["boot2", "rt"]
boot2 = ["rp2040-boot2"]
rt = ["cortex-m-rt","rp2040-hal/rt"]

Errors:
There are all errors i have been able to capture, as i get a lot of warnings, making the terminal so full i cant see them all.

Summary
>error[E0599]: no function or associated item named `to_u32` found for struct `FixedI64` in the current scope
   --> boards\rp-pico\examples\stepper_example.rs:166:69
    |
166 |             Ok(fugit::TimerDurationU32::<TIMER_HZ>::from_ticks(Num::to_u32(&delay).expect("the delay to convert")))
    |                                                            
         ^^^^^^
    |                                                            
         |
    |                                                            
         function or associated item not found in `FixedI64<UInt<UInt<UInt<UInt<UInt<UInt<UTerm, B1>, B0>, B0>, B0>, B0>, B0>>`   
    |                                                            
         help: there is an associated function with a similar name: `to_f32`

>error[E0308]: mismatched types
  --> boards\rp-pico\examples\stepper_example.rs:64:14
   |
63 | #[entry]
   | -------- implicitly returns `()` as its body has no tail or `return` expression
64 | fn main() -> ! {
   |              ^ expected `!`, found `()`
   |
   = note:   expected type `!`
           found unit type `()`
>error[E0277]: the `?` operator can only be used in a function that returns `Result` or `Option` (or another type that implements `FromResidual`)
   --> boards\rp-pico\examples\stepper_example.rs:152:16
    |
64  | / fn main() -> ! {
65  | |     // Grab our singleton objects
66  | |     let mut pac = pac::Peripherals::take().unwrap();
67  | |
...   |
152 | |         .wait()?;
    | |                ^ cannot use the `?` operator in a function that returns `!`
...   |
168 | |     }
169 | | }
    | |_- this function should return `Result` or `Option` to accept `?`
    |
    = help: the trait `FromResidual<_>` is not implemented for `!`

>error[E0277]: the `?` operator can only be used in a function that returns `Result` or `Option` (or another type that implements `FromResidual`)
   --> boards\rp-pico\examples\stepper_example.rs:139:71
    |
64  | / fn main() -> ! {
65  | |     // Grab our singleton objects
66  | |     let mut pac = pac::Peripherals::take().unwrap();     
67  | |
...   |
139 | |         .enable_direction_control(dir, Direction::Forward, &mut timer)?
    | |                                                          
             ^ cannot use the `?` operator in a function that returns `!`
...   |
168 | |     }
169 | | }
    | |_- this function should return `Result` or `Option` to accept `?`
    |
    = help: the trait `FromResidual<_>` is not implemented for `!`

>error[E0599]: no function or associated item named `drivers` found for struct `Stepper` in the current scope
   --> boards\rp-pico\examples\stepper_example.rs:137:32
    |
137 |     let mut stepper = Stepper::drivers(DRV8825::new())// let mut stepper = Stepper::from_driver(MyDriver::new())
    |                                ^^^^^^^
    |                                |
    |                                function or associated item not found in `Stepper<_>`
    |                                help: there is an associated function with a similar name: `driver`

>error[E0191]: the value of the associated type `Time` (from trait `_embedded_hal_timer_CountDown`) must be specified
   --> boards\rp-pico\examples\stepper_example.rs:104:26
    |
104 |     let mut timer = <dyn embedded_hal::timer::CountDown::<1_000_000>>::new();//Timer
    |                          ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ associated type `Time` must be specified

>error[E0599]: no function or associated item named `new` found for trait object `dyn _embedded_hal_timer_CountDown` in the current scope
   --> boards\rp-pico\examples\stepper_example.rs:104:72
    |
104 |     let mut timer = <dyn embedded_hal::timer::CountDown::<1_000_000>>::new();//Timer
    |                                                            
            ^^^ function or associated item not found in `dyn _embedded_hal_timer_CountDown`

>error[E0599]: no function or associated item named `from_num` found for struct `FixedI64` in the current scope
   --> boards\rp-pico\examples\stepper_example.rs:119:29
    |
119 |     let target_accel = Num::from_num(0.001); // steps / tick^2; 1000 steps / s^2
    |                             ^^^^^^^^ function or associated item not found in `FixedI64<UInt<UInt<UInt<UInt<UInt<UInt<UTerm, B1>, B0>, B0>, B0>, B0>, B0>>`

>error[E0599]: no function or associated item named `from_num` found for struct `FixedI64` in the current scope
   --> boards\rp-pico\examples\stepper_example.rs:120:26
    |
120 |     let max_speed = Num::from_num(0.001); // steps / tick; 1000 steps / s
    |                          ^^^^^^^^ function or associated item not found in `FixedI64<UInt<UInt<UInt<UInt<UInt<UInt<UTerm, B1>, B0>, B0>, B0>, B0>, B0>>`

>error[E0107]: this trait takes 0 generic arguments but 1 generic argument was supplied
   --> boards\rp-pico\examples\stepper_example.rs:104:47
    |
104 |     let mut timer = <dyn embedded_hal::timer::CountDown::<1_000_000>>::new();//Timer
    |                                               ^^^^^^^^^   --------- help: replace the generic bound with the associated type: `Time = 1_000_000`
    |                                               |
    |                                               expected 0 generic arguments
    |
note: trait defined here, with 0 generic parameters
   --> C:\Users\vende\.cargo\registry\src\github.com-1ecc6299db9ec823\embedded-hal-0.2.7\src\timer.rs:60:11
    |
60  | pub trait CountDown {
    |   

>error[E0282]: type annotations needed
   --> boards\rp-pico\examples\stepper_example.rs:104:59
    |
104 |     let mut timer = <dyn embedded_hal::timer::CountDown::<1_000_000>>::new();//Timer
    |                                                           ^^^^^^^^^ cannot infer type for type `{integer}`

This topic was automatically closed 90 days after the last reply. We invite you to open a new topic if you have further questions or comments.