Pololu 3Pi/Zumo Robot Build System Documentation
This document provides brief documentation for building and running the Pololu 3Pi+ 2040 robot firmware with multiple robot support and different firmware tasks. It covers the ./run build script usage, feature flag system, and multi-robot configuration workflow.
Setup
Hardware Preparation
- Connect the Pololu using a USB-C cable and the debug probe as described here.
- Uncomment the following line in
config.tomlrunner = "probe-rs run --chip RP2040 --protocol swd"
Make Executable Runscript
#make executable (first time only)
chmod +x run
Complete ./run Script Reference
It is recommended to use the ./run script, but you can use the equivalent cargo commands if preferred
Script Syntax
./run [robot_type] [target]
Parameters:
- robot_type (optional): zumo, 3pi, or empty for default
- target (optional): teleop, trajectory, build, or empty for main binary
All Available Commands
| Command | Robot Config | Binary | Description |
|---|---|---|---|
./run |
Default | Main | Default joystick_control.rs, main binary |
./run zumo |
Zumo | Main | Zumo-specific config, main binary |
./run 3pi |
3Pi | Main | 3Pi-specific config, main binary |
./run zumo menu |
Zumo | programm_entrance | Zumo config, menu binary |
./run 3pi menu |
3Pi | programm_entrance | 3Pi config, menu binary |
./run zumo teleop |
Zumo | teleop_control | Zumo config, teleop binary |
./run 3pi teleop |
3Pi | teleop_control | 3Pi config, teleop binary |
./run zumo trajectory_following |
Zumo | trajectory_following | Zumo config, trajectory binary |
./run 3pi trajectory_following |
3Pi | trajectory_following | 3Pi config, trajectory binary |
./run zumo build |
Zumo | - | Build only (no flash) |
./run 3pi build |
3Pi | - | Build only (no flash) |
Equivalent Cargo Commands
./run Command |
Equivalent Cargo Command |
|---|---|
./run |
cargo run --release |
./run zumo |
cargo run --release --features zumo |
./run 3pi |
cargo run --release --features 3pi |
./run 3pi menu |
cargo run --release --bin programm_entrance --features 3pi |
./run zumo teleop |
cargo run --release --bin teleop_control --features zumo |
./run 3pi trajectory_following |
cargo run --release --bin trajectory_following --features 3pi |
./run zumo build |
cargo build --release --features zumo |
Technical Implementation
The build system uses Rust's conditional compilation with feature flags to select robot-specific modules at compile time.
Feature Flag System
- Feature Selection: Robot type determined by
--features zumoor--features 3pi - Module Selection:
lib.rsconditionally compiles the appropriate joystick control module - Re-export: Selected module is re-exported as
joystick_controlfor transparent usage - Compilation: Main code imports from
joystick_controlwithout knowing the underlying implementation
Code Structure
lib.rs Conditional Compilation
// Default joystick control (for testing)
#[cfg(not(any(feature = "zumo", feature = "3pi")))]
pub mod joystick_control;
// Robot-specific modules
#[cfg(feature = "zumo")]
pub mod joystick_control_zumo;
#[cfg(feature = "zumo")]
pub use joystick_control_zumo as joystick_control;
#[cfg(feature = "3pi")]
pub mod joystick_control_3pi;
#[cfg(feature = "3pi")]
pub use joystick_control_3pi as joystick_control;
Cargo.toml Feature Definition
[features]
default = [] # No default robot (uses joystick_control.rs)
zumo = [] # Empty feature flag for Zumo
3pi = [] # Empty feature flag for 3Pi
Key Differences Between Robot Modules
| Aspect | Zumo | 3Pi | Default |
|---|---|---|---|
| Module File | joystick_control_zumo.rs |
joystick_control_3pi.rs |
joystick_control.rs |
| Motor Control | motor.set_speed(-duty_left, -duty_right) |
motor.set_speed(duty_left, duty_right) |
Zumo parameters |
| Encoder CPR | 909.72 | 358.32 | 909.72 |
| Physical Constants | Zumo values | 3Pi values | Zumo values |
Development Workflows
Adding a New Robot Configuration
- Create new joystick control module (e.g.,
joystick_control_newrobot.rs) - Add feature flag in
Cargo.toml:
[features]
newrobot = []
- Update
lib.rs:
#[cfg(feature = "newrobot")]
pub mod joystick_control_newrobot;
#[cfg(feature = "newrobot")]
pub use joystick_control_newrobot as joystick_control;
- Update
./runscript validation logic
Testing Different Configurations
# Verify all configurations compile
cargo check # Default
cargo check --features zumo # Zumo
cargo check --features 3pi # 3Pi
# Build without flashing
./run zumo build
./run 3pi build
Troubleshooting
Common Issues & Solutions
Script not executable:
chmod +x run
Invalid robot type error:
Error: Invalid robot type 'typo'. Use 'zumo', '3pi', or leave empty for default
Solution: Check spelling and use exactly zumo or 3pi
Invalid target error:
Error: Invalid target 'typo'. Use 'teleop', 'trajectory', 'build', or leave empty for main binary
Solution: Use valid targets: teleop, trajectory, build, or leave empty
Feature compilation errors:
# Test individual configurations
cargo check # Default config
cargo check --features zumo # Zumo config
cargo check --features 3pi # 3Pi config
Script execution issues:
# Make sure you're in the project root
ls -la | grep run # Should show the run script
# Check script permissions
ls -la run # Should show executable permissions (x)
Verification Commands
# Build verification (without flashing)
./run zumo build # Should compile Zumo config
./run 3pi build # Should compile 3Pi config
./run build # Invalid - will show error
# Feature flag verification
cargo build --release --features zumo
cargo build --release --features 3pi
cargo build --release # Default config
Version Conflict
The newest version 1.89.0 of rustc is released on 4th Aug 2025. However, the flashing with elf2uf2-rs -d might suffer some temporary issues. For example, an error unregonized ABI occurs because of the generated elf header doesn't match the requirements of the elf2uf2 runner. (The generated 8th bit of the header is 03, which indicates that the OS/ABI type is UNIX - GNU, but actually should be 00, which indicates UNIX - System V). There are 2 ways to solve this issue:
-
If you really need the newest rustc, then each time after you build the project you should enter you target folder and do:
printf '\x00' | dd of=teleop_control bs=1 seek=7 count=1 conv=notruncThis will change the 8th bit from
03to00and then you can flash this as usual (don't build it again). -
The other way is to downgrade rustc to
1.87.0by using:rustup toolchain install 1.87.0 rustup default 1.87.0 rustup component add rust-src --toolchain 1.87.0 rustup target add thumbv6m-none-eabi --toolchain 1.87.0
Notes
- Release Mode: The
./runscript always builds in--releasemode for optimized embedded code - Backward Compatibility: Default configuration maintains compatibility with existing code
- Module Interface: All robot configurations expose the same public interface for seamless switching
- Testing: Use default configuration (
./run) for rapid development and testing - Production: Use specific robot features (
./run zumoor./run 3pi) for deployment