@@ -85,62 +85,56 @@ func (cfg *Config) Validate(path string) ([]string, error) {
85
85
86
86
func init () {
87
87
resource .RegisterComponent (motor .API , model , resource.Registration [motor.Motor , * Config ]{
88
- Constructor : func (
89
- ctx context.Context ,
90
- deps resource.Dependencies ,
91
- conf resource.Config ,
92
- logger logging.Logger ,
93
- ) (motor.Motor , error ) {
94
- actualBoard , motorConfig , err := getBoardFromRobotConfig (deps , conf )
95
- if err != nil {
96
- return nil , err
97
- }
98
-
99
- return newGPIOStepper (ctx , actualBoard , * motorConfig , conf .ResourceName (), logger )
100
- },
101
- })
88
+ Constructor : newGPIOStepper ,
89
+ },
90
+ )
102
91
}
103
92
104
- func getBoardFromRobotConfig (deps resource.Dependencies , conf resource.Config ) (board.Board , * Config , error ) {
105
- motorConfig , err := resource.NativeConfig [* Config ](conf )
106
- if err != nil {
107
- return nil , nil , err
108
- }
109
- if motorConfig .BoardName == "" {
110
- return nil , nil , errors .New ("expected board name in config for motor" )
93
+ // TODO (rh) refactor this driver so that the enable and direction logic is at the beginning of each API call
94
+ // and the step -> position logic is the only thing being handled by the background thread.
95
+ // right now too many things can be called out of lock, this function is only called from the constructor, CLose
96
+ // the doCycle step routine, and should not be called elsewhere since there's no lock in to ptoect the enable pins.
97
+ func (m * gpioStepper ) enable (ctx context.Context , high bool ) error {
98
+ var err error
99
+ if m .enablePinHigh != nil {
100
+ err = multierr .Combine (err , m .enablePinHigh .Set (ctx , high , nil ))
111
101
}
112
- b , err := board . FromDependencies ( deps , motorConfig . BoardName )
113
- if err != nil {
114
- return nil , nil , err
102
+
103
+ if m . enablePinLow != nil {
104
+ err = multierr . Combine ( err , m . enablePinLow . Set ( ctx , ! high , nil ))
115
105
}
116
- return b , motorConfig , nil
106
+
107
+ return err
117
108
}
118
109
119
110
func newGPIOStepper (
120
111
ctx context.Context ,
121
- b board.Board ,
122
- mc Config ,
123
- name resource.Name ,
112
+ deps resource.Dependencies ,
113
+ conf resource.Config ,
124
114
logger logging.Logger ,
125
115
) (motor.Motor , error ) {
126
- if b == nil {
127
- return nil , errors .New ("board is required" )
116
+ mc , err := resource.NativeConfig [* Config ](conf )
117
+ if err != nil {
118
+ return nil , err
119
+ }
120
+
121
+ b , err := board .FromDependencies (deps , mc .BoardName )
122
+ if err != nil {
123
+ return nil , err
128
124
}
129
125
130
126
if mc .TicksPerRotation == 0 {
131
127
return nil , errors .New ("expected ticks_per_rotation in config for motor" )
132
128
}
133
129
134
130
m := & gpioStepper {
135
- Named : name .AsNamed (),
131
+ Named : conf . ResourceName () .AsNamed (),
136
132
theBoard : b ,
137
133
stepsPerRotation : mc .TicksPerRotation ,
138
134
logger : logger ,
139
135
opMgr : operation .NewSingleOperationManager (),
140
136
}
141
137
142
- var err error
143
-
144
138
// only set enable pins if they exist
145
139
if mc .Pins .EnablePinHigh != "" {
146
140
m .enablePinHigh , err = b .GPIOPinByName (mc .Pins .EnablePinHigh )
@@ -208,8 +202,7 @@ type gpioStepper struct {
208
202
// SetPower sets the percentage of power the motor should employ between 0-1.
209
203
func (m * gpioStepper ) SetPower (ctx context.Context , powerPct float64 , extra map [string ]interface {}) error {
210
204
if math .Abs (powerPct ) <= .0001 {
211
- m .stop ()
212
- return nil
205
+ return m .Stop (ctx , nil )
213
206
}
214
207
215
208
if m .minDelay == 0 {
@@ -219,7 +212,10 @@ func (m *gpioStepper) SetPower(ctx context.Context, powerPct float64, extra map[
219
212
m .Name ().Name )
220
213
}
221
214
215
+ // lock added here to prevent race with doStep
216
+ m .lock .Lock ()
222
217
m .stepperDelay = time .Duration (float64 (m .minDelay ) / math .Abs (powerPct ))
218
+ m .lock .Unlock ()
223
219
224
220
if powerPct < 0 {
225
221
m .targetStepPosition = math .MinInt64
@@ -288,7 +284,9 @@ func (m *gpioStepper) doCycle(ctx context.Context) (time.Duration, error) {
288
284
func (m * gpioStepper ) doStep (ctx context.Context , forward bool ) error {
289
285
err := multierr .Combine (
290
286
m .dirPin .Set (ctx , forward , nil ),
291
- m .stepPin .Set (ctx , true , nil ))
287
+ m .stepPin .Set (ctx , true , nil ),
288
+ m .enable (ctx , true ),
289
+ )
292
290
if err != nil {
293
291
return err
294
292
}
@@ -319,13 +317,7 @@ func (m *gpioStepper) GoFor(ctx context.Context, rpm, revolutions float64, extra
319
317
ctx , done := m .opMgr .New (ctx )
320
318
defer done ()
321
319
322
- err := m .enable (ctx , true )
323
- if err != nil {
324
- return errors .Wrapf (err , "error enabling motor in GoFor from motor (%s)" , m .Name ().Name )
325
- }
326
-
327
- err = m .goForInternal (ctx , rpm , revolutions )
328
- if err != nil {
320
+ if err := m .goForInternal (ctx , rpm , revolutions ); err != nil {
329
321
return multierr .Combine (
330
322
m .enable (ctx , false ),
331
323
errors .Wrapf (err , "error in GoFor from motor (%s)" , m .Name ().Name ))
@@ -406,8 +398,7 @@ func (m *gpioStepper) SetRPM(ctx context.Context, rpm float64, extra map[string]
406
398
defer m .lock .Unlock ()
407
399
408
400
if math .Abs (rpm ) <= .0001 {
409
- m .stop ()
410
- return nil
401
+ return m .Stop (ctx , nil )
411
402
}
412
403
413
404
// calculate delay between steps for the thread in the goroutine that we started in component creation.
@@ -488,19 +479,6 @@ func (m *gpioStepper) IsPowered(ctx context.Context, extra map[string]interface{
488
479
return on , percent , err
489
480
}
490
481
491
- func (m * gpioStepper ) enable (ctx context.Context , on bool ) error {
492
- var err error
493
- if m .enablePinHigh != nil {
494
- err = multierr .Combine (err , m .enablePinHigh .Set (ctx , on , nil ))
495
- }
496
-
497
- if m .enablePinLow != nil {
498
- err = multierr .Combine (err , m .enablePinLow .Set (ctx , ! on , nil ))
499
- }
500
-
501
- return err
502
- }
503
-
504
482
func (m * gpioStepper ) Close (ctx context.Context ) error {
505
483
err := m .Stop (ctx , nil )
506
484
0 commit comments