1
0
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:
deadprogram 2017-04-24 09:59:43 +02:00
parent 0106cbb861
commit 3f89f7842c
2 changed files with 326 additions and 0 deletions

View 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
)

View 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