Skip to content

Commit 064b64c

Browse files
committed
Stepper library uses a polymorph instantiation now
1 parent 74c486a commit 064b64c

10 files changed

Lines changed: 256 additions & 205 deletions

File tree

docs/api/LiquidCrystal.md

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -55,7 +55,7 @@ The LCD interface mode can be changed at run time by calling the
5555

5656
## Example
5757

58-
Output some Text and count the time since the last reset. Mind the
58+
Output some Text and count the time since the last reset. Notice the
5959
slightly different position of the opening parenthesis at the "class
6060
constructor" function LiquidCrystal compared to the C++ instatiation.
6161

@@ -103,7 +103,8 @@ void loop() {
103103

104104
## Possible improvements
105105

106-
This is not a to-do-list, just a collection of random thoughts.
106+
This is not a to-do-list, just brainstorming and a collection of random
107+
thoughts.
107108

108109
### Direct port access
109110
As long as the pin numberings are known at compile time it would be possible

docs/api/Stepper.md

Lines changed: 96 additions & 51 deletions
Original file line numberDiff line numberDiff line change
@@ -1,62 +1,83 @@
11
# Stepper Library
22

3-
For driving stepper motors with 2, 4 or 5 phases.
3+
A Library for driving stepper motors with 2, 4 or 5 phases.
44
Derived from the Arduino Stepper library v1.8.0.
55

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

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

15-
## API table
1620

1721
Arduino method | sduino function
1822
-------------- | ---------------
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+
```
2647

2748

2849

2950
## Example
3051

52+
Notice the slightly different position of the opening parenthesis at the
53+
"class constructor" 'function' Stepper compared to the C++ instantiation.
3154
(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+
3456

3557
C-Version for use with sduino:
3658

3759
```c
3860
#include <Arduino.h>
3961
#include <Stepper.h>
4062

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
4365

44-
Stepper myStepper;
66+
// initialize the stepper library on pins 8 through 11:
67+
Stepper (myStepper,stepsPerRevolution, 8, 9, 10, 11);
4568

4669
void setup() {
47-
// initialize the stepper library on pins 8 through 11:
48-
myStepper = Stepper_4phase(stepsPerRevolution, 8, 9, 10, 11);
4970
// set the speed at 60 rpm:
50-
Stepper_setSpeed(myStepper, 60);
71+
myStepper_setSpeed(60);
5172
}
5273

5374
void loop() {
5475
// step one revolution in one direction:
55-
Stepper_step(myStepper, stepsPerRevolution);
76+
myStepper_step(stepsPerRevolution);
5677
delay(500);
5778

5879
// step one revolution in the other direction:
59-
Stepper_step(myStepper, -stepsPerRevolution);
80+
myStepper_step(-stepsPerRevolution);
6081
delay(500);
6182
}
6283
```
@@ -89,40 +110,64 @@ void loop() {
89110
```
90111

91112

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
93125

126+
Stepper (myStepper, numOfSteps, MotorPin1, MotorPin2);
94127
```
95-
#include <Stepper.h>
96128
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:
98133
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+
}
101145
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+
}
110152
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+
```
114154

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).
117160

118-
// mover method:
119-
void Stepper_step(Stepper this, int number_of_steps);
120161

121-
// replace the version() method with a simple define
122-
#define Stepper_version() 5
123162

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+
127172

128173
[Back to the main page](../index.html)

docs/index.md

Lines changed: 7 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -42,6 +42,10 @@ with github pages and the preinstalled jekyll-themes?)
4242

4343
1. [Introduction and Overview](index.html)
4444
2. [API descriptions and migration guidelines](api.html)
45+
* [Standard Arduino functions]()
46+
* [HardwareSerial]()
47+
* [SPI]()
48+
* [I2C]()
4549
* [LiquidCrystal character LCD library](api/LiquidCrystal.html)
4650
* [PCD8544 libray for Nokia 5110-like graphical LCDs](api/PCD8544.html)
4751
* [Mini_SSD1306 library for monochrome OLED-displays](api/Mini_SSD1306.html)
@@ -54,7 +58,7 @@ with github pages and the preinstalled jekyll-themes?)
5458
4. [Ways to define a pin mapping](pin_mapping.html)
5559
5. [Installing and using the SDCC compiler](sdcc.html)
5660
6. [Using the SPL with SDCC and sduino](spl.html)
57-
7. [c preprocessor macro magic](macro.html).
61+
7. [C preprocessor macro magic](macro.html)
5862

5963

6064

@@ -281,10 +285,12 @@ structure is easier to understand.
281285

282286
The current state of the port does not include the deadlock protection,
283287
though.
288+
[API description](api/I2C.html)
284289

285290

286291
#### HardwareSerial
287292
The standard serial interface.
293+
[API description](api/HardwareSerial.html)
288294

289295

290296

sduino/hardware/sduino/stm8/cores/sduino/xmacro.h

Lines changed: 23 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -155,29 +155,41 @@
155155
#define XInstanciation(type,instance) \
156156
type instance
157157
// constructor with one argument
158-
#define XConstructor1(class,instance,name,atype,arg) inline \
159-
void instance##_##name(atype arg)\
160-
{instance=class##_##name(arg);}
161-
#define XConstructor2(class,instance,name,atype1,arg1,atype2,arg2) inline \
158+
#define XConstructor1(class,instance,name,atype1) inline \
159+
void instance##_##name(atype1 arg1)\
160+
{class##_##name(&instance,arg1);}
161+
#define XConstructor2(class,instance,name,atype1,atype2) inline \
162+
void instance##_##name(atype1 arg1,atype2 arg2)\
163+
{class##_##name(&instance,arg1,arg2);}
164+
#define XConstructor3(class,instance,name,atype1,atype2,atype3) inline \
165+
void instance##_##name(atype1 arg1,atype2 arg2,atype3 arg3)\
166+
{class##_##name(&instance,arg1,arg2,arg3);}
167+
/* old system wher instance was a pointer
168+
// constructor with one argument
169+
#define XConstructor1(class,instance,name,atype1) inline \
170+
void instance##_##name(atype1 arg1)\
171+
{instance=class##_##name(arg1);}
172+
#define XConstructor2(class,instance,name,atype1,atype2) inline \
162173
void instance##_##name(atype1 arg1,atype2 arg2)\
163174
{instance=class##_##name(arg1,arg2);}
164-
#define XConstructor3(class,instance,name,atype1,arg1,atype2,arg2,atype3,arg3) inline \
175+
#define XConstructor3(class,instance,name,atype1,atype2,atype3) inline \
165176
void instance##_##name(atype1 arg1,atype2 arg2,atype3 arg3)\
166177
{instance=class##_##name(arg1,arg2,arg3);}
178+
*/
167179
// simple method without arguments
168180
#define XMethod0(class,instance,name) inline \
169181
void instance##_##name()\
170-
{class##_##name(instance);}
182+
{class##_##name(&instance);}
171183
#define XMethod0return(class,instance,type,name) inline \
172184
type instance##_##name()\
173-
{return class##_##name(instance);}
185+
{return class##_##name(&instance);}
174186
// method with one argument
175-
#define XMethod1(class,instance,name,atype1,arg1) inline \
187+
#define XMethod1(class,instance,name,atype1) inline \
176188
void instance##_##name(atype1 arg1)\
177-
{class##_##name(instance,arg1);}
178-
#define XMethod1return(class,instance,type,name,atype1,arg1) inline \
189+
{class##_##name(&instance,arg1);}
190+
#define XMethod1return(class,instance,type,name,atype1) inline \
179191
type instance##_##name(atype1 arg1)\
180-
{return class##_##name(instance,arg1);}
192+
{return class##_##name(&instance,arg1);}
181193

182194

183195
#endif

sduino/hardware/sduino/stm8/libraries/Mini_SSD1306/examples/oled-mini/oled-mini.c

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -44,7 +44,7 @@ All text above, and the splash screen must be included in any redistribution
4444

4545

4646
// I2C is included here to let the build system automatically be aware of this
47-
// second-level dependency. Ofterwise you would need to list it in the Makefile:
47+
// second-level dependency. Otherwise you would need to list it in the Makefile:
4848
// ARDUINO_LIBS = I2C
4949
#include "I2C.h"
5050
#include "Mini_SSD1306.h"

sduino/hardware/sduino/stm8/libraries/Stepper/examples/stepper_oneRevolution/stepper_oneRevolution.c

Lines changed: 4 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -21,14 +21,13 @@
2121
#include <Serial.h>
2222
#include <Stepper.h>
2323

24-
const int stepsPerRevolution = 200; // change this to fit the number of steps per revolution
25-
// for your motor
24+
// change this to fit the number of steps per revolution for your motor
25+
#define stepsPerRevolution 200
2626

27-
Stepper(myStepper);
27+
// initialize the stepper library on pins 8 through 11:
28+
Stepper (myStepper,stepsPerRevolution, 8, 9, 10, 11);
2829

2930
void setup() {
30-
// initialize the stepper library on pins 8 through 11:
31-
myStepper_4phase(stepsPerRevolution, 8, 9, 10, 11);
3231
// set the speed at 60 rpm:
3332
myStepper_setSpeed(60);
3433
// initialize the serial port:

sduino/hardware/sduino/stm8/libraries/Stepper/examples/stepper_oneStepAtATime/stepper_oneStepAtATime.c

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -24,16 +24,15 @@
2424
#include <Serial.h>
2525
#include <Stepper.h>
2626

27-
const int stepsPerRevolution = 200; // change this to fit the number of steps per revolution
27+
#define stepsPerRevolution 200 // change this to fit the number of steps per revolution
2828
// for your motor
2929

30-
Stepper(myStepper);
30+
// initialize the stepper library on pins 8 through 11:
31+
Stepper (myStepper,stepsPerRevolution, 8, 9, 10, 11);
3132

3233
int stepCount = 0; // number of steps the motor has taken
3334

3435
void setup() {
35-
// initialize the stepper library on pins 8 through 11:
36-
myStepper_4phase(stepsPerRevolution, 8, 9, 10, 11);
3736
// initialize the serial port:
3837
Serial_begin(9600);
3938
}
@@ -46,3 +45,4 @@ void loop() {
4645
stepCount++;
4746
delay(500);
4847
}
48+

sduino/hardware/sduino/stm8/libraries/Stepper/examples/stepper_speedControl/stepper_speedControl.c

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -22,17 +22,17 @@
2222
#include <Arduino.h>
2323
#include <Stepper.h>
2424

25-
const int stepsPerRevolution = 200; // change this to fit the number of steps per revolution
25+
#define stepsPerRevolution 200 // change this to fit the number of steps per revolution
2626
// for your motor
2727

2828

29-
Stepper(myStepper);
29+
// initialize the stepper library on pins 8 through 11:
30+
Stepper (myStepper,stepsPerRevolution, 8, 9, 10, 11);
3031

3132
int stepCount = 0; // number of steps the motor has taken
3233

3334
void setup() {
34-
// initialize the stepper library on pins 8 through 11:
35-
myStepper_4phase(stepsPerRevolution, 8, 9, 10, 11);
35+
// nothing to do inside the setup
3636
}
3737

3838
void loop() {

0 commit comments

Comments
 (0)