Skip to content

Commit

Permalink
Initial commit of driver code, with accompanying example, for the Ada…
Browse files Browse the repository at this point in the history
…fruit_MotorHat.
  • Loading branch information
Josh Finken committed Aug 2, 2016
1 parent 74a0b76 commit c3f142f
Show file tree
Hide file tree
Showing 4 changed files with 227 additions and 0 deletions.
3 changes: 3 additions & 0 deletions examples/Makefile
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
all:
GOARM=7 GOARCH=arm GOOS=linux go build -v raspi_adafruit.go
# scp raspi_adafruit [email protected]:~
31 changes: 31 additions & 0 deletions examples/raspi_adafruit.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,31 @@
package main

import (
"time"

"github.com/hybridgroup/gobot"
"github.com/hybridgroup/gobot/platforms/i2c"
"github.com/hybridgroup/gobot/platforms/raspi"
)

func main() {
gbot := gobot.NewGobot()
r := raspi.NewRaspiAdaptor("raspi")
adaFruit := i2c.NewAdafruitDriver(r, "adafruit")

work := func() {
gobot.Every(5*time.Second, func() {
adaFruit.Run()
})
}

robot := gobot.NewRobot("adaFruitBot",
[]gobot.Connection{r},
[]gobot.Device{adaFruit},
work,
)

gbot.AddRobot(robot)

gbot.Start()
}
191 changes: 191 additions & 0 deletions platforms/i2c/adafruit_drivers.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,191 @@
package i2c

import (
"fmt"
"time"

"github.com/hybridgroup/gobot"
)

var _ gobot.Driver = (*AdafruitMotorHatDriver)(nil)

const motorHatAddress = 0x60

// TODO: consider moving to other file, etc
const (
// Registers
_Mode1 = 0x00
_Mode2 = 0x01
_SubAdr1 = 0x02
_SubAdr2 = 0x03
_SubAdr3 = 0x04
_Prescale = 0xFE
_LedZeroOnL = 0x06
_LedZeroOnH = 0x07
_LedZeroOffL = 0x08
_LedZeroOffH = 0x09
_AllLedOnL = 0xFA
_AllLedOnH = 0xFB
_AllLedOffL = 0xFC
_AllLedOffH = 0xFD

// Bits
_Restart = 0x80
_Sleep = 0x10
_AllCall = 0x01
_Invrt = 0x10
_Outdrv = 0x04
)

// AdafruitMotorHatDriver is a driver for the DC+Stepper Motor HAT from Adafruit.
// This HAT is a Raspberry Pi add-on that can drive up to 4 DC or 2 Stepper motors
// with full PWM speed control. It has a dedicated PWM driver chip onboard to
// control both motor direction and speed over I2C.
type AdafruitMotorHatDriver struct {
name string
connection I2c
gobot.Commander
}

func (a *AdafruitMotorHatDriver) Name() string { return a.name }
func (a *AdafruitMotorHatDriver) Connection() gobot.Connection { return a.connection.(gobot.Connection) }

// NewAdafruitDriver adds the following API commands: TODO
func NewAdafruitDriver(a I2c, name string) *AdafruitMotorHatDriver {
driver := &AdafruitMotorHatDriver{
name: name,
connection: a,
Commander: gobot.NewCommander(),
}
// TODO: add API funcs
return driver
}

// Start initializes the Adafruit Motor HAT
func (a *AdafruitMotorHatDriver) Start() (errs []error) {
if err := a.connection.I2cStart(motorHatAddress); err != nil {
return []error{err}
}
/*
def __init__(self, address=0x40, debug=False):
self.i2c = Adafruit_I2C(address)
self.i2c.debug = debug
self.address = address
self.debug = debug
if (self.debug):
print "Reseting PCA9685 MODE1 (without SLEEP) and MODE2"
self.setAllPWM(0, 0)
self.i2c.write8(self.__MODE2, self.__OUTDRV)
self.i2c.write8(self.__MODE1, self.__ALLCALL)
time.sleep(0.005) # wait for oscillator
mode1 = self.i2c.readU8(self.__MODE1)
mode1 = mode1 & ~self.__SLEEP # wake up (reset sleep)
self.i2c.write8(self.__MODE1, mode1)
time.sleep(0.005) # wait for oscillator
*/
return
}

