Skip to content

Commit bb66c37

Browse files
authored
[RSDK-9603] Move enable pin logic into doCycle to allow SetPower and SetRPM to enable the configured EN pins (viamrobotics#4666)
1 parent 067cf77 commit bb66c37

File tree

3 files changed

+151
-100
lines changed

3 files changed

+151
-100
lines changed

.gitignore

+3
Original file line numberDiff line numberDiff line change
@@ -92,3 +92,6 @@ web/cmd/server/*.core
9292

9393
# direnv (optional dev tool)
9494
.envrc
95+
96+
# codegpt
97+
.codegpt/*

components/motor/gpiostepper/gpiostepper.go

+36-58
Original file line numberDiff line numberDiff line change
@@ -85,62 +85,56 @@ func (cfg *Config) Validate(path string) ([]string, error) {
8585

8686
func init() {
8787
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+
)
10291
}
10392

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))
111101
}
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))
115105
}
116-
return b, motorConfig, nil
106+
107+
return err
117108
}
118109

119110
func newGPIOStepper(
120111
ctx context.Context,
121-
b board.Board,
122-
mc Config,
123-
name resource.Name,
112+
deps resource.Dependencies,
113+
conf resource.Config,
124114
logger logging.Logger,
125115
) (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
128124
}
129125

130126
if mc.TicksPerRotation == 0 {
131127
return nil, errors.New("expected ticks_per_rotation in config for motor")
132128
}
133129

134130
m := &gpioStepper{
135-
Named: name.AsNamed(),
131+
Named: conf.ResourceName().AsNamed(),
136132
theBoard: b,
137133
stepsPerRotation: mc.TicksPerRotation,
138134
logger: logger,
139135
opMgr: operation.NewSingleOperationManager(),
140136
}
141137

142-
var err error
143-
144138
// only set enable pins if they exist
145139
if mc.Pins.EnablePinHigh != "" {
146140
m.enablePinHigh, err = b.GPIOPinByName(mc.Pins.EnablePinHigh)
@@ -208,8 +202,7 @@ type gpioStepper struct {
208202
// SetPower sets the percentage of power the motor should employ between 0-1.
209203
func (m *gpioStepper) SetPower(ctx context.Context, powerPct float64, extra map[string]interface{}) error {
210204
if math.Abs(powerPct) <= .0001 {
211-
m.stop()
212-
return nil
205+
return m.Stop(ctx, nil)
213206
}
214207

215208
if m.minDelay == 0 {
@@ -219,7 +212,10 @@ func (m *gpioStepper) SetPower(ctx context.Context, powerPct float64, extra map[
219212
m.Name().Name)
220213
}
221214

215+
// lock added here to prevent race with doStep
216+
m.lock.Lock()
222217
m.stepperDelay = time.Duration(float64(m.minDelay) / math.Abs(powerPct))
218+
m.lock.Unlock()
223219

224220
if powerPct < 0 {
225221
m.targetStepPosition = math.MinInt64
@@ -288,7 +284,9 @@ func (m *gpioStepper) doCycle(ctx context.Context) (time.Duration, error) {
288284
func (m *gpioStepper) doStep(ctx context.Context, forward bool) error {
289285
err := multierr.Combine(
290286
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+
)
292290
if err != nil {
293291
return err
294292
}
@@ -319,13 +317,7 @@ func (m *gpioStepper) GoFor(ctx context.Context, rpm, revolutions float64, extra
319317
ctx, done := m.opMgr.New(ctx)
320318
defer done()
321319

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 {
329321
return multierr.Combine(
330322
m.enable(ctx, false),
331323
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]
406398
defer m.lock.Unlock()
407399

408400
if math.Abs(rpm) <= .0001 {
409-
m.stop()
410-
return nil
401+
return m.Stop(ctx, nil)
411402
}
412403

413404
// 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{
488479
return on, percent, err
489480
}
490481

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-
504482
func (m *gpioStepper) Close(ctx context.Context) error {
505483
err := m.Stop(ctx, nil)
506484

0 commit comments

Comments
 (0)