mirror of
https://github.com/hybridgroup/gobot.git
synced 2025-04-26 13:48:49 +08:00
i2c: update PCA9685 driver to use same protocol as Adafruit Python lib
Signed-off-by: Ron Evans <ron@hybridgroup.com>
This commit is contained in:
parent
58db149a40
commit
b3574b310f
@ -11,6 +11,7 @@ const pca9685Address = 0x40
|
||||
|
||||
const (
|
||||
PCA9685_MODE1 = 0x00
|
||||
PCA9685_MODE2 = 0x01
|
||||
PCA9685_PRESCALE = 0xFE
|
||||
PCA9685_SUBADR1 = 0x02
|
||||
PCA9685_SUBADR2 = 0x03
|
||||
@ -23,6 +24,12 @@ const (
|
||||
PCA9685_ALLLED_ON_H = 0xFB
|
||||
PCA9685_ALLLED_OFF_L = 0xFC
|
||||
PCA9685_ALLLED_OFF_H = 0xFD
|
||||
|
||||
PCA9685_RESTART = 0x80
|
||||
PCA9685_SLEEP = 0x10
|
||||
PCA9685_ALLCALL = 0x01
|
||||
PCA9685_INVRT = 0x10
|
||||
PCA9685_OUTDRV = 0x04
|
||||
)
|
||||
|
||||
// PCA9685Driver is a Gobot Driver for the PCA9685 16-channel 12-bit PWM/Servo controller.
|
||||
@ -101,14 +108,35 @@ func (p *PCA9685Driver) Start() (err error) {
|
||||
return err
|
||||
}
|
||||
|
||||
if _, err := p.connection.Write([]byte{PCA9685_MODE1, 0x00}); err != nil {
|
||||
if err := p.SetAllPWM(0, 0); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
if _, err := p.connection.Write([]byte{PCA9685_ALLLED_OFF_H, 0x10}); err != nil {
|
||||
if _, err := p.connection.Write([]byte{PCA9685_MODE2, PCA9685_OUTDRV}); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
if _, err := p.connection.Write([]byte{PCA9685_MODE1, PCA9685_ALLCALL}); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
time.Sleep(5 * time.Millisecond)
|
||||
|
||||
if _, err := p.connection.Write([]byte{byte(PCA9685_MODE1)}); err != nil {
|
||||
return err
|
||||
}
|
||||
oldmode, err := p.connection.ReadByte()
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
oldmode = oldmode &^ byte(PCA9685_SLEEP)
|
||||
|
||||
if _, err := p.connection.Write([]byte{PCA9685_MODE1, oldmode}); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
time.Sleep(5 * time.Millisecond)
|
||||
|
||||
return
|
||||
}
|
||||
|
||||
@ -127,7 +155,46 @@ func (p *PCA9685Driver) Halt() (err error) {
|
||||
// Most typically you set "on" to a zero value, and then set "off" to your desired duty.
|
||||
//
|
||||
func (p *PCA9685Driver) SetPWM(channel int, on uint16, off uint16) (err error) {
|
||||
if _, err := p.connection.Write([]byte{byte(PCA9685_LED0_ON_L + 4*channel), byte(on), byte(on >> 8), byte(off), byte(off >> 8)}); err != nil {
|
||||
if _, err := p.connection.Write([]byte{byte(PCA9685_LED0_ON_L + 4*channel), byte(on) & 0xFF}); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
if _, err := p.connection.Write([]byte{byte(PCA9685_LED0_ON_H + 4*channel), byte(on >> 8)}); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
if _, err := p.connection.Write([]byte{byte(PCA9685_LED0_OFF_L + 4*channel), byte(off) & 0xFF}); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
if _, err := p.connection.Write([]byte{byte(PCA9685_LED0_OFF_H + 4*channel), byte(off >> 8)}); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
return
|
||||
}
|
||||
|
||||
// SetAllPWM sets all channels to a pwm value from 0-4096.
|
||||
// Params:
|
||||
// on uint16 - the time to start the pulse
|
||||
// off uint16 - the time to stop the pulse
|
||||
//
|
||||
// Most typically you set "on" to a zero value, and then set "off" to your desired duty.
|
||||
//
|
||||
func (p *PCA9685Driver) SetAllPWM(on uint16, off uint16) (err error) {
|
||||
if _, err := p.connection.Write([]byte{byte(PCA9685_ALLLED_ON_L), byte(on) & 0xFF}); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
if _, err := p.connection.Write([]byte{byte(PCA9685_ALLLED_ON_H), byte(on >> 8)}); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
if _, err := p.connection.Write([]byte{byte(PCA9685_ALLLED_OFF_L), byte(off) & 0xFF}); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
if _, err := p.connection.Write([]byte{byte(PCA9685_ALLLED_OFF_H), byte(off >> 8)}); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
@ -149,8 +216,7 @@ func (p *PCA9685Driver) SetPWMFreq(freq float32) error {
|
||||
if _, err := p.connection.Write([]byte{byte(PCA9685_MODE1)}); err != nil {
|
||||
return err
|
||||
}
|
||||
data := make([]byte, 1)
|
||||
oldmode, err := p.connection.Read(data)
|
||||
oldmode, err := p.connection.ReadByte()
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
@ -170,9 +236,10 @@ func (p *PCA9685Driver) SetPWMFreq(freq float32) error {
|
||||
return err
|
||||
}
|
||||
|
||||
time.Sleep(100 * time.Millisecond)
|
||||
time.Sleep(5 * time.Millisecond)
|
||||
|
||||
// Enable response to All Call address, enable auto-increment, clear restart
|
||||
if _, err := p.connection.Write([]byte{byte(PCA9685_MODE1), byte(oldmode | 0xa1)}); err != nil {
|
||||
if _, err := p.connection.Write([]byte{byte(PCA9685_MODE1), byte(oldmode | 0x80)}); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
|
@ -52,8 +52,11 @@ func TestPCA9685DriverOptions(t *testing.T) {
|
||||
|
||||
// Methods
|
||||
func TestPCA9685DriverStart(t *testing.T) {
|
||||
pca := initTestPCA9685Driver()
|
||||
|
||||
pca, adaptor := initTestPCA9685DriverWithStubbedAdaptor()
|
||||
adaptor.i2cReadImpl = func(b []byte) (int, error) {
|
||||
copy(b, []byte{0x01})
|
||||
return 1, nil
|
||||
}
|
||||
gobottest.Assert(t, pca.Start(), nil)
|
||||
}
|
||||
|
||||
@ -72,21 +75,32 @@ func TestPCA9685DriverStartWriteError(t *testing.T) {
|
||||
}
|
||||
|
||||
func TestPCA9685DriverHalt(t *testing.T) {
|
||||
pca := initTestPCA9685Driver()
|
||||
pca, adaptor := initTestPCA9685DriverWithStubbedAdaptor()
|
||||
adaptor.i2cReadImpl = func(b []byte) (int, error) {
|
||||
copy(b, []byte{0x01})
|
||||
return 1, nil
|
||||
}
|
||||
gobottest.Assert(t, pca.Start(), nil)
|
||||
gobottest.Assert(t, pca.Halt(), nil)
|
||||
}
|
||||
|
||||
func TestPCA9685DriverSetPWM(t *testing.T) {
|
||||
pca := initTestPCA9685Driver()
|
||||
pca, adaptor := initTestPCA9685DriverWithStubbedAdaptor()
|
||||
adaptor.i2cReadImpl = func(b []byte) (int, error) {
|
||||
copy(b, []byte{0x01})
|
||||
return 1, nil
|
||||
}
|
||||
gobottest.Assert(t, pca.Start(), nil)
|
||||
gobottest.Assert(t, pca.SetPWM(0, 0, 256), nil)
|
||||
}
|
||||
|
||||
func TestPCA9685DriverSetPWMError(t *testing.T) {
|
||||
pca, adaptor := initTestPCA9685DriverWithStubbedAdaptor()
|
||||
adaptor.i2cReadImpl = func(b []byte) (int, error) {
|
||||
copy(b, []byte{0x01})
|
||||
return 1, nil
|
||||
}
|
||||
gobottest.Assert(t, pca.Start(), nil)
|
||||
|
||||
adaptor.i2cWriteImpl = func([]byte) (int, error) {
|
||||
return 0, errors.New("write error")
|
||||
}
|
||||
@ -95,6 +109,10 @@ func TestPCA9685DriverSetPWMError(t *testing.T) {
|
||||
|
||||
func TestPCA9685DriverSetPWMFreq(t *testing.T) {
|
||||
pca, adaptor := initTestPCA9685DriverWithStubbedAdaptor()
|
||||
adaptor.i2cReadImpl = func(b []byte) (int, error) {
|
||||
copy(b, []byte{0x01})
|
||||
return 1, nil
|
||||
}
|
||||
gobottest.Assert(t, pca.Start(), nil)
|
||||
|
||||
adaptor.i2cReadImpl = func(b []byte) (int, error) {
|
||||
@ -106,6 +124,10 @@ func TestPCA9685DriverSetPWMFreq(t *testing.T) {
|
||||
|
||||
func TestPCA9685DriverSetPWMFreqReadError(t *testing.T) {
|
||||
pca, adaptor := initTestPCA9685DriverWithStubbedAdaptor()
|
||||
adaptor.i2cReadImpl = func(b []byte) (int, error) {
|
||||
copy(b, []byte{0x01})
|
||||
return 1, nil
|
||||
}
|
||||
gobottest.Assert(t, pca.Start(), nil)
|
||||
|
||||
adaptor.i2cReadImpl = func(b []byte) (int, error) {
|
||||
@ -116,6 +138,10 @@ func TestPCA9685DriverSetPWMFreqReadError(t *testing.T) {
|
||||
|
||||
func TestPCA9685DriverSetPWMFreqWriteError(t *testing.T) {
|
||||
pca, adaptor := initTestPCA9685DriverWithStubbedAdaptor()
|
||||
adaptor.i2cReadImpl = func(b []byte) (int, error) {
|
||||
copy(b, []byte{0x01})
|
||||
return 1, nil
|
||||
}
|
||||
gobottest.Assert(t, pca.Start(), nil)
|
||||
|
||||
adaptor.i2cWriteImpl = func([]byte) (int, error) {
|
||||
@ -131,7 +157,11 @@ func TestPCA9685DriverSetName(t *testing.T) {
|
||||
}
|
||||
|
||||
func TestPCA9685DriverCommands(t *testing.T) {
|
||||
pca := initTestPCA9685Driver()
|
||||
pca, adaptor := initTestPCA9685DriverWithStubbedAdaptor()
|
||||
adaptor.i2cReadImpl = func(b []byte) (int, error) {
|
||||
copy(b, []byte{0x01})
|
||||
return 1, nil
|
||||
}
|
||||
pca.Start()
|
||||
|
||||
err := pca.Command("PwmWrite")(map[string]interface{}{"pin": "1", "val": "1"})
|
||||
|
Loading…
x
Reference in New Issue
Block a user