|
1 | 1 | # Stepper Library |
2 | 2 |
|
3 | | -For driving stepper motors with 2, 4 or 5 phases. |
| 3 | +A Library for driving stepper motors with 2, 4 or 5 phases. |
4 | 4 | Derived from the Arduino Stepper library v1.8.0. |
5 | 5 |
|
6 | | -This library has a slightly diffent user interface than the usual singleton |
7 | | -libraries. This allows for handling more than one stepper per Sketch but it |
8 | | -requires some more attention when porting an existing sketch from C++ to C. |
9 | 6 |
|
10 | | -Each Stepper instance is represented by a file-descriptor-like structure. |
11 | | -This structure is initialized by a constructor-like function returning a |
12 | | -pointer to this stucture. This pointer needs to be given as the first |
13 | | -argument for ever other function call to identify the stepper instance. |
| 7 | +## API |
| 8 | + |
| 9 | +This library is a multi-instance library, it supports an arbitrary number of |
| 10 | +stepper motors per sketch. |
| 11 | + |
| 12 | +The API syntax is very similar to the original C++ syntax, thanks to some |
| 13 | +[c preprocessor macro magic](macro.html). |
| 14 | + |
| 15 | +The declaration supports polymorphism, so all that is needed to adopt an |
| 16 | +existing sketch for use with sduino is moving the opening bracket at |
| 17 | +the class declarator line and replacing the dots in the method names for |
| 18 | +underscores. |
14 | 19 |
|
15 | | -## API table |
16 | 20 |
|
17 | 21 | Arduino method | sduino function |
18 | 22 | -------------- | --------------- |
19 | | - | Stepper myStepper; // global variable |
20 | | -Stepper myStepper(steps, pin1,pin2); | myStepper = Stepper_2phase(steps, pin1,pin2); |
21 | | -Stepper myStepper(steps, pin1,pin2,pin3,pin4); | myStepper = Stepper_4phase(steps,pin1,pin2,pin3,pin4); |
22 | | -Stepper myStepper(steps, pin1,pin2,pin3,pin4,pin5);| myStepper = Stepper_5phase(steps,pin1,pin2,pin3,pin4,pin5); |
23 | | -myStepper.setSpeed(speed); | Stepper_setSpeed(myStepper, speed); |
24 | | -myStepper.step(n); | Stepper_step(myStepper, n); |
25 | | -myStepper.version(); | Stepper_version(); |
| 23 | +`Stepper myStepper(steps, pin1,pin2);` | `Stepper (myStepper,steps,pin1,pin2);` |
| 24 | +`Stepper myStepper(steps, pin1,pin2,pin3,pin4);`| `Stepper (myStepper,steps,pin1,pin2,pin3,pin4);` |
| 25 | +`Stepper myStepper(steps, pin1,pin2,pin3,pin4,pin5);`| `Stepper (myStepper,steps,pin1,pin2,pin3,pin4,pin5);` |
| 26 | +`myStepper.setSpeed(speed);` | `myStepper_setSpeed(speed);` |
| 27 | +`myStepper.step(n);` | `myStepper_step(n);` |
| 28 | +`myStepper.version();` | `myStepper_version();` |
| 29 | + |
| 30 | + |
| 31 | +There is no explicit constructor method. The output mode is set |
| 32 | +automatically right before the very first motor step. |
| 33 | + |
| 34 | +This means that the driver pins stay uninitialized (in input mode) and are |
| 35 | +left floating until the first step is requested. This won't be a problem in |
| 36 | +most cases as most motor drivers are using pull-up or pull-down resistors to |
| 37 | +ensure definite signal levels. |
| 38 | + |
| 39 | +If needed, the application could call the (internal) `stepMotor(0)` method |
| 40 | +in the setup() function to force an immediate port pin initialization: |
| 41 | + |
| 42 | +```c |
| 43 | +setup() { |
| 44 | + myStepper_stepMotor(0); // sets the motor pins to output mode |
| 45 | +} |
| 46 | +``` |
26 | 47 |
|
27 | 48 |
|
28 | 49 |
|
29 | 50 | ## Example |
30 | 51 |
|
| 52 | +Notice the slightly different position of the opening parenthesis at the |
| 53 | +"class constructor" 'function' Stepper compared to the C++ instantiation. |
31 | 54 | (available in the examples folder as `stepper_oneRevolution.c`) |
32 | | -Notice the Variable `myStepper` of type `Stepper` that is intialized by a |
33 | | -constructor-like function `Stepper_4phase`: |
| 55 | + |
34 | 56 |
|
35 | 57 | C-Version for use with sduino: |
36 | 58 |
|
37 | 59 | ```c |
38 | 60 | #include <Arduino.h> |
39 | 61 | #include <Stepper.h> |
40 | 62 |
|
41 | | -const int stepsPerRevolution = 200; // change this to fit the number of steps p |
42 | | -// for your motor |
| 63 | +// change this to fit the number of steps per revolution for your motor |
| 64 | +#define stepsPerRevolution 200 |
43 | 65 |
|
44 | | -Stepper myStepper; |
| 66 | +// initialize the stepper library on pins 8 through 11: |
| 67 | +Stepper (myStepper,stepsPerRevolution, 8, 9, 10, 11); |
45 | 68 |
|
46 | 69 | void setup() { |
47 | | - // initialize the stepper library on pins 8 through 11: |
48 | | - myStepper = Stepper_4phase(stepsPerRevolution, 8, 9, 10, 11); |
49 | 70 | // set the speed at 60 rpm: |
50 | | - Stepper_setSpeed(myStepper, 60); |
| 71 | + myStepper_setSpeed(60); |
51 | 72 | } |
52 | 73 |
|
53 | 74 | void loop() { |
54 | 75 | // step one revolution in one direction: |
55 | | - Stepper_step(myStepper, stepsPerRevolution); |
| 76 | + myStepper_step(stepsPerRevolution); |
56 | 77 | delay(500); |
57 | 78 |
|
58 | 79 | // step one revolution in the other direction: |
59 | | - Stepper_step(myStepper, -stepsPerRevolution); |
| 80 | + myStepper_step(-stepsPerRevolution); |
60 | 81 | delay(500); |
61 | 82 | } |
62 | 83 | ``` |
@@ -89,40 +110,64 @@ void loop() { |
89 | 110 | ``` |
90 | 111 |
|
91 | 112 |
|
92 | | -## API |
| 113 | +## Implementation details |
| 114 | + |
| 115 | +Technically, each Stepper instance is represented by a file-descriptor-like |
| 116 | +structure. This structure is initialized by the instantiation macro |
| 117 | +`Stepper`. This means that all values are required to be constant values, |
| 118 | +known at compile time. A `const` qualifier is not enough for SDCC, it |
| 119 | +requires either a `#define` or an `enum`: |
| 120 | + |
| 121 | +```c |
| 122 | +const int numOfSteps = 1; // does not work with SDCC |
| 123 | +#define MotorPin1 10 // ok, works |
| 124 | +enum { MotorPin2 = 11 }; // ok, works |
93 | 125 |
|
| 126 | +Stepper (myStepper, numOfSteps, MotorPin1, MotorPin2); |
94 | 127 | ``` |
95 | | -#include <Stepper.h> |
96 | 128 |
|
97 | | -// plain C interface for use with SDCC |
| 129 | +If you really need to (re-) configure the pin connections at run time you could |
| 130 | +initialize a data structure with `0` for the unknown pin numbers and set them |
| 131 | +later by directy accessing the structure before the first use of that |
| 132 | +instance: |
98 | 133 |
|
99 | | -// use a pointer to struct Stepper_s as a class instance aquivalent |
100 | | -typedef struct Stepper_s *Stepper; |
| 134 | +```c |
| 135 | +Stepper (myStepper,0,0); |
| 136 | +
|
| 137 | +setup() { |
| 138 | + ... do some calculations for the pin numbers ... |
| 139 | + myStepper.motor_pin_1 = pin[0]; |
| 140 | + myStepper.motor_pin_2 = pin[1]; |
| 141 | + myStepper.motor_pin_3 = pin[2]; |
| 142 | + myStepper.motor_pin_4 = pin[3]; |
| 143 | + ... |
| 144 | +} |
101 | 145 |
|
102 | | -// "constructor" function |
103 | | -Stepper Stepper_5phase( |
104 | | - unsigned int number_of_steps, |
105 | | - unsigned char motor_pin_1, |
106 | | - unsigned char motor_pin_2, |
107 | | - unsigned char motor_pin_3, |
108 | | - unsigned char motor_pin_4, |
109 | | - unsigned char motor_pin_5); |
| 146 | +loop () { |
| 147 | + ... |
| 148 | + myStepper_setSpeed(60); |
| 149 | + myStepper_step(100); |
| 150 | + ... |
| 151 | +} |
110 | 152 |
|
111 | | -// use #defines to emulate the polymorph class constructor in C++ |
112 | | -#define Stepper_2phase(N,A,B) Stepper_5phase((N),(A),(B),0,0,0) |
113 | | -#define Stepper_4phase(N,A,B,C,D) Stepper_5phase((N),(A),(B),(C),(D),0) |
| 153 | +``` |
114 | 154 |
|
115 | | -// speed setter method: |
116 | | -void Stepper_setSpeed(Stepper this, long whatSpeed); |
| 155 | +All functions require a pointer to the stepper data structur as their first |
| 156 | +argument to identify the stepper instance. All this pointer handling is |
| 157 | +hidden by preprocessor magic, but it is still real and pure C. If you |
| 158 | +insist, you can still call the 'real' functions yourself (but you gain |
| 159 | +nothing, the compiler produces exactly the same output). |
117 | 160 |
|
118 | | -// mover method: |
119 | | -void Stepper_step(Stepper this, int number_of_steps); |
120 | 161 |
|
121 | | -// replace the version() method with a simple define |
122 | | -#define Stepper_version() 5 |
123 | 162 |
|
124 | | -// (not so) private: |
125 | | -void Stepper_stepMotor(Stepper s, int this_step); |
126 | | -``` |
| 163 | + |
| 164 | +## Possible impovements |
| 165 | + |
| 166 | +This is not a to-do-list, just brainstorming and a collection of random |
| 167 | +thoughts. |
| 168 | + |
| 169 | +Nothing yet. |
| 170 | + |
| 171 | + |
127 | 172 |
|
128 | 173 | [Back to the main page](../index.html) |
0 commit comments