mirror of
https://github.com/hybridgroup/gobot.git
synced 2025-05-02 22:17:12 +08:00
i2c: initial WIP on support for ADS1015
Signed-off-by: deadprogram <ron@hybridgroup.com>
This commit is contained in:
parent
0106cbb861
commit
3f89f7842c
282
drivers/i2c/ads1015_driver.go
Normal file
282
drivers/i2c/ads1015_driver.go
Normal file
@ -0,0 +1,282 @@
|
||||
package i2c
|
||||
|
||||
import (
|
||||
"errors"
|
||||
"time"
|
||||
|
||||
"gobot.io/x/gobot"
|
||||
)
|
||||
|
||||
const ads1015Address = 0x48
|
||||
|
||||
// ADS1015Driver is a Driver for a ADS1015 analog to digital converter.
|
||||
// Information used to create this driver came from the Adafruit C++ code
|
||||
// for the ADS1015 located here:
|
||||
// https://github.com/adafruit/Adafruit_ADS1X15
|
||||
//
|
||||
// It been tested using the Adafruit breakout board:
|
||||
// https://www.adafruit.com/product/1083
|
||||
//
|
||||
type ADS1015Driver struct {
|
||||
name string
|
||||
conversionDelay int
|
||||
gain uint16
|
||||
connector Connector
|
||||
connection Connection
|
||||
Config
|
||||
}
|
||||
|
||||
// NewADS1015Driver creates a new driver with specified i2c interface
|
||||
// Params:
|
||||
// conn 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 NewADS1015Driver(a Connector, options ...func(Config)) *ADS1015Driver {
|
||||
d := &ADS1015Driver{
|
||||
name: gobot.DefaultName("ADS1015"),
|
||||
connector: a,
|
||||
conversionDelay: ADS1015ConversionDelay,
|
||||
gain: ADS1015RegConfigPga6144v,
|
||||
Config: NewConfig(),
|
||||
}
|
||||
|
||||
for _, option := range options {
|
||||
option(d)
|
||||
}
|
||||
|
||||
return d
|
||||
}
|
||||
|
||||
// Name returns the name for this Driver
|
||||
func (d *ADS1015Driver) Name() string { return d.name }
|
||||
|
||||
// SetName sets the name for this Driver
|
||||
func (d *ADS1015Driver) SetName(n string) { d.name = n }
|
||||
|
||||
// Connection returns the connection for this Driver
|
||||
func (d *ADS1015Driver) Connection() gobot.Connection { return d.connector.(gobot.Connection) }
|
||||
|
||||
// Start initializes the driver
|
||||
func (d *ADS1015Driver) Start() (err error) {
|
||||
bus := d.GetBusOrDefault(d.connector.GetDefaultBus())
|
||||
address := d.GetAddressOrDefault(ads1015Address)
|
||||
|
||||
d.connection, err = d.connector.GetConnection(address, bus)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
return
|
||||
}
|
||||
|
||||
// Halt returns true if device is halted successfully
|
||||
func (d *ADS1015Driver) Halt() (err error) { return }
|
||||
|
||||
// ReadADC gets a single ADC reading from the specified channel
|
||||
func (d *ADS1015Driver) ReadADC(c uint8) (val uint16, err error) {
|
||||
cfg := d.getDefaultConfig()
|
||||
|
||||
switch c {
|
||||
case 0:
|
||||
cfg |= ADS1015RegConfigMuxSingle0
|
||||
case 1:
|
||||
cfg |= ADS1015RegConfigMuxSingle1
|
||||
case 2:
|
||||
cfg |= ADS1015RegConfigMuxSingle2
|
||||
case 3:
|
||||
cfg |= ADS1015RegConfigMuxSingle3
|
||||
default:
|
||||
err = errors.New("Invalid channel.")
|
||||
return
|
||||
}
|
||||
|
||||
if err = d.connection.WriteWordData(ADS1015RegPointerConfig, cfg); err != nil {
|
||||
return
|
||||
}
|
||||
|
||||
time.Sleep(time.Duration(d.conversionDelay) * time.Millisecond)
|
||||
|
||||
if val, err = d.connection.ReadWordData(ADS1015RegPointerConvert); err != nil {
|
||||
val = 0
|
||||
return
|
||||
}
|
||||
|
||||
// Shift 12-bit results right 4 bits for the ADS1015
|
||||
val >>= 4
|
||||
return
|
||||
}
|
||||
|
||||
// ReadADCDifference01 reads the conversion results, measuring the voltage
|
||||
// difference between the P (AIN0) and N (AIN1) input. Returns signed value
|
||||
// since the difference can be either positive or negative.
|
||||
//
|
||||
func (d *ADS1015Driver) ReadADCDifference01() (val int16, err error) {
|
||||
cfg := d.getDefaultConfig()
|
||||
|
||||
cfg |= ADS1015RegConfigMuxDiff01
|
||||
|
||||
if err = d.connection.WriteWordData(ADS1015RegPointerConfig, cfg); err != nil {
|
||||
return
|
||||
}
|
||||
|
||||
time.Sleep(time.Duration(d.conversionDelay) * time.Millisecond)
|
||||
|
||||
return d.getConversionResult()
|
||||
}
|
||||
|
||||
// ReadADCDifference01 reads the conversion results, measuring the voltage
|
||||
// difference between the P (AIN2) and N (AIN3) input. Returns signed value
|
||||
// since the difference can be either positive or negative.
|
||||
//
|
||||
func (d *ADS1015Driver) ReadADCDifference23() (val int16, err error) {
|
||||
cfg := d.getDefaultConfig()
|
||||
|
||||
cfg |= ADS1015RegConfigMuxDiff23
|
||||
|
||||
if err = d.connection.WriteWordData(ADS1015RegPointerConfig, cfg); err != nil {
|
||||
return
|
||||
}
|
||||
|
||||
time.Sleep(time.Duration(d.conversionDelay) * time.Millisecond)
|
||||
|
||||
return d.getConversionResult()
|
||||
}
|
||||
|
||||
func (d *ADS1015Driver) getDefaultConfig() uint16 {
|
||||
var cfg uint16
|
||||
cfg = ADS1015RegConfigCqueNone |
|
||||
ADS1015RegConfigClatNonLat |
|
||||
ADS1015RegConfigCpolActvLow |
|
||||
ADS1015RegConfigCmodeTrad |
|
||||
ADS1015RegConfigDr1600sps |
|
||||
ADS1015RegConfigModeSingle |
|
||||
ADS1015RegConfigOsSingle
|
||||
|
||||
cfg |= d.gain
|
||||
|
||||
return cfg
|
||||
}
|
||||
|
||||
func (d *ADS1015Driver) getConversionResult() (val int16, err error) {
|
||||
var v uint16
|
||||
if v, err = d.connection.ReadWordData(ADS1015RegPointerConvert); err != nil {
|
||||
return int16(0), err
|
||||
}
|
||||
|
||||
// Shift 12-bit results right 4 bits for the ADS1015
|
||||
v >>= 4
|
||||
|
||||
if v > 0x07FF {
|
||||
// negative number - extend the sign to 16th bit
|
||||
v |= 0xF000
|
||||
}
|
||||
|
||||
return int16(v), nil
|
||||
}
|
||||
|
||||
const (
|
||||
// ADS1015ConversionDelay is the conversion delay in ms
|
||||
ADS1015ConversionDelay = 1
|
||||
|
||||
// pointer register
|
||||
ADS1015RegPointerMask = 0x03
|
||||
ADS1015RegPointerConvert = 0x03
|
||||
ADS1015RegPointerConfig = 0x01
|
||||
ADS1015RegPointerLowThresh = 0x02
|
||||
ADS1015RegPointerHiThresh = 0x03
|
||||
|
||||
// config register
|
||||
ADS1015RegConfigOsMask = 0x8000
|
||||
// Write: Set to start a single-conversion
|
||||
ADS1015RegConfigOsSingle = 0x8000
|
||||
// Read: Bit = 0 when conversion is in progress
|
||||
ADS1015RegConfigOsBusy = 0x0000
|
||||
// Read: Bit = 1 when device is not performing a conversion
|
||||
ADS1015RegConfigOsNotBusy = 0x8000
|
||||
|
||||
ADS1015RegConfigMuxMask = 0x7000
|
||||
// Differential P = AIN0, N = AIN1 (default)
|
||||
ADS1015RegConfigMuxDiff01 = 0x0000
|
||||
// Differential P = AIN0, N = AIN3
|
||||
ADS1015RegConfigMuxDiff03 = 0x1000
|
||||
// Differential P = AIN1, N = AIN3
|
||||
ADS1015RegConfigMuxDiff13 = 0x2000
|
||||
// Differential P = AIN2, N = AIN3
|
||||
ADS1015RegConfigMuxDiff23 = 0x3000
|
||||
// Single-ended AIN0
|
||||
ADS1015RegConfigMuxSingle0 = 0x4000
|
||||
// Single-ended AIN1
|
||||
ADS1015RegConfigMuxSingle1 = 0x5000
|
||||
// Single-ended AIN2
|
||||
ADS1015RegConfigMuxSingle2 = 0x6000
|
||||
// Single-ended AIN3
|
||||
ADS1015RegConfigMuxSingle3 = 0x7000
|
||||
|
||||
ADS1015RegConfigPgaMask = 0x0e00
|
||||
// +/-6.144V range = Gain 2/3
|
||||
ADS1015RegConfigPga6144v = 0x0000
|
||||
// +/-4.096V range = Gain 1
|
||||
ADS1015RegConfigPga4096v = 0x0200
|
||||
// +/-2.048V range = Gain 2 (default)
|
||||
ADS1015RegConfigPga2048v = 0x0400
|
||||
// +/-1.024V range = Gain 4
|
||||
ADS1015RegConfigPga1024v = 0x0600
|
||||
// +/-0.512V range = Gain 8
|
||||
ADS1015RegConfigPga0512v = 0x0800
|
||||
// +/-0.256V range = Gain 16
|
||||
ADS1015RegConfigPga0256v = 0x0800
|
||||
|
||||
ADS1015RegConfigModeMask = 0x0100
|
||||
// Continuous conversion mode
|
||||
ADS1015RegConfigModeContin = 0x0000
|
||||
// Power-down single-shot mode (default)
|
||||
ADS1015RegConfigModeSingle = 0x0100
|
||||
|
||||
ADS1015RegConfigDrMask = 0x00e0
|
||||
// 128 samples per second
|
||||
ADS1015RegConfigDr128sps = 0x0000
|
||||
// 250 samples per second
|
||||
ADS1015RegConfigDr250sps = 0x0020
|
||||
// 490 samples per second
|
||||
ADS1015RegConfigDr490sps = 0x0040
|
||||
// 960 samples per second
|
||||
ADS1015RegConfigDr960sps = 0x0060
|
||||
// 1600 samples per second
|
||||
ADS1015RegConfigDr1600sps = 0x0080
|
||||
// 2400 samples per second
|
||||
ADS1015RegConfigDr2400sps = 0x00a0
|
||||
// 3300 samples per second
|
||||
ADS1015RegConfigDr3300sps = 0x00c0
|
||||
|
||||
ADS1015RegConfigCmodeMask = 0x0010
|
||||
// Traditional comparator with hysteresis (default)
|
||||
ADS1015RegConfigCmodeTrad = 0x0000
|
||||
// Window comparator
|
||||
ADS1015RegConfigCmodeWindow = 0x0010
|
||||
|
||||
ADS1015RegConfigCpolMask = 0x0009
|
||||
// ALERT/RDY pin is low when active (default)
|
||||
ADS1015RegConfigCpolActvLow = 0x0000
|
||||
// ALERT/RDY pin is high when active
|
||||
ADS1015RegConfigCpolActvHi = 0x0008
|
||||
|
||||
// Determines if ALERT/RDY pin latches once asserted
|
||||
ADS1015RegConfigClatMask = 0x0004
|
||||
// Non-latching comparator (default)
|
||||
ADS1015RegConfigClatNonLat = 0x0000
|
||||
// Latching comparator
|
||||
ADS1015RegConfigClatLat = 0x0004
|
||||
|
||||
ADS1015RegConfigCqueMask = 0x0003
|
||||
// Assert ALERT/RDY after one conversions
|
||||
ADS1015RegConfigCque1Conv = 0x0000
|
||||
// Assert ALERT/RDY after two conversions
|
||||
ADS1015RegConfigCque2Conv = 0x0001
|
||||
// Assert ALERT/RDY after four conversions
|
||||
ADS1015RegConfigCque4Conv = 0x0002
|
||||
// Disable the comparator and put ALERT/RDY in high state (default)
|
||||
ADS1015RegConfigCqueNone = 0x0003
|
||||
)
|
44
drivers/i2c/ads1015_driver_test.go
Normal file
44
drivers/i2c/ads1015_driver_test.go
Normal file
@ -0,0 +1,44 @@
|
||||
package i2c
|
||||
|
||||
import (
|
||||
"testing"
|
||||
|
||||
"gobot.io/x/gobot"
|
||||
"gobot.io/x/gobot/gobottest"
|
||||
)
|
||||
|
||||
var _ gobot.Driver = (*ADS1015Driver)(nil)
|
||||
|
||||
// --------- HELPERS
|
||||
func initTestADS1015Driver() (driver *ADS1015Driver) {
|
||||
driver, _ = initTestADS1015DriverWithStubbedAdaptor()
|
||||
return
|
||||
}
|
||||
|
||||
func initTestADS1015DriverWithStubbedAdaptor() (*ADS1015Driver, *i2cTestAdaptor) {
|
||||
adaptor := newI2cTestAdaptor()
|
||||
return NewADS1015Driver(adaptor), adaptor
|
||||
}
|
||||
|
||||
// --------- BASE TESTS
|
||||
func TestNewADS1015Driver(t *testing.T) {
|
||||
// Does it return a pointer to an instance of ADS1015Driver?
|
||||
var bm interface{} = NewADS1015Driver(newI2cTestAdaptor())
|
||||
_, ok := bm.(*ADS1015Driver)
|
||||
if !ok {
|
||||
t.Errorf("NewADS1015Driver() should have returned a *ADS1015Driver")
|
||||
}
|
||||
}
|
||||
|
||||
func TestADS1015DriverSetName(t *testing.T) {
|
||||
d := initTestADS1015Driver()
|
||||
d.SetName("TESTME")
|
||||
gobottest.Assert(t, d.Name(), "TESTME")
|
||||
}
|
||||
|
||||
func TestADS1015DriverOptions(t *testing.T) {
|
||||
d := NewADS1015Driver(newI2cTestAdaptor(), WithBus(2))
|
||||
gobottest.Assert(t, d.GetBusOrDefault(1), 2)
|
||||
}
|
||||
|
||||
// --------- DRIVER SPECIFIC TESTS
|
Loading…
x
Reference in New Issue
Block a user