stepper_lib 0.11.2

A simple library to control motors and components
Documentation
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
# stepper_lib


[![Crates.io version](https://img.shields.io/crates/v/stepper_lib.svg?style=flat-square) ](https://crates.io/crates/stepper_lib)
[![stepper_lib: rustc 1.68+]][Rust 1.68]

[stepper_lib: rustc 1.68+]: https://img.shields.io/badge/stepper_lib-rustc_1.68+-lightgray.svg
[Rust 1.68]: https://blog.rust-lang.org/2023/03/09/Rust-1.68.0.html

A library for all types of components used in robots, including controlls for stepper motors, servo motors and more complex assemblies using said motors. Currently all implementations are made for the raspberry pi, though new implementations for more controllers are currently being made.

Basis library for the [sybot_lib]("https://github.com/SamuelNoesslboeck/sybot_lib)

### Goal


- Create an all-in-one library to control motors, read sensors and do basic calculations in rust.

# In Action


Let us assume we want to control a simple stepper motor (in this example a [17HE15_1504_S](https://www.omc-stepperonline.com/index.php?route=product/product/get_file&file=2838/17HE15-1504S.pdf)) with a PWM controller connected to the BCM pins 27 and 19.

<details>
<summary>
Click to show Cargo.toml
</summary>

```toml
# ...


[dependencies]
# Include the library configured for the raspberry pi

stepper_lib = { version = "0.11.0", features = [ "rasp" ] } 

# ...

```
</details>
<p></p>

```rust
use core::f32::consts::PI;

// Include components and data
use stepper_lib::{StepperCtrl, StepperConst, SyncComp};
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(2.0 * PI);
const OMEGA : Omega = Omega(10.0);

fn main() -> Result<(), stepper_lib::Error> {
    // Create the controls for a stepper motor
    let mut ctrl = StepperCtrl::new(
        StepperConst::MOT_17HE15_1504S, 
        PIN_DIR, 
        PIN_STEP
    );
    // Link the component to a system
    ctrl.write_link(LinkedData { 
        u: 12.0,    // System voltage in volts
        s_f: 1.5    // System safety factor, should be at least 1.0
    }); 

    // Apply some loads
    ctrl.apply_inertia(Inertia(0.2));
    ctrl.apply_force(Force(0.10));

    println!("Staring to move");
    let delta_real = ctrl.drive_rel(DELTA, OMEGA)?;      // Move the motor
    println!("Distance {}rad with max speed {:?}rad/s done", 
        delta_real, OMEGA);

    Ok(())
}
```
(Source: "examples/stepper_motor.rs")

# Overview


- [Features]#features
- [Components]#components
- [Tools]#tools
- [Platforms and simulation]#platforms-and-simulation
- [Issues and requests]#issues-and-requests

## Features


- [x] Motors
  - [x] Stepper motors
  - [x] Servo motors
  - [x] DC motors
- [ ] Components
  - [x] Cylinder
  - [x] Gear joint
  - [x] Cylinder-triangle
  - [ ] Conveyor
- [x] Tools
  - [x] Tongs
  - [x] Axial joint
- [x] Calculation
  - [x] Complex acceleration curves
  - [x] Overloads
  - [x] Forces
  - [x] Inertias
- [ ] Measurements
  - [x] Simple switch
  - [ ] Rotary resolver
- [x] Extendable
  - [x] Custom components
  - [x] Custom tools
- [ ] Minimal
  - [ ] Fully supports `no_std` environment
  - [ ] Available for basic embedded systems
- Platforms
  - Raspberry Pi and similar

## 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.

<details>
<summary>Click to show Cargo.toml</summary>

```toml
# ...


[dependencies]
# Include the library configured for the raspberry pi

stepper_lib = { version = "0.11.0", features = [ "rasp" ] } 

# ...

```
</details>
<p></p>

```rust
// Include components and data
use stepper_lib::{StepperCtrl, StepperConst, SyncComp};
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
    }); 

    // Apply some loads
    cylinder.apply_inertia(Inertia(0.2));
    cylinder.apply_force(Force(0.10));

    println!("Staring to move ... ");
    let delta_real = cylinder.drive_rel(DELTA, OMEGA)?;         // Move the cylinder
    println!("Distance {}mm with max speed {:?}mm/s done", 
        delta_real, OMEGA);

    Ok(())
}
```

(Source: "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.

<details>
<summary>
Click to show Cargo.toml
</summary>

```toml
# ...


[dependencies]
# Include the library configured for the raspberry pi

stepper_lib = { version = "0.11.0", features = [ "rasp" ] } 

# ...

```
</details>
<p></p>

```rust
// Include components and data
use stepper_lib::{StepperCtrl, StepperConst, SyncComp};
use stepper_lib::data::LinkedData;
use stepper_lib::meas::SimpleMeas;
// 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);      
const OMEGA : Omega = Omega(20.0);      

// Defining component structure
#[derive(Debug)]

struct MyComp {
    ctrl : StepperCtrl,
    ratio : f32
}

impl MyComp {
    pub fn new(ctrl : StepperCtrl, ratio : f32) -> Self {
        Self { ctrl, ratio }
    }
}

impl SimpleMeas for MyComp {
    fn init_meas(&mut self, _ : u8) {
        todo!()     // Not required in this example
    }
}

impl SyncComp for MyComp {
    // Required memebers
        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
        }

        fn to_json(&self) -> Result<serde_json::Value, serde_json::Error> {
            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, omega : Omega) 
            -> Result<Delta, stepper_lib::Error> {
        println!("Now driving!"); // Our custom message

        let delta_real = self.ctrl.drive_rel(
            self.delta_for_super(delta, self.gamma()), 
            self.omega_for_super(omega, self.gamma())
        )?;

        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
    }); 

    // Apply some loads
    comp.apply_inertia(Inertia(0.2));
    comp.apply_force(Force(0.10));

    println!("Staring to move ... ");
    let delta_real = comp.drive_rel(DELTA, OMEGA)?;         // 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
// "
```

(Source: "examples/custom_component.rs")

## Tools


The library also includes various simple tools like tongs, axial joints and so on. These tools are controlled by a servo controller, though other types of motors can be used in custom tools by implementing the `Tool` trait, just like `SyncComp`.

This example controls a simple pair of tongs using a servo motor.

<details>
<summary>
Click to show Cargo.toml
</summary>

```toml
# ...


[dependencies]
# Include the library configured for the raspberry pi

stepper_lib = { version = "0.11.0", features = [ "rasp" ] } 

# ...

```
</details>

```rust
use core::time::Duration;

use std::thread::sleep;

use stepper_lib::{SimpleTool, Tool};
use stepper_lib::comp::tool::Tongs;
use stepper_lib::ctrl::servo::ServoDriver;
use stepper_lib::data::servo::ServoConst;

// Include the unit system
use stepper_lib::units::*;

// Pin declerations (BCM on raspberry pi)
const PIN_PWM : u8 = 27;

fn main() -> Result<(), stepper_lib::Error> {
    // Create the tongs controller
    let mut tongs = Tongs::new(
        ServoDriver::new(ServoConst::MG996R, PIN_PWM),    // The tongs use a MG996R servo connected to the BCM pin 27   
        0.2,        // when the pwm signal is at 20%, the tongs are open
        0.8,        // when the pwm signal is at 80%, the tongs are closed
        100.0,      // the tongs are 100 millimeters long
        Inertia(0.2)        // the tongs have a weight of 0.2 kg
    );

    tongs.mount();

    tongs.activate();
    sleep(Duration::from_secs(1));
    tongs.deactivate();

    Ok(())
}
```

## Platforms and simulation


The final goal of the library is to work on as many platforms as possible, even on embedded systems. To configure the library for a specific platform, the right features have to be enabled. Note that some of the features automatically enable `std` usage.

The current platforms and features enabled are
- "rasp": Raspberry Pi and similar controllers

```toml
# Platform features

rasp = [ "std", "dep:rppal" ]
```

If no platform is selected the library automatically goes into simulation mode. Meaning no movements will be actually executed, no pins will be written to or checked, which can lead to problems. As the library does for example not care if the same two pins are used in simulation mode.

## Issues and requests


If you encounter any issues or if you have any request for new features, feel free to create an issue at the [GitHub repo](https://github.com/SamuelNoesslboeck/stepper_lib).