-
-
Notifications
You must be signed in to change notification settings - Fork 1k
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
i2c(PCA9685, adafruit): clean up architecture and fix init
- Loading branch information
1 parent
991af9a
commit 4eda24a
Showing
14 changed files
with
1,037 additions
and
1,005 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,45 @@ | ||
package i2c | ||
|
||
import ( | ||
"gobot.io/x/gobot/v2" | ||
) | ||
|
||
// Adafruit2327Driver is a driver for Adafruit 16-Channel PWM/Servo HAT & Bonnet - a Raspberry Pi add-on, based on | ||
// PCA9685. This driver just wraps the PCA9685Driver. | ||
// Stacking 62 of them is possible (addresses 0x40..0x7E), for controlling up to 992 servos. | ||
// datasheet: | ||
// https://cdn-learn.adafruit.com/downloads/pdf/adafruit-16-channel-pwm-servo-hat-for-raspberry-pi.pdf | ||
type Adafruit2327Driver struct { | ||
*PCA9685Driver | ||
} | ||
|
||
// NewAdafruit2327Driver initializes a new driver for PWM servos. | ||
// Params: | ||
// | ||
// c Connector - the Adaptor to use with this Driver | ||
// | ||
// Optional params: | ||
// | ||
// i2c.WithBus(int): bus to use with this driver | ||
// i2c.WithAddress(int): address to use with this driver | ||
func NewAdafruit2327Driver(c Connector, options ...func(Config)) *Adafruit2327Driver { | ||
pca := NewPCA9685Driver(c, options...) // the default address of the driver is already 0x40 | ||
pca.SetName(gobot.DefaultName("Adafruit2327ServoHat")) | ||
d := &Adafruit2327Driver{ | ||
PCA9685Driver: pca, | ||
} | ||
|
||
// TODO: add API funcs | ||
return d | ||
} | ||
|
||
// SetServoMotorFreq sets the frequency for the currently addressed PWM Servo HAT. | ||
func (a *Adafruit2327Driver) SetServoMotorFreq(freq float64) error { | ||
return a.SetPWMFreq(float32(freq)) | ||
} | ||
|
||
// SetServoMotorPulse is a convenience function to specify the 'tick' value, | ||
// between 0-4095, when the signal will turn on, and when it will turn off. | ||
func (a *Adafruit2327Driver) SetServoMotorPulse(channel byte, on, off int32) error { | ||
return a.SetPWM(int(channel), uint16(on), uint16(off)) | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,94 @@ | ||
package i2c | ||
|
||
import ( | ||
"errors" | ||
"strings" | ||
"testing" | ||
|
||
"github.com/stretchr/testify/assert" | ||
"gobot.io/x/gobot/v2" | ||
) | ||
|
||
// this ensures that the implementation implements the gobot.Driver interface | ||
var _ gobot.Driver = (*Adafruit2327Driver)(nil) | ||
|
||
func initTestAdafruit2327WithStubbedAdaptor() (*Adafruit2327Driver, *i2cTestAdaptor) { | ||
a := newI2cTestAdaptor() | ||
d := NewAdafruit2327Driver(a) | ||
if err := d.Start(); err != nil { | ||
panic(err) | ||
} | ||
return d, a | ||
} | ||
|
||
func TestNewAdafruit2327Driver(t *testing.T) { | ||
// arrange & act | ||
d := NewAdafruit2327Driver(newI2cTestAdaptor()) | ||
// assert | ||
assert.IsType(t, &Adafruit2327Driver{}, d) | ||
assert.True(t, strings.HasPrefix(d.Name(), "Adafruit2327ServoHat")) | ||
assert.Equal(t, 0x40, d.defaultAddress) | ||
} | ||
|
||
func TestAdafruit2327Options(t *testing.T) { | ||
// This is a general test, that options are applied in constructor by using the common WithBus() option and | ||
// least one of this driver. Further tests for options can also be done by call of "WithOption(val)(d)". | ||
// arrange & act | ||
d := NewAdafruit2327Driver(newI2cTestAdaptor(), WithBus(2)) | ||
// assert | ||
assert.Equal(t, 2, d.GetBusOrDefault(1)) | ||
} | ||
|
||
func TestAdafruit2327SetServoMotorFreq(t *testing.T) { | ||
// arrange | ||
d, a := initTestAdafruit2327WithStubbedAdaptor() | ||
a.written = []byte{} // reset writes of former test | ||
const freq = 60.0 | ||
// act | ||
err := d.SetServoMotorFreq(freq) | ||
// assert | ||
assert.NoError(t, err) | ||
assert.Equal(t, 9, len(a.written)) // detailed test, see "TestPCA9685SetPWMFreq" | ||
} | ||
|
||
func TestAdafruit2327SetServoMotorFreqError(t *testing.T) { | ||
// arrange | ||
d, a := initTestAdafruit2327WithStubbedAdaptor() | ||
a.i2cWriteImpl = func([]byte) (int, error) { | ||
return 0, errors.New("write error") | ||
} | ||
const freq = 60.0 | ||
// act & assert | ||
assert.ErrorContains(t, d.SetServoMotorFreq(freq), "write error") | ||
} | ||
|
||
func TestAdafruit2327SetServoMotorPulse(t *testing.T) { | ||
// arrange | ||
d, a := initTestAdafruit2327WithStubbedAdaptor() | ||
a.written = []byte{} // reset writes of former test | ||
const ( | ||
channel byte = 7 | ||
on int32 = 1234 | ||
off int32 = 4321 | ||
) | ||
// act | ||
err := d.SetServoMotorPulse(channel, on, off) | ||
// assert | ||
assert.NoError(t, err) | ||
assert.Equal(t, 8, len(a.written)) // detailed test, see "TestPCA9685SetPWM" | ||
} | ||
|
||
func TestAdafruit2327SetServoMotorPulseError(t *testing.T) { | ||
// arrange | ||
d, a := initTestAdafruit2327WithStubbedAdaptor() | ||
a.i2cWriteImpl = func([]byte) (int, error) { | ||
return 0, errors.New("write error") | ||
} | ||
const ( | ||
channel byte = 7 | ||
on int32 = 1234 | ||
off int32 = 4321 | ||
) | ||
// act & assert | ||
assert.ErrorContains(t, d.SetServoMotorPulse(channel, on, off), "write error") | ||
} |
Oops, something went wrong.