| Crates.io | mecha10-drivers-motor |
| lib.rs | mecha10-drivers-motor |
| version | 0.1.47 |
| created_at | 2026-01-15 07:27:38.26863+00 |
| updated_at | 2026-01-25 07:05:50.967991+00 |
| description | Motor driver for the Mecha10 robotics framework |
| homepage | |
| repository | https://github.com/mecha10/mecha10 |
| max_upload_size | |
| id | 2044794 |
| size | 172,608 |
Production-ready motor drivers for the Mecha10 robotics framework, supporting the most popular motor types used in robotics.
MotorDriver trait for all motor typesAdd to your Cargo.toml:
[dependencies]
mecha10-drivers-motor = { path = "path/to/mecha10-monorepo/packages/drivers/motor" }
use mecha10_drivers_motor::dynamixel::{DynamixelDriver, DynamixelConfig};
use mecha10_drivers_motor::common::{MotorDriver, MotorCommand, ControlMode};
#[tokio::main]
async fn main() -> Result<(), Box<dyn std::error::Error>> {
// Configure driver
let config = DynamixelConfig {
port: "/dev/ttyUSB0".to_string(),
baud_rate: 1_000_000, // 1 Mbps
motor_ids: vec![1, 2, 3],
control_mode: ControlMode::Position,
update_rate_hz: 100.0,
calibration_file: Some("motor_calibration.json".to_string()),
position_pid: None,
velocity_pid: None,
};
// Initialize driver
let mut driver = DynamixelDriver::new(config);
driver.init().await?;
// Enable motors
driver.enable(1).await?;
// Send position command (90 degrees)
let cmd = MotorCommand {
motor_id: 1,
mode: ControlMode::Position,
target: std::f64::consts::PI / 2.0, // 1.57 rad
velocity_limit: Some(2.0),
torque_limit: Some(1.0),
profile_velocity: None,
profile_acceleration: None,
};
driver.send_command(&cmd).await?;
// Read motor state
let state = driver.read_state(1).await?;
println!("Position: {} rad, Velocity: {} rad/s", state.position, state.velocity);
println!("Temperature: {}°C, Voltage: {}V", state.temperature, state.voltage);
Ok(())
}
use mecha10_drivers_motor::odrive::{ODriveDriver, ODriveConfig};
use mecha10_drivers_motor::common::{MotorDriver, MotorCommand, ControlMode};
#[tokio::main]
async fn main() -> Result<(), Box<dyn std::error::Error>> {
let config = ODriveConfig {
port: "/dev/ttyACM0".to_string(),
baud_rate: 115200,
axes: vec![0, 1], // Dual-axis control
control_mode: ControlMode::Velocity,
update_rate_hz: 100.0,
calibration_file: None,
current_limit: 10.0, // 10A
velocity_limit: 10000.0, // counts/s
};
let mut driver = ODriveDriver::new(config);
driver.init().await?;
// Enable axis
driver.enable(0).await?;
// Send velocity command
let cmd = MotorCommand {
motor_id: 0,
mode: ControlMode::Velocity,
target: 5000.0, // counts/s
velocity_limit: None,
torque_limit: Some(5.0),
profile_velocity: None,
profile_acceleration: None,
};
driver.send_command(&cmd).await?;
Ok(())
}
use mecha10_drivers_motor::stepper::{StepperDriver, StepperConfig, StepperInterface, StepperMotorConfig};
use mecha10_drivers_motor::common::{MotorDriver, MotorCommand, ControlMode};
#[tokio::main]
async fn main() -> Result<(), Box<dyn std::error::Error>> {
let config = StepperConfig {
interface: StepperInterface::GRBL {
port: "/dev/ttyUSB0".to_string(),
baud_rate: 115200,
},
motors: vec![
StepperMotorConfig {
motor_id: 0,
steps_per_rev: 200, // 1.8° stepper
microsteps: 16,
gear_ratio: 1.0,
max_velocity: 1000.0,
max_acceleration: 500.0,
enable_active_high: false,
invert_direction: false,
},
],
update_rate_hz: 100.0,
calibration_file: None,
};
let mut driver = StepperDriver::new(config);
driver.init().await?;
// Send position command
let cmd = MotorCommand {
motor_id: 0,
mode: ControlMode::Position,
target: 3.14, // π radians (180°)
velocity_limit: Some(500.0),
torque_limit: None,
profile_velocity: None,
profile_acceleration: Some(250.0),
};
driver.send_command(&cmd).await?;
Ok(())
}
Computer → USB2Dynamixel/U2D2 → Dynamixel Chain
Wiring:
- Data: TTL (XL series) or RS-485 (XM/XH series)
- Power: 12V (XL) or 12-24V (XM/XH)
- Daisy-chain supported (up to 253 devices)
Configuration:
- Set unique IDs for each servo
- Configure baud rate (57600, 115200, 1M, 3M, 4M)
Computer → USB/UART → ODrive → BLDC Motor + Encoder
Wiring:
Axis 0/1:
- Motor: Phase A, B, C
- Encoder: A, B, Z (quadrature) or Hall U, V, W
- Power: 12-56V DC, up to 120A
Configuration:
- Calibrate motor (motor.config.resistance, motor.config.inductance)
- Calibrate encoder (encoder.config.cpr)
- Tune PID (controller.config.pos_gain, vel_gain)
Computer → GRBL Controller/GPIO → Stepper Driver → Stepper Motor
Wiring (GPIO):
- Step pin
- Direction pin
- Enable pin (optional)
- Motor: typically 4-wire bipolar
Configuration:
- Set microstepping (MS1, MS2, MS3 pins)
- Configure current limit (potentiometer on driver)
MotorCommand {
mode: ControlMode::Position,
target: 1.57, // radians
velocity_limit: Some(2.0), // max speed
torque_limit: Some(1.0), // max torque
..Default::default()
}
MotorCommand {
mode: ControlMode::Velocity,
target: 5.0, // rad/s
torque_limit: Some(1.0),
..Default::default()
}
MotorCommand {
mode: ControlMode::Torque,
target: 0.5, // N⋅m or Amps
..Default::default()
}
Synchronized control of multiple motors:
use mecha10_drivers_motor::common::MultiMotorCommand;
let cmd = MultiMotorCommand {
motor_ids: vec![1, 2, 3],
mode: ControlMode::Position,
targets: vec![0.0, 1.57, 3.14],
timestamp_us: now_micros(),
};
driver.send_multi_command(&cmd).await?;
Save and load motor calibrations:
use mecha10_drivers_motor::common::MotorCalibration;
// Create calibrations
let calibrations = vec![
MotorCalibration {
motor_id: 1,
position_offset: 0.0,
direction: 1,
gear_ratio: 1.0,
encoder_resolution: 4096,
max_velocity: 10.0,
max_torque: 2.0,
},
];
// Save to file
let path = std::path::PathBuf::from("motor_calibration.json");
MotorCalibration::save(&calibrations, &path)?;
// Load from file
let loaded = MotorCalibration::load(&path)?;
All drivers return detailed error information:
match driver.send_command(&cmd).await {
Ok(_) => println!("Command sent successfully"),
Err(e) => {
match e {
Mecha10Error::HardwareError(msg) => {
eprintln!("Hardware error: {}", msg);
}
Mecha10Error::ConnectionError(msg) => {
eprintln!("Connection error: {}", msg);
// Attempt to reconnect
}
_ => eprintln!("Other error: {}", e),
}
}
}
// Read motor errors
let state = driver.read_state(1).await?;
if state.error_flags != 0 {
let errors = MotorError::from_flags(state.error_flags);
for error in errors {
eprintln!("Motor error: {:?}", error);
}
}
| Motor Type | Update Rate | Latency | Communication |
|---|---|---|---|
| Dynamixel | 100-1000 Hz | 1-10ms | Serial (TTL/RS-485) |
| ODrive | 100-500 Hz | 2-20ms | USB/UART |
| Stepper | 1-100 Hz | <1ms | GPIO/GRBL |