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.
This commit is contained in:
Neil Davis
2022-03-02 14:05:54 +00:00
committed by Ron Evans
parent 1c038f5183
commit 8ddcd69ac0
2 changed files with 143 additions and 23 deletions
+138 -22
View File
@@ -2,28 +2,76 @@
package easystepper // import "tinygo.org/x/drivers/easystepper" package easystepper // import "tinygo.org/x/drivers/easystepper"
import ( import (
"errors"
"machine" "machine"
"time" "time"
) )
// StepMode determines the coil sequence used to perform a single step
type StepMode uint8
// Valid values for StepMode
const (
// ModeFour uses a 'four step' coil sequence (12-23-34-41). This is the default (zero-value) mode
ModeFour StepMode = iota
// ModeEight uses an 'eight step' coil sequence (1-12-2-23-3-34-4-41)
ModeEight
)
// stepCount is a helper function to return the number of steps in a StepMode sequence
func (sm StepMode) stepCount() uint {
switch sm {
default:
fallthrough
case ModeFour:
return 4
case ModeEight:
return 8
}
}
// DeviceConfig contains the configuration data for a single easystepper driver
type DeviceConfig struct {
// Pin1 ... Pin4 determines the pins to configure and use for the device
Pin1, Pin2, Pin3, Pin4 machine.Pin
// StepCount is the number of steps required to perform a full revolution of the stepper motor
StepCount uint
// RPM determines the speed of the stepper motor in 'Revolutions per Minute'
RPM uint
// Mode determines the coil sequence used to perform a single step
Mode StepMode
}
// DualDeviceConfig contains the configuration data for a dual easystepper driver
type DualDeviceConfig struct {
DeviceConfig
// Pin5 ... Pin8 determines the pins to configure and use for the second device
Pin5, Pin6, Pin7, Pin8 machine.Pin
}
// Device holds the pins and the delay between steps // Device holds the pins and the delay between steps
type Device struct { type Device struct {
pins [4]machine.Pin pins [4]machine.Pin
stepDelay int32 stepDelay time.Duration
stepNumber uint8 stepNumber uint8
stepMode StepMode
} }
// DualDevice holds information for controlling 2 motors // DualDevice holds information for controlling 2 motors
type DualDevice struct { type DualDevice struct {
devices [2]Device devices [2]*Device
} }
// New returns a new easystepper driver given 4 pins, number of steps and rpm // New returns a new single easystepper driver given a DeviceConfig
func New(pin1, pin2, pin3, pin4 machine.Pin, steps int32, rpm int32) Device { func New(config DeviceConfig) (*Device, error) {
return Device{ if config.StepCount == 0 || config.RPM == 0 {
pins: [4]machine.Pin{pin1, pin2, pin3, pin4}, return nil, errors.New("config.StepCount and config.RPM must be > 0")
stepDelay: 60000000 / (steps * rpm),
} }
return &Device{
pins: [4]machine.Pin{config.Pin1, config.Pin2, config.Pin3, config.Pin4},
stepDelay: time.Second * 60 / time.Duration((config.StepCount * config.RPM)),
stepMode: config.Mode,
}, nil
} }
// Configure configures the pins of the Device // Configure configures the pins of the Device
@@ -34,17 +82,23 @@ func (d *Device) Configure() {
} }
// NewDual returns a new dual easystepper driver given 8 pins, number of steps and rpm // NewDual returns a new dual easystepper driver given 8 pins, number of steps and rpm
func NewDual(pin1, pin2, pin3, pin4, pin5, pin6, pin7, pin8 machine.Pin, steps int32, rpm int32) DualDevice { func NewDual(config DualDeviceConfig) (*DualDevice, error) {
var dual DualDevice // Create the first device
dual.devices[0] = Device{ dev1, err := New(config.DeviceConfig)
pins: [4]machine.Pin{pin1, pin2, pin3, pin4}, if err != nil {
stepDelay: 60000000 / (steps * rpm), return nil, err
} }
dual.devices[1] = Device{ // Create the second device
pins: [4]machine.Pin{pin5, pin6, pin7, pin8}, config.DeviceConfig.Pin1 = config.Pin5
stepDelay: 60000000 / (steps * rpm), config.DeviceConfig.Pin2 = config.Pin6
config.DeviceConfig.Pin3 = config.Pin7
config.DeviceConfig.Pin4 = config.Pin8
dev2, err := New(config.DeviceConfig)
if err != nil {
return nil, err
} }
return dual // Return composite dual device
return &DualDevice{devices: [2]*Device{dev1, dev2}}, nil
} }
// Configure configures the pins of the DualDevice // Configure configures the pins of the DualDevice
@@ -64,7 +118,7 @@ func (d *Device) Move(steps int32) {
var s int32 var s int32
d.stepMotor(d.stepNumber) d.stepMotor(d.stepNumber)
for s = int32(d.stepNumber); s < steps; s++ { for s = int32(d.stepNumber); s < steps; s++ {
time.Sleep(time.Duration(d.stepDelay) * time.Microsecond) time.Sleep(d.stepDelay)
d.moveDirectionSteps(direction, s) d.moveDirectionSteps(direction, s)
} }
} }
@@ -101,7 +155,7 @@ func (d *DualDevice) Move(stepsA, stepsB int32) {
stepsA += int32(d.devices[max].stepNumber) stepsA += int32(d.devices[max].stepNumber)
minStep = int32(d.devices[min].stepNumber) minStep = int32(d.devices[min].stepNumber)
for s := int32(d.devices[max].stepNumber); s < stepsA; s++ { for s := int32(d.devices[max].stepNumber); s < stepsA; s++ {
time.Sleep(time.Duration(d.devices[0].stepDelay) * time.Microsecond) time.Sleep(d.devices[0].stepDelay)
d.devices[max].moveDirectionSteps(directions[max], s) d.devices[max].moveDirectionSteps(directions[max], s)
if ((s * stepsB) / stepsA) > minStep { if ((s * stepsB) / stepsA) > minStep {
@@ -119,6 +173,18 @@ func (d *DualDevice) Off() {
// stepMotor changes the pins' state to the correct step // stepMotor changes the pins' state to the correct step
func (d *Device) stepMotor(step uint8) { func (d *Device) stepMotor(step uint8) {
switch d.stepMode {
default:
fallthrough
case ModeFour:
d.stepMotor4(step)
case ModeEight:
d.stepMotor8(step)
}
}
// stepMotor4 changes the pins' state to the correct step in 4-step mode
func (d *Device) stepMotor4(step uint8) {
switch step { switch step {
case 0: case 0:
d.pins[0].High() d.pins[0].High()
@@ -148,13 +214,63 @@ func (d *Device) stepMotor(step uint8) {
d.stepNumber = step d.stepNumber = step
} }
// stepMotor8 changes the pins' state to the correct step in 8-step mode
func (d *Device) stepMotor8(step uint8) {
switch step {
case 0:
d.pins[0].High()
d.pins[2].Low()
d.pins[1].Low()
d.pins[3].Low()
case 1:
d.pins[0].High()
d.pins[2].High()
d.pins[1].Low()
d.pins[3].Low()
case 2:
d.pins[0].Low()
d.pins[2].High()
d.pins[1].Low()
d.pins[3].Low()
case 3:
d.pins[0].Low()
d.pins[2].High()
d.pins[1].High()
d.pins[3].Low()
case 4:
d.pins[0].Low()
d.pins[2].Low()
d.pins[1].High()
d.pins[3].Low()
case 5:
d.pins[0].Low()
d.pins[2].Low()
d.pins[1].High()
d.pins[3].High()
case 6:
d.pins[0].Low()
d.pins[2].Low()
d.pins[1].Low()
d.pins[3].High()
case 7:
d.pins[0].High()
d.pins[2].Low()
d.pins[1].Low()
d.pins[3].High()
}
d.stepNumber = step
}
// moveDirectionSteps uses the direction to calculate the correct step and change the motor to it. // moveDirectionSteps uses the direction to calculate the correct step and change the motor to it.
// Direction true: 0, 1, 2, 3, 0, 1, 2, ... // Direction true: (4-step mode) 0, 1, 2, 3, 0, 1, 2, ...
// Direction false: 0, 3, 2, 1, 0, 3, 2, ... // Direction false: (4-step mode) 0, 3, 2, 1, 0, 3, 2, ...
// Direction true: (8-step mode) 0, 1, 2, 3, 4, 5, 6, 7, 0, 1, 2, ...
// Direction false: (8-step mode) 0, 7, 6, 5, 4, 3, 2, 1, 0, 7, 6, ...
func (d *Device) moveDirectionSteps(direction bool, step int32) { func (d *Device) moveDirectionSteps(direction bool, step int32) {
modulus := int32(d.stepMode.stepCount())
if direction { if direction {
d.stepMotor(uint8(step % 4)) d.stepMotor(uint8(step % modulus))
} else { } else {
d.stepMotor(uint8((step + 2*(step%2)) % 4)) d.stepMotor(uint8(((-step % modulus) + modulus) % modulus))
} }
} }
+5 -1
View File
@@ -8,7 +8,11 @@ import (
) )
func main() { func main() {
motor := easystepper.New(machine.P13, machine.P15, machine.P14, machine.P16, 200, 75) config := easystepper.DeviceConfig{
Pin1: machine.P13, Pin2: machine.P15, Pin3: machine.P14, Pin4: machine.P16,
StepCount: 200, RPM: 75, Mode: easystepper.ModeFour,
}
motor, _ := easystepper.New(config)
motor.Configure() motor.Configure()
for { for {