# Components A component (`trait SyncComp` in the library) represents a synchronous motor, optionally connected to a mechanical structure that transforms the rotatory movements created by the motor. If a struct implements the `SyncComp` trait, it can be linked into a group with `SyncCompGroup`, later required in the [sybot_lib](https://github.com/SamuelNoesslboeck/sybot_lib). The library does include some standard components commonly used - *Cylinder*, a simple cylinder translating the rotatory movements of a motor to a linear extension - *GearJoint*, a motor connected to a gear that translates the movement with a certain ratio - *Cylinder-triangle*, a cylinder being the hypotenuse in a triangular shape, creating a high torque/slow movement joint In this example we drive a cylinder by a certain amount of millimeters.
Click to show Cargo.toml ```toml # ... [dependencies] # Include the library configured for the raspberry pi stepper_lib = { version = "0.11.6", features = [ "rasp" ] } # ... ```

```rust // Include components and data use stepper_lib::{StepperCtrl, StepperConst, SyncComp, Setup}; use stepper_lib::comp::Cylinder; use stepper_lib::data::LinkedData; // Include the unit system use stepper_lib::units::*; // Pin declerations (BCM on raspberry pi) const PIN_DIR : u8 = 27; const PIN_STEP : u8 = 19; // Define distance and max speed const DELTA : Delta = Delta(10.0); // 10 millimeters const OMEGA : Omega = Omega(20.0); // 20 millimeters per second fn main() -> Result<(), stepper_lib::Error> { // Create the controls for a stepper motor let mut cylinder = Cylinder::new( StepperCtrl::new( StepperConst::MOT_17HE15_1504S, PIN_DIR, PIN_STEP ), 1.273 // Spindle pitch of the cylinder, per radian the cylinder // extends for 1.273 millimeters, this factor calculates out // of the pitch per revolve (8mm) divided by 2*PI (for radians) ); // Link the component to a system cylinder.write_link(LinkedData { u: 12.0, // System voltage in volts s_f: 1.5 // System safety factor, should be at least 1.0 }); cylinder.setup(); // Apply some loads cylinder.apply_inertia(Inertia(0.2)); cylinder.apply_force(Force(0.10)); cylinder.set_omega_max(OMEGA); println!("Staring to move ... "); let delta_real = cylinder.drive_rel(DELTA, 1.0)?; // Move the cylinder println!("Distance {}mm with max speed {:?}mm/s done", delta_real, OMEGA); Ok(()) } ``` (See [the rust example](../examples/cylinder.rs)) ## Custom components If a component is desired that is not included in the standard components, then a custom component can be created. Simply implement the `SyncComp` trait for the component. There are two ways of defining a new component - Defining a super component, which would be the motor to a gear or the cylinder in the `CylinderTriangle`, the only functions that have to be overwritten then are the functions required to communicate with the super component. Though in many cases some kind of ratio is added. - Completely implementing the trait, therefore defining a completely new type of motor. The following example shows a custom component with a stepper motor as super component. Additionally it prints out a message every time write drive a relative distance.
Click to show Cargo.toml ```toml # ... [dependencies] # Include the library configured for the raspberry pi stepper_lib = { version = "0.11.6", features = [ "rasp" ] } # ... ```

```rust // Include library use stepper_lib::prelude::*; // Pin declerations (BCM on raspberry pi) const PIN_DIR : u8 = 27; const PIN_STEP : u8 = 19; // Define distance and max speed const DELTA : Delta = Delta(10.0); const OMEGA : Omega = Omega(10.0); // Defining component structure #[derive(Debug)] struct MyComp { ctrl : StepperCtrl, // The stepper motor built into the component ratio : f32 // The gear ratio, e.g. a spingle or } impl MyComp { pub fn new(ctrl : StepperCtrl, ratio : f32) -> Self { Self { ctrl, ratio } } } impl Setup for MyComp { fn setup(&mut self) -> Result<(), stepper_lib::Error> { self.ctrl.setup()?; // Setting up the super component Ok(()) } } impl SyncComp for MyComp { // Required memebers fn consts<'a>(&'a self) -> &'a StepperConst { todo!() } fn vars<'a>(&'a self) -> &'a stepper_lib::data::CompVars { todo!() // Not required in this example } fn link<'a>(&'a self) -> &'a LinkedData { todo!() // Not required in this example } // // Super component (motor) // The following two overrides give the library access to the stepper motor controller stored in our component fn super_comp(&self) -> Option<&dyn SyncComp> { Some(&self.ctrl) } fn super_comp_mut(&mut self) -> Option<&mut dyn SyncComp> { Some(&mut self.ctrl) } // // Ratio // The following two overrides cause the library to translate the distance by the ratio we defined for our component fn gamma_for_super(&self, this_gamma : Gamma) -> Gamma { this_gamma * self.ratio // Distance is translated by the ratio } fn gamma_for_this(&self, super_gamma : Gamma) -> Gamma { super_gamma / self.ratio } // fn drive_rel(&mut self, delta : Delta, speed_f : f32) -> Result { println!("Now driving!"); // Our custom message let delta_real = self.ctrl.drive_rel( self.delta_for_super(delta, self.gamma()), speed_f )?; Ok(self.delta_for_this(delta_real, self.gamma_for_super(self.gamma()))) } } fn main() -> Result<(), stepper_lib::Error> { // Create the controls for a stepper motor let mut comp = MyComp::new( StepperCtrl::new(StepperConst::MOT_17HE15_1504S, PIN_DIR, PIN_STEP), 2.0 // Example ratio ); // Link the component to a system comp.write_link(LinkedData { u: 12.0, // System voltage in volts s_f: 1.5 // System safety factor, should be at least 1.0 }); comp.setup()?; // Apply some loads comp.apply_inertia(Inertia(0.2)); comp.apply_force(Force(0.10)); // Limit the component velocity comp.set_omega_max(OMEGA); println!("Staring to move ... "); let delta_real = comp.drive_rel(DELTA, 1.0)?; // Move the comp println!("Distance {}rad with max speed {:?}rad/s done", delta_real, OMEGA); Ok(()) } // Console output: // " // Starting to move ... // Now driving! // Distance 10rad with max speed 20rad/s done // " ``` (See [the rust example](../examples/custom_component.rs))