// Halt returns true if devices is halted successfully
func (a *AdafruitMotorHatDriver) Halt() (errs []error) { return }

//
/*
def setPWM(self, channel, on, off):
"Sets a single PWM channel"
self.i2c.write8(self.__LED0_ON_L+4*channel, on & 0xFF)
self.i2c.write8(self.__LED0_ON_H+4*channel, on >> 8)
self.i2c.write8(self.__LED0_OFF_L+4*channel, off & 0xFF)
self.i2c.write8(self.__LED0_OFF_H+4*channel, off >> 8)
*/
func (a *AdafruitMotorHatDriver) setPWM(pin byte, on, off int32) (err error) {
reg := _LedZeroOnL + 4*pin
val := byte(on & 0xff)
if err = a.connection.I2cWrite(motorHatAddress, []byte{reg, val}); err != nil {
return
}
reg = _LedZeroOnH + 4*pin
val = byte(on >> 8)
if err = a.connection.I2cWrite(motorHatAddress, []byte{reg, val}); err != nil {
return
}
reg = _LedZeroOffL + 4*pin
val = byte(off & 0xff)
if err = a.connection.I2cWrite(motorHatAddress, []byte{reg, val}); err != nil {
return
}
reg = _LedZeroOffH + 4*pin
val = byte(off >> 8)
if err = a.connection.I2cWrite(motorHatAddress, []byte{reg, val}); err != nil {
return
}
return
}

func (a *AdafruitMotorHatDriver) setPin(pin byte, value int32) (err error) {
if value == 0 {
return a.setPWM(pin, 0, 4096)
}
if value == 1 {
return a.setPWM(pin, 4096, 0)
}
return nil
}

/*
Test Runner:
For motor 3:
pwm = 2
in2 = 3
in1 = 4
1. SetSpeed(setPWM(self.PWMpin, 0, speed*16))
2. Run(Adafruit_MotorHAT.FORWARD):
self.MC.setPin(self.IN2pin, 0)
self.MC.setPin(self.IN1pin, 1)
Run():
Where setPin(pin, value) is:
if (value == 0):
self._pwm.setPWM(pin, 0, 4096)
if (value == 1):
self._pwm.setPWM(pin, 4096, 0)
*/
func (a *AdafruitMotorHatDriver) Run() (err error) {
fmt.Printf("NOW: %s\n", time.Now().String())
//-------------------------------------------------------------------------
// set the speed:
//-------------------------------------------------------------------------
var speed int32 = 255 // full speed!
var in1Pin byte = 4
var in2Pin byte = 3
var pwmPin byte = 2

if err = a.setPWM(pwmPin, 0, speed*16); err != nil {
return
}
//-------------------------------------------------------------------------
// run FORWARD:
//-------------------------------------------------------------------------
if err = a.setPin(in2Pin, 0); err != nil {
return
}
if err = a.setPin(in1Pin, 1); err != nil {
return
}
//-------------------------------------------------------------------------
// Sleep and RELEASE
//-------------------------------------------------------------------------
<-time.After(2000 * time.Millisecond)

if err = a.setPin(in1Pin, 0); err != nil {
return
}
if err = a.setPin(in2Pin, 0); err != nil {
return
}
return
}
2 changes: 2 additions & 0 deletions sysfs/i2c_device.go
Original file line number Diff line number Diff line change
Expand Up @@ -126,6 +126,8 @@ func (d *i2cDevice) Write(b []byte) (n int, err error) {
return d.file.Write(b)
}

// Command byte - a data byte which often selects a register on the device:
// https://www.kernel.org/doc/Documentation/i2c/smbus-protocol
command := byte(b[0])
buf := b[1:]

Expand Down

0 comments on commit c3f142f

Please sign in to comment.