diff --git a/README.md b/README.md index 39e39776c..29eeed7e8 100644 --- a/README.md +++ b/README.md @@ -288,6 +288,7 @@ a shared set of drivers provided using the `gobot/drivers/spi` package: - [SPI](https://en.wikipedia.org/wiki/Serial_Peripheral_Interface_Bus) <=> [Drivers](https://github.com/hybridgroup/gobot/tree/master/drivers/spi) - APA102 Programmable LEDs + - MCP3002 Analog/Digital Converter - MCP3004 Analog/Digital Converter - MCP3008 Analog/Digital Converter diff --git a/drivers/spi/README.MD b/drivers/spi/README.MD index cf2907c07..66ac9bbaa 100644 --- a/drivers/spi/README.MD +++ b/drivers/spi/README.MD @@ -15,6 +15,7 @@ Gobot has a extensible system for connecting to hardware devices. The following spi Devices are currently supported: - APA102 Programmable LEDs +- MCP3002 Analog/Digital Converter - MCP3004 Analog/Digital Converter - MCP3008 Analog/Digital Converter - GoPiGo3 Robot diff --git a/drivers/spi/mcp3002.go b/drivers/spi/mcp3002.go new file mode 100644 index 000000000..010a4f6bb --- /dev/null +++ b/drivers/spi/mcp3002.go @@ -0,0 +1,86 @@ +package spi + +import ( + "errors" + "strconv" + + "gobot.io/x/gobot" +) + +// MCP3002DriverMaxChannel is the number of channels (plus one) of this A/D converter. +const MCP3002DriverMaxChannel = 1 + +// MCP3002Driver is a driver for the MCP3002 A/D converter. +type MCP3002Driver struct { + name string + connector Connector + connection Connection +} + +// NewMCP3002Driver creates a new Gobot Driver for MCP3002 A/D converter +// +// Params: +// a *Adaptor - the Adaptor to use with this Driver +// +func NewMCP3002Driver(a Connector) *MCP3002Driver { + d := &MCP3002Driver{ + name: gobot.DefaultName("MCP3002"), + connector: a, + } + return d +} + +// Name returns the name of the device. +func (d *MCP3002Driver) Name() string { return d.name } + +// SetName sets the name of the device. +func (d *MCP3002Driver) SetName(n string) { d.name = n } + +// Connection returns the Connection of the device. +func (d *MCP3002Driver) Connection() gobot.Connection { return d.connection.(gobot.Connection) } + +// Start initializes the driver. +func (d *MCP3002Driver) Start() (err error) { + bus := d.connector.GetSpiDefaultBus() + mode := d.connector.GetSpiDefaultMode() + maxSpeed := d.connector.GetSpiDefaultMaxSpeed() + d.connection, err = d.connector.GetSpiConnection(bus, mode, maxSpeed) + if err != nil { + return err + } + return nil +} + +// Halt stops the driver. +func (d *MCP3002Driver) Halt() (err error) { + d.connection.Close() + return +} + +// Read reads the current analog data for the desired channel. +func (d *MCP3002Driver) Read(channel int) (result int, err error) { + if channel < 0 || channel > MCP3002DriverMaxChannel { + return 0, errors.New("Invalid channel for read") + } + + tx := make([]byte, 2) + tx[0] = 0x68 + (byte(channel) << 4) + tx[1] = 0x00 + + rx := make([]byte, 2) + + err = d.connection.Tx(tx, rx) + if err == nil && len(rx) == 2 { + result = int(((rx[0] & 0x3) << 8) + rx[1]) + } + + return result, err +} + +// AnalogRead returns value from analog reading of specified pin +func (d *MCP3002Driver) AnalogRead(pin string) (value int, err error) { + channel, _ := strconv.Atoi(pin) + value, err = d.Read(channel) + + return +} diff --git a/drivers/spi/mcp3002_test.go b/drivers/spi/mcp3002_test.go new file mode 100644 index 000000000..1285e8c8d --- /dev/null +++ b/drivers/spi/mcp3002_test.go @@ -0,0 +1,37 @@ +package spi + +import ( + "testing" + + "gobot.io/x/gobot" + "gobot.io/x/gobot/drivers/aio" + "gobot.io/x/gobot/gobottest" +) + +var _ gobot.Driver = (*MCP3002Driver)(nil) + +// must implement the AnalogReader interface +var _ aio.AnalogReader = (*MCP3002Driver)(nil) + +func initTestMCP3002Driver() *MCP3002Driver { + d := NewMCP3002Driver(&TestConnector{}) + return d +} + +func TestMCP3002DriverStart(t *testing.T) { + d := initTestMCP3002Driver() + gobottest.Assert(t, d.Start(), nil) +} + +func TestMCP3002DriverHalt(t *testing.T) { + d := initTestMCP3002Driver() + d.Start() + gobottest.Assert(t, d.Halt(), nil) +} + +func TestMCP3002DriverRead(t *testing.T) { + d := initTestMCP3002Driver() + d.Start() + + // TODO: actual read test +} diff --git a/drivers/spi/mcp3004.go b/drivers/spi/mcp3004.go index 6fb92b674..7c4e87a45 100644 --- a/drivers/spi/mcp3004.go +++ b/drivers/spi/mcp3004.go @@ -17,14 +17,14 @@ type MCP3004Driver struct { connection Connection } -// NewMCP3004Driver creates a new Gobot Driver for MCP3004Driver A/D converter +// NewMCP3004Driver creates a new Gobot Driver for MCP3004 A/D converter // // Params: // a *Adaptor - the Adaptor to use with this Driver // func NewMCP3004Driver(a Connector) *MCP3004Driver { d := &MCP3004Driver{ - name: gobot.DefaultName("MCP3008"), + name: gobot.DefaultName("MCP3004"), connector: a, } return d @@ -65,14 +65,14 @@ func (d *MCP3004Driver) Read(channel int) (result int, err error) { tx := make([]byte, 3) tx[0] = 0x01 - tx[1] = 0x80 + (byte(channel) << 4) + tx[1] = byte(8+channel) << 4 tx[2] = 0x00 rx := make([]byte, 3) err = d.connection.Tx(tx, rx) if err == nil && len(rx) == 3 { - result = int(((rx[1] & 0x03) << 8) + rx[2]) + result = int(((rx[1] & 0x3) << 8) + rx[2]) } return result, err diff --git a/drivers/spi/mcp3008.go b/drivers/spi/mcp3008.go index 2de0663f4..484b92a2b 100644 --- a/drivers/spi/mcp3008.go +++ b/drivers/spi/mcp3008.go @@ -65,14 +65,14 @@ func (d *MCP3008Driver) Read(channel int) (result int, err error) { tx := make([]byte, 3) tx[0] = 0x01 - tx[1] = 0x80 + (byte(channel) << 4) + tx[1] = byte(8+channel) << 4 tx[2] = 0x00 rx := make([]byte, 3) err = d.connection.Tx(tx, rx) if err == nil && len(rx) == 3 { - result = int(((rx[1] & 0x03) << 8) + rx[2]) + result = int(((rx[1] & 0x3) << 8) + rx[2]) } return result, err