diff --git a/.vscode/settings.json b/.vscode/settings.json
index 5234c64..bacd3af 100644
--- a/.vscode/settings.json
+++ b/.vscode/settings.json
@@ -1,5 +1,6 @@
{
"rust-analyzer.cargo.target": "thumbv6m-none-eabi",
"rust-analyzer.checkOnSave.allTargets": false,
- "editor.formatOnSave": true
+ "editor.formatOnSave": true,
+ "workbench.colorTheme": "Default Dark+"
}
\ No newline at end of file
diff --git a/README.md b/README.md
index 6d9f121..b79110e 100644
--- a/README.md
+++ b/README.md
@@ -1,279 +1,12 @@
-# Project template for rp2040-hal
+# RP2040 Rust Robot
+Robot controller code in Rust for a two wheel robot driven by a _Raspberry Pi Pico (RP2040)_.
-This template is intended as a starting point for developing your own firmware based on the rp2040-hal.
+_This is a Work in Progress_
-It includes all of the `knurling-rs` tooling as showcased in https://github.com/knurling-rs/app-template (`defmt`, `defmt-rtt`, `panic-probe`, `flip-link`) to make development as easy as possible.
+This project is a fork of the [rp2040-project-template](https://github.com/rp-rs/rp2040-project-template). See the template's [README.md](https://github.com/rp-rs/rp2040-project-template/blob/main/README.md) for details on how to build the code found here for the RP2040.
-`probe-rs` is configured as the default runner, so you can start your program as easy as
-```sh
-cargo run --release
-```
-If you aren't using a debugger (or want to use other debugging configurations), check out [alternative runners](#alternative-runners) for other options
-
-
-
-
- Table of Contents
-
- - Requirements
- - Installation of development dependencies
- - Running
- - Alternative runners
- - Notes on using rp2040_boot2
- - Feature flags
- - Roadmap
- - Contributing
- - Code of conduct
- - License
- - Contact
-
-
-
-
-
- Requirements
-
-- The standard Rust tooling (cargo, rustup) which you can install from https://rustup.rs/
-
-- Toolchain support for the cortex-m0+ processors in the rp2040 (thumbv6m-none-eabi)
-
-- flip-link - this allows you to detect stack-overflows on the first core, which is the only supported target for now.
-
-- (by default) A [`probe-rs` installation](https://probe.rs/docs/getting-started/installation/)
-
-- A [`probe-rs` compatible](https://probe.rs/docs/getting-started/probe-setup/) probe
-
- You can use a second
- [Pico as a CMSIS-DAP debug probe](debug_probes.md#raspberry-pi-pico). Details
- on other supported debug probes can be found in
- [debug_probes.md](debug_probes.md)
-
-
-
-
-
- Installation of development dependencies
-
-```sh
-rustup target install thumbv6m-none-eabi
-cargo install flip-link
-# Installs the probe-rs tools, including probe-rs run, our recommended default runner
-cargo install probe-rs --features=cli --locked
-# If you want to use elf2uf2-rs instead, do...
-cargo install elf2uf2-rs --locked
-```
-If you get the error ``binary `cargo-embed` already exists`` during installation of probe-rs, run `cargo uninstall cargo-embed` to uninstall your older version of cargo-embed before trying again.
-
-
-
-
-
-
- Running
-
-For a debug build
-```sh
-cargo run
-```
-For a release build
-```sh
-cargo run --release
-```
-
-If you do not specify a DEFMT_LOG level, it will be set to `debug`.
-That means `println!("")`, `info!("")` and `debug!("")` statements will be printed.
-If you wish to override this, you can change it in `.cargo/config.toml`
-```toml
-[env]
-DEFMT_LOG = "off"
-```
-You can also set this inline (on Linux/MacOS)
-```sh
-DEFMT_LOG=trace cargo run
-```
-
-or set the _environment variable_ so that it applies to every `cargo run` call that follows:
-#### Linux/MacOS/unix
-```sh
-export DEFMT_LOG=trace
-```
-
-Setting the DEFMT_LOG level for the current session
-for bash
-```sh
-export DEFMT_LOG=trace
-```
-
-#### Windows
-Windows users can only override DEFMT_LOG through `config.toml`
-or by setting the environment variable as a separate step before calling `cargo run`
-- cmd
-```cmd
-set DEFMT_LOG=trace
-```
-- powershell
-```ps1
-$Env:DEFMT_LOG = trace
-```
-
-```cmd
-cargo run
-```
-
-
-
-
- Alternative runners
-
-If you don't have a debug probe or if you want to do interactive debugging you can set up an alternative runner for cargo.
-
-Some of the options for your `runner` are listed below:
-
-* **`cargo embed`**
- This is basically a more configurable version of `probe-rs run`, our default runner.
- See [the `cargo-embed` tool docs page](https://probe.rs/docs/tools/cargo-embed/) for
- more information.
-
- *Step 1* - Install `cargo-embed`. This is part of the [`probe-rs`](https://crates.io/crates/probe-rs) tools:
-
- ```console
- $ cargo install probe-rs --features=cli --locked
- ```
-
- *Step 2* - Update settings in [Embed.toml](./Embed.toml)
- - The defaults are to flash, reset, and start a defmt logging session
- You can find all the settings and their meanings [in the probe-rs repo](https://github.com/probe-rs/probe-rs/blob/c0610e98008cbb34d0dc056fcddff0f2d4f50ad5/probe-rs/src/bin/probe-rs/cmd/cargo_embed/config/default.toml)
-
- *Step 3* - Use the command `cargo embed`, which will compile the code, flash the device
- and start running the configuration specified in Embed.toml
-
- ```console
- $ cargo embed --release
- ```
-
-* **probe-rs-debugger**
- *Step 1* - Install Visual Studio Code from https://code.visualstudio.com/
-
- *Step 2* - Install `probe-rs`
- ```console
- $ cargo install probe-rs --features=cli --locked
- ```
-
- *Step 3* - Open this project in VSCode
-
- *Step 4* - Install `debugger for probe-rs` via the VSCode extensions menu (View > Extensions)
-
- *Step 5* - Launch a debug session by choosing `Run`>`Start Debugging` (or press F5)
-
-* **Loading a UF2 over USB**
- *Step 1* - Install [`elf2uf2-rs`](https://github.com/JoNil/elf2uf2-rs):
-
- ```console
- $ cargo install elf2uf2-rs --locked
- ```
-
- *Step 2* - Modify `.cargo/config` to change the default runner
-
- ```toml
- [target.`cfg(all(target-arch = "arm", target_os = "none"))`]
- runner = "elf2uf2-rs -d"
- ```
-
- The all-Arm wildcard `'cfg(all(target_arch = "arm", target_os = "none"))'` is used
- by default in the template files, but may also be replaced by
- `thumbv6m-none-eabi`.
-
- *Step 3* - Boot your RP2040 into "USB Bootloader mode", typically by rebooting
- whilst holding some kind of "Boot Select" button. On Linux, you will also need
- to 'mount' the device, like you would a USB Thumb Drive.
-
- *Step 4* - Use `cargo run`, which will compile the code and start the
- specified 'runner'. As the 'runner' is the `elf2uf2-rs` tool, it will build a UF2
- file and copy it to your RP2040.
-
- ```console
- $ cargo run --release
- ```
-
-* **Loading with picotool**
- As ELF files produced by compiling Rust code are completely compatible with ELF
- files produced by compiling C or C++ code, you can also use the Raspberry Pi
- tool [picotool](https://github.com/raspberrypi/picotool). The only thing to be
- aware of is that picotool expects your ELF files to have a `.elf` extension, and
- by default Rust does not give the ELF files any extension. You can fix this by
- simply renaming the file.
-
- This means you can't easily use it as a cargo runner - yet.
-
- Also of note is that the special
- [pico-sdk](https://github.com/raspberrypi/pico-sdk) macros which hide
- information in the ELF file in a way that `picotool info` can read it out, are
- not supported in Rust. An alternative is TBC.
-
-
-
-
- Notes on using rp2040_boot2
-
- The second-stage boot loader must be written to the .boot2 section. That
- is usually handled by the board support package (e.g.`rp-pico`). If you don't use
- one, you should initialize the boot loader manually. This can be done by adding the
- following to the beginning of main.rs:
- ```rust
- use rp2040_boot2;
- #[link_section = ".boot2"]
- #[used]
- pub static BOOT_LOADER: [u8; 256] = rp2040_boot2::BOOT_LOADER_W25Q080;
- ```
-
-
-
-
-
- Feature flags
-
- There are several [feature flags in rp2040-hal](https://docs.rs/rp2040-hal/latest/rp2040_hal/#crate-features).
- If you want to enable some of them, uncomment the `rp2040-hal` dependency in `Cargo.toml` and add the
- desired feature flags there. For example, to enable ROM functions for f64 math using the feature `rom-v2-intrinsics`:
- ```
- rp2040-hal = { version="0.9", features=["rt", "critical-section-impl", "rom-v2-intrinsics"] }
- ```
-
-
-
-
-## Roadmap
-
-NOTE These packages are under active development. As such, it is likely to
-remain volatile until a 1.0.0 release.
-
-See the [open issues](https://github.com/rp-rs/rp2040-project-template/issues) for a list of
-proposed features (and known issues).
-
-## Contributing
-
-Contributions are what make the open source community such an amazing place to be learn, inspire, and create. Any contributions you make are **greatly appreciated**.
-
-The steps are:
-
-1. Fork the Project by clicking the 'Fork' button at the top of the page.
-2. Create your Feature Branch (`git checkout -b feature/AmazingFeature`)
-3. Make some changes to the code or documentation.
-4. Commit your Changes (`git commit -m 'Add some AmazingFeature'`)
-5. Push to the Feature Branch (`git push origin feature/AmazingFeature`)
-6. Create a [New Pull Request](https://github.com/rp-rs/rp-hal/pulls)
-7. An admin will review the Pull Request and discuss any changes that may be required.
-8. Once everyone is happy, the Pull Request can be merged by an admin, and your work is part of our project!
-
-## Code of Conduct
-
-Contribution to this crate is organized under the terms of the [Rust Code of
-Conduct][CoC], and the maintainer of this crate, the [rp-rs team], promises
-to intervene to uphold that code of conduct.
-
-[CoC]: CODE_OF_CONDUCT.md
-[rp-rs team]: https://github.com/orgs/rp-rs/teams/rp-rs
+## Hardware
## License
@@ -284,8 +17,3 @@ information on each specific licence.
Any submissions to this project (e.g. as Pull Requests) must be made available
under these terms.
-
-## Contact
-
-Raise an issue: [https://github.com/rp-rs/rp2040-project-template/issues](https://github.com/rp-rs/rp2040-project-template/issues)
-Chat to us on Matrix: [#rp-rs:matrix.org](https://matrix.to/#/#rp-rs:matrix.org)
diff --git a/src/l298n/mod.rs b/src/l298n/mod.rs
new file mode 100644
index 0000000..dc57be1
--- /dev/null
+++ b/src/l298n/mod.rs
@@ -0,0 +1 @@
+pub mod motor_controller;
diff --git a/src/l298n/motor_controller.rs b/src/l298n/motor_controller.rs
new file mode 100644
index 0000000..d30ed59
--- /dev/null
+++ b/src/l298n/motor_controller.rs
@@ -0,0 +1,125 @@
+use embedded_hal::digital::v2::OutputPin;
+use embedded_hal::PwmPin;
+
+pub struct MotorController {
+ ina1: INA1,
+ ina2: INA2,
+ inb1: INB1,
+ inb2: INB2,
+ ena: ENA,
+ enb: ENB,
+}
+
+#[allow(dead_code)]
+impl MotorController
+where
+ INA1: OutputPin,
+ INA2: OutputPin,
+ INB1: OutputPin,
+ INB2: OutputPin,
+ ENA: PwmPin,
+ ENB: PwmPin,
+{
+ pub fn new(ina1: INA1, ina2: INA2, inb1: INB1, inb2: INB2, ena: ENA, enb: ENB) -> Self
+ where
+ INA1: OutputPin,
+ INA2: OutputPin,
+ INB1: OutputPin,
+ INB2: OutputPin,
+ ENA: PwmPin,
+ ENB: PwmPin,
+ {
+ Self {
+ ina1,
+ ina2,
+ inb1,
+ inb2,
+ ena,
+ enb,
+ }
+ }
+
+ pub fn set_duty(&mut self, duty_a: ENA::Duty, duty_b: ENB::Duty) {
+ self.ena.set_duty(duty_a);
+ self.enb.set_duty(duty_b);
+ }
+
+ pub fn set_duty_a(&mut self, duty: ENA::Duty) {
+ self.ena.set_duty(duty);
+ }
+
+ pub fn set_duty_b(&mut self, duty: ENB::Duty) {
+ self.enb.set_duty(duty);
+ }
+
+ pub fn get_duty_a(&self) -> ENA::Duty {
+ self.ena.get_duty()
+ }
+
+ pub fn get_duty_b(&self) -> ENB::Duty {
+ self.enb.get_duty()
+ }
+
+ pub fn forward(&mut self) {
+ self.ina1.set_high().ok();
+ self.ina2.set_low().ok();
+ self.inb1.set_high().ok();
+ self.inb2.set_low().ok();
+ self.ena.enable();
+ self.enb.enable();
+ }
+
+ pub fn forward_a(&mut self) {
+ self.ina1.set_high().ok();
+ self.ina2.set_low().ok();
+ self.ena.enable();
+ }
+
+ pub fn forward_b(&mut self) {
+ self.inb1.set_high().ok();
+ self.inb2.set_low().ok();
+ self.enb.enable();
+ }
+
+ pub fn reverse(&mut self) {
+ self.ina1.set_low().ok();
+ self.ina2.set_high().ok();
+ self.inb1.set_low().ok();
+ self.inb2.set_high().ok();
+ self.ena.enable();
+ self.enb.enable();
+ }
+
+ pub fn reverse_a(&mut self) {
+ self.ina1.set_low().ok();
+ self.ina2.set_high().ok();
+ self.ena.enable();
+ }
+
+ pub fn reverse_b(&mut self) {
+ self.inb1.set_low().ok();
+ self.inb2.set_high().ok();
+ self.enb.enable();
+ }
+
+ pub fn stop(&mut self) {
+ self.ena.disable();
+ self.enb.disable();
+ self.ina1.set_low().ok();
+ self.ina2.set_low().ok();
+ self.inb1.set_low().ok();
+ self.inb2.set_low().ok();
+ }
+
+ pub fn stop_a(&mut self) {
+ self.ena.disable();
+ self.ina1.set_low().ok();
+ self.ina2.set_low().ok();
+ }
+
+ pub fn stop_b(&mut self) {
+ self.enb.disable();
+ self.inb1.set_low().ok();
+ self.inb2.set_low().ok();
+ }
+}
diff --git a/src/main.rs b/src/main.rs
index 71b0223..21ad126 100644
--- a/src/main.rs
+++ b/src/main.rs
@@ -3,6 +3,7 @@
//! This will blink an LED attached to GP25, which is the pin the Pico uses for the on-board LED.
#![no_std]
#![no_main]
+mod l298n;
use bsp::entry;
use defmt::*;
@@ -18,10 +19,13 @@ use rp_pico as bsp;
use bsp::hal::{
clocks::{init_clocks_and_plls, Clock},
pac,
+ pwm::Slices,
sio::Sio,
watchdog::Watchdog,
};
+use l298n::motor_controller::MotorController;
+
#[entry]
fn main() -> ! {
info!("Program start");
@@ -53,6 +57,32 @@ fn main() -> ! {
&mut pac.RESETS,
);
+ // Init PWMs
+ let pwm_slices = Slices::new(pac.PWM, &mut pac.RESETS);
+ // Configure PWM
+ let mut pwm3 = pwm_slices.pwm3;
+
+ pwm3.set_ph_correct();
+ pwm3.enable();
+
+ let mut channel_a = pwm3.channel_a;
+ let mut channel_b = pwm3.channel_b;
+
+ channel_a.output_to(pins.gpio6);
+ channel_b.output_to(pins.gpio7);
+
+ // set up motor controller
+ let mut motor_controller = MotorController::new(
+ pins.gpio8.into_push_pull_output(),
+ pins.gpio9.into_push_pull_output(),
+ pins.gpio10.into_push_pull_output(),
+ pins.gpio11.into_push_pull_output(),
+ channel_a,
+ channel_b,
+ );
+ motor_controller.set_duty(20, 20);
+ info!("motor_controller created");
+
// This is the correct pin on the Raspberry Pico board. On other boards, even if they have an
// on-board LED, it might need to be changed.
// Notably, on the Pico W, the LED is not connected to any of the RP2040 GPIOs but to the cyw43 module instead. If you have
@@ -62,11 +92,13 @@ fn main() -> ! {
loop {
info!("on!");
+ motor_controller.forward();
led_pin.set_high().unwrap();
- delay.delay_ms(500);
+ delay.delay_ms(1000);
info!("off!");
+ motor_controller.stop();
led_pin.set_low().unwrap();
- delay.delay_ms(500);
+ delay.delay_ms(1000);
}
}