From c9276f440cff768f3509c348a219f5affcbd3bad Mon Sep 17 00:00:00 2001 From: Ron Evans Date: Tue, 14 Aug 2018 00:21:46 +0200 Subject: [PATCH] i2c: GrovePi digitalwrite implemented Signed-off-by: Ron Evans --- drivers/i2c/grovepi_driver.go | 91 +++++++++++++++++++++++------- drivers/i2c/grovepi_driver_test.go | 3 + examples/raspi_grove_pi_blink.go | 34 +++++++++++ 3 files changed, 108 insertions(+), 20 deletions(-) create mode 100644 examples/raspi_grove_pi_blink.go diff --git a/drivers/i2c/grovepi_driver.go b/drivers/i2c/grovepi_driver.go index ac33c4b5..87851878 100644 --- a/drivers/i2c/grovepi_driver.go +++ b/drivers/i2c/grovepi_driver.go @@ -15,14 +15,17 @@ const ( CommandWriteDigital = 2 CommandReadAnalog = 3 CommandWriteAnalog = 4 + CommandPinMode = 5 CommandReadDHT = 40 ) // GrovePiDriver is a driver for the GrovePi for I²C bus interface. type GrovePiDriver struct { - name string - connector Connector - connection Connection + name string + digitalPins map[int]string + analogPins map[int]string + connector Connector + connection Connection Config } @@ -36,9 +39,11 @@ type GrovePiDriver struct { // func NewGrovePiDriver(a Connector, options ...func(Config)) *GrovePiDriver { d := &GrovePiDriver{ - name: gobot.DefaultName("GrovePi"), - connector: a, - Config: NewConfig(), + name: gobot.DefaultName("GrovePi"), + digitalPins: make(map[int]string), + analogPins: make(map[int]string), + connector: a, + Config: NewConfig(), } for _, option := range options { @@ -78,12 +83,18 @@ func (d *GrovePiDriver) Halt() (err error) { return } func (d *GrovePiDriver) AnalogRead(pin string) (value int, err error) { // TODO: strip off the leading "A" - var channel int - channel, err = strconv.Atoi(pin) + var pinNum int + pinNum, err = strconv.Atoi(pin) if err != nil { return } - value, err = d.ReadAnalog(byte(channel)) + + if dir, ok := d.analogPins[pinNum]; !ok || dir != "input" { + d.PinMode(byte(pinNum), "input") + d.analogPins[pinNum] = "input" + } + + value, err = d.ReadAnalog(byte(pinNum)) return } @@ -114,23 +125,41 @@ func (d *GrovePiDriver) ReadAnalog(pin byte) (int, error) { } // ReadDigital reads digitally to the GrovePi -func (d *GrovePiDriver) ReadDigital(pin byte, size int) ([]byte, error) { - buf := []byte{CommandReadDigital, pin, 0, 0} - _, err := d.connection.Write(buf) +func (d *GrovePiDriver) ReadDigital(pin byte) (val int, err error) { + buf := []byte{1, CommandReadDigital, pin, 0, 0} + _, err = d.connection.Write(buf) if err != nil { - return nil, err + return } time.Sleep(100 * time.Millisecond) d.connection.Write([]byte{1}) - data := make([]byte, size) - _, err = d.connection.Read(data) + v, err := d.connection.ReadByte() if err != nil { - return nil, err + return } - return data, err + return int(v), err +} + +// DigitalRead performs a read on a digital pin. +func (d *GrovePiDriver) DigitalRead(pin string) (val int, err error) { + // TODO: strip off the leading "D" + var pinNum int + pinNum, err = strconv.Atoi(pin) + if err != nil { + return + } + + if dir, ok := d.digitalPins[pinNum]; !ok || dir != "input" { + d.PinMode(byte(pinNum), "input") + d.digitalPins[pinNum] = "input" + } + + val, err = d.ReadDigital(byte(pinNum)) + + return } // WriteDigital writes digitally to the GrovePi @@ -144,12 +173,18 @@ func (d *GrovePiDriver) WriteDigital(pin byte, val byte) error { // DigitalWrite writes a value to a specific digital pin implementing the DigitalWriter interface. func (d *GrovePiDriver) DigitalWrite(pin string, val byte) (err error) { // TODO: strip off the leading "D" - var channel int - channel, err = strconv.Atoi(pin) + var pinNum int + pinNum, err = strconv.Atoi(pin) if err != nil { return } - err = d.WriteDigital(byte(channel), val) + + if dir, ok := d.digitalPins[pinNum]; !ok || dir != "output" { + d.PinMode(byte(pinNum), "output") + d.digitalPins[pinNum] = "output" + } + + err = d.WriteDigital(byte(pinNum), val) return } @@ -162,6 +197,22 @@ func (d *GrovePiDriver) WriteAnalog(pin byte, val byte) error { return err } +// PinMode sets the pin mode to input or output. +func (d *GrovePiDriver) PinMode(pin byte, mode string) error { + var b []byte + if mode == "output" { + b = []byte{1, CommandPinMode, pin, 1, 0} + } else { + b = []byte{1, CommandPinMode, pin, 0, 0} + } + _, err := d.connection.Write(b) + time.Sleep(100 * time.Millisecond) + if err != nil { + return err + } + return nil +} + // ReadDHT returns temperature and humidity from DHT sensor func (d *GrovePiDriver) ReadDHT(pin byte, size int) ([]byte, error) { cmd := []byte{1, CommandReadDHT, pin, 0, 0} diff --git a/drivers/i2c/grovepi_driver_test.go b/drivers/i2c/grovepi_driver_test.go index f717f204..9a631554 100644 --- a/drivers/i2c/grovepi_driver_test.go +++ b/drivers/i2c/grovepi_driver_test.go @@ -12,6 +12,9 @@ import ( var _ gobot.Driver = (*GrovePiDriver)(nil) +// must implement the DigitalReader interface +var _ gpio.DigitalReader = (*GrovePiDriver)(nil) + // must implement the DigitalWriter interface var _ gpio.DigitalWriter = (*GrovePiDriver)(nil) diff --git a/examples/raspi_grove_pi_blink.go b/examples/raspi_grove_pi_blink.go new file mode 100644 index 00000000..fed62674 --- /dev/null +++ b/examples/raspi_grove_pi_blink.go @@ -0,0 +1,34 @@ +// +build example +// +// Do not build by default. + +package main + +import ( + "time" + + "gobot.io/x/gobot" + "gobot.io/x/gobot/drivers/gpio" + "gobot.io/x/gobot/drivers/i2c" + "gobot.io/x/gobot/platforms/raspi" +) + +func main() { + r := raspi.NewAdaptor() + gp := i2c.NewGrovePiDriver(r) + led := gpio.NewLedDriver(gp, "2") + + work := func() { + gobot.Every(1*time.Second, func() { + led.Toggle() + }) + } + + robot := gobot.NewRobot("blinkBot", + []gobot.Connection{r}, + []gobot.Device{gp, led}, + work, + ) + + robot.Start() +}