use stepper_motion::{
config::units::{Degrees, DegreesPerSec, DegreesPerSecSquared, Microsteps},
motor::StepperMotorBuilder,
motion::MotionProfile,
};
struct MockDelay;
impl embedded_hal::delay::DelayNs for MockDelay {
fn delay_ns(&mut self, ns: u32) {
std::thread::sleep(std::time::Duration::from_nanos(ns as u64));
}
}
struct MockPin {
state: bool,
}
impl MockPin {
fn new() -> Self {
Self { state: false }
}
}
impl embedded_hal::digital::OutputPin for MockPin {
fn set_high(&mut self) -> Result<(), Self::Error> {
self.state = true;
Ok(())
}
fn set_low(&mut self) -> Result<(), Self::Error> {
self.state = false;
Ok(())
}
}
impl embedded_hal::digital::ErrorType for MockPin {
type Error = core::convert::Infallible;
}
fn main() {
println!("=== Basic Motor Control Example ===\n");
let step_pin = MockPin::new();
let dir_pin = MockPin::new();
let delay = MockDelay;
let motor = StepperMotorBuilder::new()
.name("demo_motor")
.step_pin(step_pin)
.dir_pin(dir_pin)
.delay(delay)
.steps_per_revolution(200)
.microsteps(Microsteps::SIXTEENTH)
.gear_ratio(1.0)
.max_velocity(DegreesPerSec(360.0))
.max_acceleration(DegreesPerSecSquared(720.0))
.build()
.expect("Failed to build motor");
println!("Motor created: {}", motor.name());
println!("Initial position: {} steps ({} degrees)",
motor.position_steps().0,
motor.position_degrees().0
);
println!("State: {}", motor.state_name());
println!("\n=== Mechanical Constraints (Unit Conversion) ===");
let constraints = motor.constraints();
println!("Motor configuration:");
println!(" Steps/revolution: {} (base 200 × 16 microsteps)", constraints.steps_per_revolution);
println!(" Steps/degree: {:.4}", constraints.steps_per_degree);
println!(" Max velocity: {:.2}°/s = {:.0} steps/s",
constraints.max_velocity.0,
constraints.max_velocity_steps_per_sec);
println!(" Max acceleration: {:.2}°/s² = {:.0} steps/s²",
constraints.max_acceleration.0,
constraints.max_acceleration_steps_per_sec2);
println!(" Min step interval: {} ns ({:.0} kHz max)",
constraints.min_step_interval_ns,
1_000_000_000.0 / constraints.min_step_interval_ns as f64 / 1000.0);
println!("\nUnit conversions:");
let target_degrees = Degrees(90.0);
let target_steps = (target_degrees.0 * constraints.steps_per_degree) as i64;
println!(" 90° = {} steps", target_steps);
let target_degrees = Degrees(360.0);
let target_steps = (target_degrees.0 * constraints.steps_per_degree) as i64;
println!(" 360° (1 rev) = {} steps", target_steps);
let profile = MotionProfile::asymmetric_trapezoidal(
3200, 3200.0, 6400.0, 3200.0, );
println!("\n=== Motion Profile ===");
println!("Total steps: {}", profile.total_steps);
println!("Direction: {:?}", profile.direction);
println!("Acceleration phase: {} steps", profile.accel_steps);
println!("Cruise phase: {} steps", profile.cruise_steps);
println!("Deceleration phase: {} steps", profile.decel_steps);
println!("Initial interval: {} ns", profile.initial_interval_ns);
println!("Cruise interval: {} ns", profile.cruise_interval_ns);
println!("Estimated duration: {:.3} seconds", profile.estimated_duration_secs());
println!("\n=== Configuration Loading ===");
let toml_content = r#"
[motors.demo]
name = "demo_motor"
steps_per_revolution = 200
microsteps = 16
gear_ratio = 1.0
max_velocity_deg_per_sec = 360.0
max_acceleration_deg_per_sec2 = 720.0
[motors.demo.limits]
min_degrees = -180.0
max_degrees = 180.0
policy = "reject"
[trajectories.home]
motor = "demo"
target_degrees = 0.0
velocity_percent = 50
acceleration_deg_per_sec2 = 500.0
deceleration_deg_per_sec2 = 200.0
[trajectories.quarter_turn]
motor = "demo"
target_degrees = 90.0
velocity_percent = 100
"#;
let config: stepper_motion::SystemConfig = toml::from_str(toml_content)
.expect("Failed to parse config");
println!("Loaded configuration with {} motor(s) and {} trajectory(ies)",
config.motors.len(),
config.trajectories.len()
);
stepper_motion::validate_config(&config).expect("Configuration validation failed");
println!("Configuration validated successfully!");
if let Some(home_traj) = config.trajectory("home") {
println!("\nTrajectory 'home':");
println!(" Target: {} degrees", home_traj.target_degrees.0);
println!(" Velocity: {}% of max", home_traj.velocity_percent);
println!(" Asymmetric: {}", if home_traj.is_asymmetric() { "yes" } else { "no" });
if let Some(accel) = home_traj.acceleration {
println!(" Acceleration: {} deg/s²", accel.0);
}
if let Some(decel) = home_traj.deceleration {
println!(" Deceleration: {} deg/s²", decel.0);
}
}
println!("\n=== Example Complete ===");
println!("In production code, call motor.move_to(Degrees(90.0)) to execute motion.");
}