| Crates.io | ev3-drivebase |
| lib.rs | ev3-drivebase |
| version | 0.1.2 |
| created_at | 2025-12-12 15:01:17.099229+00 |
| updated_at | 2025-12-16 17:02:03.221335+00 |
| description | A DriveBase for the EV3 |
| homepage | |
| repository | https://github.com/Kingananas20/ev3dev-drivebase-rs |
| max_upload_size | |
| id | 1981685 |
| size | 62,175 |
A high-level DriveBase abstraction for LEGO Mindstorms EV3 robots running ev3dev, written in Rust.
This crate provides an easy-to-use interface for controlling two-wheeled robots, similar to the DriveBase classes found in the Python and MicroPython ev3dev libraries.
Add this to your Cargo.toml:
[dependencies]
ev3-drivebase = "0.1.0"
use ev3_drivebase::{DriveBase, Motor, Direction, BrakeMode};
use ev3_drivebase::ev3dev_lang_rust::{Ev3Error, motors::MotorPort};
fn main() -> Result<(), Ev3Error> {
// Define motor configuration
let left = Motor::new(MotorPort::OutA, Direction::Clockwise);
let right = Motor::new(MotorPort::OutB, Direction::CounterClockwise);
// Create drivebase with wheel diameter (43.2mm) and axle track (185mm)
let mut drivebase = DriveBase::new(left, right, 43.2, 185.0)?;
// Configure behavior
drivebase
.set_brake_mode(BrakeMode::Hold)?
.set_acceleration(4000)?
.set_deceleration(4000)?;
// Drive 500mm forward at 100 deg/s
drivebase.drive(100, 500, true)?;
// Turn 90 degrees counter-clockwise in place
drivebase.turn(200, 90, None)?;
// Drive backward 300mm
drivebase.drive(100, -300, true)?;
Ok(())
}
When setting up your drivebase, you need to specify which direction each motor should turn to make the robot move forward. This depends on how your motors are physically mounted:
Direction::Clockwise: Use if the motor shaft points toward the front of the robotDirection::CounterClockwise: Use if the motor shaft points toward the back of the robotFor a typical two-wheeled robot with motors on opposite sides, one motor will be Clockwise and the other CounterClockwise.
The drivebase requires two measurements:
These values are critical for accurate distance and turning calculations.
All measurements and parameters use the following units:
The brake mode determines how motors behave when stopped:
BrakeMode::Coast: Motors freely coast to a stop with no active braking. Lowest power consumption but least precise.BrakeMode::Brake: Motors actively brake to stop quickly but don't hold position afterward.BrakeMode::Hold: Motors actively hold their position after stopping. Most precise but uses more power.The drive() method moves the robot forward or backward:
// Drive 500mm forward at 200 deg/s and stop
drivebase.drive(200, 500, true)?;
// Drive 300mm backward at 150 deg/s and stop
drivebase.drive(150, -300, true)?;
// Drive forward continuously (don't stop after distance)
drivebase.drive(250, 1000, false)?;
The turn() method provides two types of turns:
In-Place Turns (robot rotates around its center):
// Turn 90 degrees counter-clockwise
drivebase.turn(200, 90, None)?;
// Turn 180 degrees clockwise
drivebase.turn(200, -180, None)?;
Arc Turns (robot follows a circular path):
// Turn 90 degrees with a 200mm radius
drivebase.turn(200, 90, Some(200.0))?;
// Sharp 45-degree turn with 50mm radius
drivebase.turn(150, 45, Some(50.0))?;
Set how quickly the robot speeds up and slows down:
// Smooth acceleration for delicate tasks
drivebase.set_acceleration(2000)?;
drivebase.set_deceleration(2000)?;
// Quick response for fast movements
drivebase.set_acceleration(5000)?;
drivebase.set_deceleration(5000)?;
Recommendations:
Add color sensors for line following:
use ev3_drivebase::ev3dev_lang_rust::sensors::{ColorSensor, SensorPort};
let mut drivebase = DriveBase::new(left, right, 43.2, 185.0)?;
let left_sensor = ColorSensor::get(SensorPort::In1)?;
let right_sensor = ColorSensor::get(SensorPort::In2)?;
drivebase.add_colorsensor(left_sensor, right_sensor);
// Access sensors through drivebase.left_sensor and drivebase.right_sensor
Monitor the state of your robot:
// Check if motors are running
if drivebase.is_running()? {
println!("Motors are active");
}
// Check if motors are accelerating
if drivebase.is_ramping()? {
println!("Motors are ramping up");
}
// Check if motors are holding position
if drivebase.is_holding()? {
println!("Motors are holding");
}
// Check for problems
if drivebase.is_stalled()? {
println!("Warning: Motors stalled!");
drivebase.stop()?;
}
if drivebase.is_overloaded()? {
println!("Warning: Motors overloaded!");
drivebase.stop()?;
}
Stop the robot at any time:
drivebase.stop()?; // Stops according to brake mode
Reset all motor parameters:
drivebase.reset()?; // Resets and stops motors
To compile your program for the EV3, you'll need to cross-compile for the ARMv5TE architecture:
rustup target add armv5te-unknown-linux-musleabi
# On Ubuntu/Debian
sudo apt-get install gcc-arm-linux-gnueabi
# Or use rust-lld (recommended, no external dependencies)
.cargo/config.toml in your project):[build]
target = "armv5te-unknown-linux-musleabi"
[target.armv5te-unknown-linux-musleabi]
linker = "rust-lld"
cargo build --release --target armv5te-unknown-linux-musleabi
Your binary will be in target/armv5te-unknown-linux-musleabi/release/.
Transfer the binary to your EV3 and run it:
# Using scp
scp target/armv5te-unknown-linux-musleabi/release/my-robot robot@ev3dev.local:~/
# SSH into the EV3
ssh robot@ev3dev.local
# Make executable and run
chmod +x my-robot
./my-robot
For faster development, consider using ev3-runner to automatically upload and run your programs:
cargo install ev3-runner
# On your EV3, start the server
ev3-runner server
# From your computer
ev3-runner client run ./target/armv5te-unknown-linux-musleabi/release/my-robot --host 192.168.x.x:6767
use ev3_drivebase::{DriveBase, Motor, Direction, BrakeMode};
use ev3_drivebase::ev3dev_lang_rust::{Ev3Error, motors::MotorPort};
fn main() -> Result<(), Ev3Error> {
let left = Motor::new(MotorPort::OutA, Direction::Clockwise);
let right = Motor::new(MotorPort::OutB, Direction::CounterClockwise);
let mut drivebase = DriveBase::new(left, right, 43.2, 185.0)?;
drivebase.set_brake_mode(BrakeMode::Hold)?;
// Drive in a square
for _ in 0..4 {
drivebase.drive(300, 500, true)?; // 50cm forward
drivebase.turn(200, 90, None)?; // 90° turn
}
Ok(())
}
use ev3_drivebase::{DriveBase, Motor, Direction, BrakeMode};
use ev3_drivebase::ev3dev_lang_rust::{Ev3Error, motors::MotorPort};
fn main() -> Result<(), Ev3Error> {
let left = Motor::new(MotorPort::OutD, Direction::Clockwise);
let right = Motor::new(MotorPort::OutC, Direction::CounterClockwise);
let mut drivebase = DriveBase::new(left, right, 43.2, 185.0)?;
drivebase
.set_brake_mode(BrakeMode::Hold)?
.set_acceleration(3000)?;
// Simple avoidance: back up and turn
drivebase.drive(200, -150, true)?; // Back up 15cm
drivebase.turn(250, 45, None)?; // Turn 45° right
drivebase.drive(300, 300, true)?; // Move forward 30cm
Ok(())
}
use ev3_drivebase::{DriveBase, Motor, Direction, BrakeMode};
use ev3_drivebase::ev3dev_lang_rust::{Ev3Error, motors::MotorPort};
fn main() -> Result<(), Ev3Error> {
let left = Motor::new(MotorPort::OutA, Direction::Clockwise);
let right = Motor::new(MotorPort::OutB, Direction::CounterClockwise);
let mut drivebase = DriveBase::new(left, right, 43.2, 185.0)?;
drivebase
.set_brake_mode(BrakeMode::Brake)?
.set_acceleration(2000)?
.set_deceleration(2000)?;
// Drive in a smooth S-curve
drivebase.turn(300, 90, Some(300.0))?; // Gentle left curve
drivebase.turn(300, -90, Some(300.0))?; // Gentle right curve
Ok(())
}
For detailed API documentation, run:
cargo doc --open
Contributions are welcome! Please feel free to submit a Pull Request.
This project is licensed under the MIT License - see the LICENSE file for details.
This crate is inspired by the DriveBase implementations in:
If you encounter any issues or have questions: