Skip to content

Commit 8ddcd69

Browse files
neildavisdeadprogram
authored andcommitted
Add support for '8-step mode' to easystepper
Currently, easystepper driver supports only '4-step mode' (12-23-34-41) when energizing the coils This does not work with all motors & drivers (e.g. 28BJY-48 & ULN2003) This commit adds support for 8-step mode (1-12-2-23-3-34-4-41) Note: this commit breaks backward source compatibility for the factory/constructor functions.
1 parent 1c038f5 commit 8ddcd69

File tree

2 files changed

+143
-23
lines changed

2 files changed

+143
-23
lines changed

easystepper/easystepper.go

+138-22
Original file line numberDiff line numberDiff line change
@@ -2,28 +2,76 @@
22
package easystepper // import "tinygo.org/x/drivers/easystepper"
33

44
import (
5+
"errors"
56
"machine"
67
"time"
78
)
89

10+
// StepMode determines the coil sequence used to perform a single step
11+
type StepMode uint8
12+
13+
// Valid values for StepMode
14+
const (
15+
// ModeFour uses a 'four step' coil sequence (12-23-34-41). This is the default (zero-value) mode
16+
ModeFour StepMode = iota
17+
// ModeEight uses an 'eight step' coil sequence (1-12-2-23-3-34-4-41)
18+
ModeEight
19+
)
20+
21+
// stepCount is a helper function to return the number of steps in a StepMode sequence
22+
func (sm StepMode) stepCount() uint {
23+
switch sm {
24+
default:
25+
fallthrough
26+
case ModeFour:
27+
return 4
28+
case ModeEight:
29+
return 8
30+
}
31+
}
32+
33+
// DeviceConfig contains the configuration data for a single easystepper driver
34+
type DeviceConfig struct {
35+
// Pin1 ... Pin4 determines the pins to configure and use for the device
36+
Pin1, Pin2, Pin3, Pin4 machine.Pin
37+
// StepCount is the number of steps required to perform a full revolution of the stepper motor
38+
StepCount uint
39+
// RPM determines the speed of the stepper motor in 'Revolutions per Minute'
40+
RPM uint
41+
// Mode determines the coil sequence used to perform a single step
42+
Mode StepMode
43+
}
44+
45+
// DualDeviceConfig contains the configuration data for a dual easystepper driver
46+
type DualDeviceConfig struct {
47+
DeviceConfig
48+
// Pin5 ... Pin8 determines the pins to configure and use for the second device
49+
Pin5, Pin6, Pin7, Pin8 machine.Pin
50+
}
51+
952
// Device holds the pins and the delay between steps
1053
type Device struct {
1154
pins [4]machine.Pin
12-
stepDelay int32
55+
stepDelay time.Duration
1356
stepNumber uint8
57+
stepMode StepMode
1458
}
1559

1660
// DualDevice holds information for controlling 2 motors
1761
type DualDevice struct {
18-
devices [2]Device
62+
devices [2]*Device
1963
}
2064

21-
// New returns a new easystepper driver given 4 pins, number of steps and rpm
22-
func New(pin1, pin2, pin3, pin4 machine.Pin, steps int32, rpm int32) Device {
23-
return Device{
24-
pins: [4]machine.Pin{pin1, pin2, pin3, pin4},
25-
stepDelay: 60000000 / (steps * rpm),
65+
// New returns a new single easystepper driver given a DeviceConfig
66+
func New(config DeviceConfig) (*Device, error) {
67+
if config.StepCount == 0 || config.RPM == 0 {
68+
return nil, errors.New("config.StepCount and config.RPM must be > 0")
2669
}
70+
return &Device{
71+
pins: [4]machine.Pin{config.Pin1, config.Pin2, config.Pin3, config.Pin4},
72+
stepDelay: time.Second * 60 / time.Duration((config.StepCount * config.RPM)),
73+
stepMode: config.Mode,
74+
}, nil
2775
}
2876

2977
// Configure configures the pins of the Device
@@ -34,17 +82,23 @@ func (d *Device) Configure() {
3482
}
3583

3684
// NewDual returns a new dual easystepper driver given 8 pins, number of steps and rpm
37-
func NewDual(pin1, pin2, pin3, pin4, pin5, pin6, pin7, pin8 machine.Pin, steps int32, rpm int32) DualDevice {
38-
var dual DualDevice
39-
dual.devices[0] = Device{
40-
pins: [4]machine.Pin{pin1, pin2, pin3, pin4},
41-
stepDelay: 60000000 / (steps * rpm),
85+
func NewDual(config DualDeviceConfig) (*DualDevice, error) {
86+
// Create the first device
87+
dev1, err := New(config.DeviceConfig)
88+
if err != nil {
89+
return nil, err
4290
}
43-
dual.devices[1] = Device{
44-
pins: [4]machine.Pin{pin5, pin6, pin7, pin8},
45-
stepDelay: 60000000 / (steps * rpm),
91+
// Create the second device
92+
config.DeviceConfig.Pin1 = config.Pin5
93+
config.DeviceConfig.Pin2 = config.Pin6
94+
config.DeviceConfig.Pin3 = config.Pin7
95+
config.DeviceConfig.Pin4 = config.Pin8
96+
dev2, err := New(config.DeviceConfig)
97+
if err != nil {
98+
return nil, err
4699
}
47-
return dual
100+
// Return composite dual device
101+
return &DualDevice{devices: [2]*Device{dev1, dev2}}, nil
48102
}
49103

50104
// Configure configures the pins of the DualDevice
@@ -64,7 +118,7 @@ func (d *Device) Move(steps int32) {
64118
var s int32
65119
d.stepMotor(d.stepNumber)
66120
for s = int32(d.stepNumber); s < steps; s++ {
67-
time.Sleep(time.Duration(d.stepDelay) * time.Microsecond)
121+
time.Sleep(d.stepDelay)
68122
d.moveDirectionSteps(direction, s)
69123
}
70124
}
@@ -101,7 +155,7 @@ func (d *DualDevice) Move(stepsA, stepsB int32) {
101155
stepsA += int32(d.devices[max].stepNumber)
102156
minStep = int32(d.devices[min].stepNumber)
103157
for s := int32(d.devices[max].stepNumber); s < stepsA; s++ {
104-
time.Sleep(time.Duration(d.devices[0].stepDelay) * time.Microsecond)
158+
time.Sleep(d.devices[0].stepDelay)
105159
d.devices[max].moveDirectionSteps(directions[max], s)
106160

107161
if ((s * stepsB) / stepsA) > minStep {
@@ -119,6 +173,18 @@ func (d *DualDevice) Off() {
119173

120174
// stepMotor changes the pins' state to the correct step
121175
func (d *Device) stepMotor(step uint8) {
176+
switch d.stepMode {
177+
default:
178+
fallthrough
179+
case ModeFour:
180+
d.stepMotor4(step)
181+
case ModeEight:
182+
d.stepMotor8(step)
183+
}
184+
}
185+
186+
// stepMotor4 changes the pins' state to the correct step in 4-step mode
187+
func (d *Device) stepMotor4(step uint8) {
122188
switch step {
123189
case 0:
124190
d.pins[0].High()
@@ -148,13 +214,63 @@ func (d *Device) stepMotor(step uint8) {
148214
d.stepNumber = step
149215
}
150216

217+
// stepMotor8 changes the pins' state to the correct step in 8-step mode
218+
func (d *Device) stepMotor8(step uint8) {
219+
switch step {
220+
case 0:
221+
d.pins[0].High()
222+
d.pins[2].Low()
223+
d.pins[1].Low()
224+
d.pins[3].Low()
225+
case 1:
226+
d.pins[0].High()
227+
d.pins[2].High()
228+
d.pins[1].Low()
229+
d.pins[3].Low()
230+
case 2:
231+
d.pins[0].Low()
232+
d.pins[2].High()
233+
d.pins[1].Low()
234+
d.pins[3].Low()
235+
case 3:
236+
d.pins[0].Low()
237+
d.pins[2].High()
238+
d.pins[1].High()
239+
d.pins[3].Low()
240+
case 4:
241+
d.pins[0].Low()
242+
d.pins[2].Low()
243+
d.pins[1].High()
244+
d.pins[3].Low()
245+
case 5:
246+
d.pins[0].Low()
247+
d.pins[2].Low()
248+
d.pins[1].High()
249+
d.pins[3].High()
250+
case 6:
251+
d.pins[0].Low()
252+
d.pins[2].Low()
253+
d.pins[1].Low()
254+
d.pins[3].High()
255+
case 7:
256+
d.pins[0].High()
257+
d.pins[2].Low()
258+
d.pins[1].Low()
259+
d.pins[3].High()
260+
}
261+
d.stepNumber = step
262+
}
263+
151264
// moveDirectionSteps uses the direction to calculate the correct step and change the motor to it.
152-
// Direction true: 0, 1, 2, 3, 0, 1, 2, ...
153-
// Direction false: 0, 3, 2, 1, 0, 3, 2, ...
265+
// Direction true: (4-step mode) 0, 1, 2, 3, 0, 1, 2, ...
266+
// Direction false: (4-step mode) 0, 3, 2, 1, 0, 3, 2, ...
267+
// Direction true: (8-step mode) 0, 1, 2, 3, 4, 5, 6, 7, 0, 1, 2, ...
268+
// Direction false: (8-step mode) 0, 7, 6, 5, 4, 3, 2, 1, 0, 7, 6, ...
154269
func (d *Device) moveDirectionSteps(direction bool, step int32) {
270+
modulus := int32(d.stepMode.stepCount())
155271
if direction {
156-
d.stepMotor(uint8(step % 4))
272+
d.stepMotor(uint8(step % modulus))
157273
} else {
158-
d.stepMotor(uint8((step + 2*(step%2)) % 4))
274+
d.stepMotor(uint8(((-step % modulus) + modulus) % modulus))
159275
}
160276
}

examples/easystepper/main.go

+5-1
Original file line numberDiff line numberDiff line change
@@ -8,7 +8,11 @@ import (
88
)
99

1010
func main() {
11-
motor := easystepper.New(machine.P13, machine.P15, machine.P14, machine.P16, 200, 75)
11+
config := easystepper.DeviceConfig{
12+
Pin1: machine.P13, Pin2: machine.P15, Pin3: machine.P14, Pin4: machine.P16,
13+
StepCount: 200, RPM: 75, Mode: easystepper.ModeFour,
14+
}
15+
motor, _ := easystepper.New(config)
1216
motor.Configure()
1317

1418
for {

0 commit comments

Comments
 (0)