mirror of
https://github.com/hybridgroup/gobot.git
synced 2025-04-26 13:48:49 +08:00
add generic i2c driver
This commit is contained in:
commit
3d60ca7699
4
Makefile
4
Makefile
@ -8,9 +8,9 @@ EXAMPLES := $(shell grep -L 'joystick' $$(grep -L 'gocv' $(ALL_EXAMPLES)))
|
|||||||
# opencv platform currently skipped to prevent install of preconditions
|
# opencv platform currently skipped to prevent install of preconditions
|
||||||
including_except := $(shell go list ./... | grep -v platforms/opencv)
|
including_except := $(shell go list ./... | grep -v platforms/opencv)
|
||||||
|
|
||||||
# Run tests on nearly all directories
|
# Run tests on nearly all directories without test cache
|
||||||
test:
|
test:
|
||||||
go test -v $(including_except)
|
go test -count=1 -v $(including_except)
|
||||||
|
|
||||||
# Run tests with race detection
|
# Run tests with race detection
|
||||||
test_race:
|
test_race:
|
||||||
|
@ -260,6 +260,7 @@ Support for devices that use Inter-Integrated Circuit (I2C) have a shared set of
|
|||||||
drivers provided using the `gobot/drivers/i2c` package:
|
drivers provided using the `gobot/drivers/i2c` package:
|
||||||
|
|
||||||
- [I2C](https://en.wikipedia.org/wiki/I%C2%B2C) <=> [Drivers](https://github.com/hybridgroup/gobot/tree/master/drivers/i2c)
|
- [I2C](https://en.wikipedia.org/wiki/I%C2%B2C) <=> [Drivers](https://github.com/hybridgroup/gobot/tree/master/drivers/i2c)
|
||||||
|
- Adafruit 2x16 RGB-LCD with 5 keys
|
||||||
- Adafruit Motor Hat
|
- Adafruit Motor Hat
|
||||||
- ADS1015 Analog to Digital Converter
|
- ADS1015 Analog to Digital Converter
|
||||||
- ADS1115 Analog to Digital Converter
|
- ADS1115 Analog to Digital Converter
|
||||||
@ -271,6 +272,7 @@ drivers provided using the `gobot/drivers/i2c` package:
|
|||||||
- BMP280 Barometric Pressure/Temperature/Altitude Sensor
|
- BMP280 Barometric Pressure/Temperature/Altitude Sensor
|
||||||
- BMP388 Barometric Pressure/Temperature/Altitude Sensor
|
- BMP388 Barometric Pressure/Temperature/Altitude Sensor
|
||||||
- DRV2605L Haptic Controller
|
- DRV2605L Haptic Controller
|
||||||
|
- Generic driver for read and write values to/from register address
|
||||||
- Grove Digital Accelerometer
|
- Grove Digital Accelerometer
|
||||||
- GrovePi Expansion Board
|
- GrovePi Expansion Board
|
||||||
- Grove RGB LCD
|
- Grove RGB LCD
|
||||||
@ -285,11 +287,13 @@ drivers provided using the `gobot/drivers/i2c` package:
|
|||||||
- MPL115A2 Barometer
|
- MPL115A2 Barometer
|
||||||
- MPU6050 Accelerometer/Gyroscope
|
- MPU6050 Accelerometer/Gyroscope
|
||||||
- PCA9685 16-channel 12-bit PWM/Servo Driver
|
- PCA9685 16-channel 12-bit PWM/Servo Driver
|
||||||
|
- PCF8591 8-bit 4xA/D & 1xD/A converter
|
||||||
- SHT2x Temperature/Humidity
|
- SHT2x Temperature/Humidity
|
||||||
- SHT3x-D Temperature/Humidity
|
- SHT3x-D Temperature/Humidity
|
||||||
- SSD1306 OLED Display Controller
|
- SSD1306 OLED Display Controller
|
||||||
- TSL2561 Digital Luminosity/Lux/Light Sensor
|
- TSL2561 Digital Luminosity/Lux/Light Sensor
|
||||||
- Wii Nunchuck Controller
|
- Wii Nunchuck Controller
|
||||||
|
- YL-40 Brightness/Temperature sensor, Potentiometer, analog input, analog output Driver
|
||||||
|
|
||||||
Support for devices that use Serial Peripheral Interface (SPI) have
|
Support for devices that use Serial Peripheral Interface (SPI) have
|
||||||
a shared set of drivers provided using the `gobot/drivers/spi` package:
|
a shared set of drivers provided using the `gobot/drivers/spi` package:
|
||||||
|
@ -24,6 +24,7 @@ Gobot has a extensible system for connecting to hardware devices. The following
|
|||||||
- BMP280 Barometric Pressure/Temperature/Altitude Sensor
|
- BMP280 Barometric Pressure/Temperature/Altitude Sensor
|
||||||
- BMP388 Barometric Pressure/Temperature/Altitude Sensor
|
- BMP388 Barometric Pressure/Temperature/Altitude Sensor
|
||||||
- DRV2605L Haptic Controller
|
- DRV2605L Haptic Controller
|
||||||
|
- Generic driver for read and write values to/from register address
|
||||||
- Grove Digital Accelerometer
|
- Grove Digital Accelerometer
|
||||||
- GrovePi Expansion Board
|
- GrovePi Expansion Board
|
||||||
- Grove RGB LCD
|
- Grove RGB LCD
|
||||||
@ -44,7 +45,7 @@ Gobot has a extensible system for connecting to hardware devices. The following
|
|||||||
- SSD1306 OLED Display Controller
|
- SSD1306 OLED Display Controller
|
||||||
- TSL2561 Digital Luminosity/Lux/Light Sensor
|
- TSL2561 Digital Luminosity/Lux/Light Sensor
|
||||||
- Wii Nunchuck Controller
|
- Wii Nunchuck Controller
|
||||||
- Y-40 Brightness/Temperature sensor, Potentiometer, analog input, analog output Driver
|
- YL-40 Brightness/Temperature sensor, Potentiometer, analog input, analog output Driver
|
||||||
|
|
||||||
More drivers are coming soon...
|
More drivers are coming soon...
|
||||||
|
|
||||||
|
@ -22,6 +22,8 @@ var blue = castColor("blue")
|
|||||||
|
|
||||||
type i2cTestAdaptor struct {
|
type i2cTestAdaptor struct {
|
||||||
name string
|
name string
|
||||||
|
bus int
|
||||||
|
address int
|
||||||
written []byte
|
written []byte
|
||||||
mtx sync.Mutex
|
mtx sync.Mutex
|
||||||
i2cConnectErr bool
|
i2cConnectErr bool
|
||||||
@ -153,10 +155,12 @@ func (t *i2cTestAdaptor) WriteBlockData(reg uint8, b []byte) error {
|
|||||||
return t.writeBytes(buf)
|
return t.writeBytes(buf)
|
||||||
}
|
}
|
||||||
|
|
||||||
func (t *i2cTestAdaptor) GetConnection( /* address */ int /* bus */, int) (connection Connection, err error) {
|
func (t *i2cTestAdaptor) GetConnection(address int, bus int) (connection Connection, err error) {
|
||||||
if t.i2cConnectErr {
|
if t.i2cConnectErr {
|
||||||
return nil, errors.New("Invalid i2c connection")
|
return nil, errors.New("Invalid i2c connection")
|
||||||
}
|
}
|
||||||
|
t.bus = bus
|
||||||
|
t.address = address
|
||||||
return t, nil
|
return t, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
81
drivers/i2c/i2c_config_test.go
Normal file
81
drivers/i2c/i2c_config_test.go
Normal file
@ -0,0 +1,81 @@
|
|||||||
|
package i2c
|
||||||
|
|
||||||
|
import (
|
||||||
|
"testing"
|
||||||
|
|
||||||
|
"gobot.io/x/gobot/gobottest"
|
||||||
|
)
|
||||||
|
|
||||||
|
func TestNewConfig(t *testing.T) {
|
||||||
|
// arrange, act
|
||||||
|
ci := NewConfig()
|
||||||
|
// assert
|
||||||
|
c, ok := ci.(*i2cConfig)
|
||||||
|
if !ok {
|
||||||
|
t.Errorf("NewConfig() should have returned a *i2cConfig")
|
||||||
|
}
|
||||||
|
gobottest.Assert(t, c.bus, BusNotInitialized)
|
||||||
|
gobottest.Assert(t, c.address, AddressNotInitialized)
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestWithBus(t *testing.T) {
|
||||||
|
// arrange
|
||||||
|
c := NewConfig()
|
||||||
|
// act
|
||||||
|
c.WithBus(0x23)
|
||||||
|
// assert
|
||||||
|
gobottest.Assert(t, c.(*i2cConfig).bus, 0x23)
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestWithAddress(t *testing.T) {
|
||||||
|
// arrange
|
||||||
|
c := NewConfig()
|
||||||
|
// act
|
||||||
|
c.WithAddress(0x24)
|
||||||
|
// assert
|
||||||
|
gobottest.Assert(t, c.(*i2cConfig).address, 0x24)
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestGetBusOrDefaultWithBusOption(t *testing.T) {
|
||||||
|
var tests = map[string]struct {
|
||||||
|
init int
|
||||||
|
bus int
|
||||||
|
want int
|
||||||
|
}{
|
||||||
|
"not_initialized": {init: -1, bus: 0x25, want: 0x25},
|
||||||
|
"initialized": {init: 0x26, bus: 0x27, want: 0x26},
|
||||||
|
}
|
||||||
|
for name, tc := range tests {
|
||||||
|
t.Run(name, func(t *testing.T) {
|
||||||
|
// arrange
|
||||||
|
c := NewConfig()
|
||||||
|
// act
|
||||||
|
WithBus(tc.init)(c)
|
||||||
|
got := c.GetBusOrDefault(tc.bus)
|
||||||
|
// assert
|
||||||
|
gobottest.Assert(t, got, tc.want)
|
||||||
|
})
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestGetAddressOrDefaultWithAddressOption(t *testing.T) {
|
||||||
|
var tests = map[string]struct {
|
||||||
|
init int
|
||||||
|
address int
|
||||||
|
want int
|
||||||
|
}{
|
||||||
|
"not_initialized": {init: -1, address: 0x28, want: 0x28},
|
||||||
|
"initialized": {init: 0x29, address: 0x2A, want: 0x29},
|
||||||
|
}
|
||||||
|
for name, tc := range tests {
|
||||||
|
t.Run(name, func(t *testing.T) {
|
||||||
|
// arrange
|
||||||
|
c := NewConfig()
|
||||||
|
// act
|
||||||
|
WithAddress(tc.init)(c)
|
||||||
|
got := c.GetAddressOrDefault(tc.address)
|
||||||
|
// assert
|
||||||
|
gobottest.Assert(t, got, tc.want)
|
||||||
|
})
|
||||||
|
}
|
||||||
|
}
|
130
drivers/i2c/i2c_driver.go
Normal file
130
drivers/i2c/i2c_driver.go
Normal file
@ -0,0 +1,130 @@
|
|||||||
|
package i2c
|
||||||
|
|
||||||
|
import (
|
||||||
|
"fmt"
|
||||||
|
"strconv"
|
||||||
|
"sync"
|
||||||
|
|
||||||
|
"gobot.io/x/gobot"
|
||||||
|
)
|
||||||
|
|
||||||
|
// Driver implements the interface gobot.Driver.
|
||||||
|
type Driver struct {
|
||||||
|
name string
|
||||||
|
defaultAddress int
|
||||||
|
connector Connector
|
||||||
|
connection Connection
|
||||||
|
afterStart func() error
|
||||||
|
beforeHalt func() error
|
||||||
|
Config
|
||||||
|
gobot.Commander
|
||||||
|
mutex *sync.Mutex // mutex often needed to ensure that write-read sequences are not interrupted
|
||||||
|
}
|
||||||
|
|
||||||
|
// NewDriver creates a new generic and basic i2c gobot driver.
|
||||||
|
func NewDriver(c Connector, name string, address int, options ...func(Config)) *Driver {
|
||||||
|
d := &Driver{
|
||||||
|
name: gobot.DefaultName(name),
|
||||||
|
defaultAddress: address,
|
||||||
|
connector: c,
|
||||||
|
afterStart: func() error { return nil },
|
||||||
|
beforeHalt: func() error { return nil },
|
||||||
|
Config: NewConfig(),
|
||||||
|
Commander: gobot.NewCommander(),
|
||||||
|
mutex: &sync.Mutex{},
|
||||||
|
}
|
||||||
|
|
||||||
|
for _, option := range options {
|
||||||
|
option(d)
|
||||||
|
}
|
||||||
|
|
||||||
|
return d
|
||||||
|
}
|
||||||
|
|
||||||
|
// Name returns the name of the i2c device.
|
||||||
|
func (d *Driver) Name() string {
|
||||||
|
return d.name
|
||||||
|
}
|
||||||
|
|
||||||
|
// SetName sets the name of the i2c device.
|
||||||
|
func (d *Driver) SetName(name string) {
|
||||||
|
d.name = name
|
||||||
|
}
|
||||||
|
|
||||||
|
// Connection returns the connection of the i2c device.
|
||||||
|
func (d *Driver) Connection() gobot.Connection {
|
||||||
|
return d.connector.(gobot.Connection)
|
||||||
|
}
|
||||||
|
|
||||||
|
// Start initializes the i2c device.
|
||||||
|
func (d *Driver) Start() error {
|
||||||
|
d.mutex.Lock()
|
||||||
|
defer d.mutex.Unlock()
|
||||||
|
|
||||||
|
var err error
|
||||||
|
bus := d.GetBusOrDefault(d.connector.GetDefaultBus())
|
||||||
|
address := d.GetAddressOrDefault(int(d.defaultAddress))
|
||||||
|
|
||||||
|
if d.connection, err = d.connector.GetConnection(address, bus); err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
return d.afterStart()
|
||||||
|
}
|
||||||
|
|
||||||
|
// Halt halts the i2c device.
|
||||||
|
func (d *Driver) Halt() error {
|
||||||
|
d.mutex.Lock()
|
||||||
|
defer d.mutex.Unlock()
|
||||||
|
|
||||||
|
if err := d.beforeHalt(); err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
// currently there is nothing to do here for the driver
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
// Write implements a simple write mechanism to the given register of an i2c device.
|
||||||
|
func (d *Driver) Write(pin string, val int) error {
|
||||||
|
d.mutex.Lock()
|
||||||
|
defer d.mutex.Unlock()
|
||||||
|
|
||||||
|
register, err := driverParseRegister(pin)
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
// TODO: create buffer from size
|
||||||
|
// currently only one byte value is supported
|
||||||
|
b := []byte{uint8(val)}
|
||||||
|
return d.connection.WriteBlockData(uint8(register), b)
|
||||||
|
}
|
||||||
|
|
||||||
|
// Read implements a simple read mechanism from the given register of an i2c device.
|
||||||
|
func (d *Driver) Read(pin string) (int, error) {
|
||||||
|
d.mutex.Lock()
|
||||||
|
defer d.mutex.Unlock()
|
||||||
|
|
||||||
|
register, err := driverParseRegister(pin)
|
||||||
|
if err != nil {
|
||||||
|
return 0, err
|
||||||
|
}
|
||||||
|
|
||||||
|
// TODO: create buffer from size
|
||||||
|
// currently only one byte value is supported
|
||||||
|
b := []byte{0}
|
||||||
|
if err := d.connection.ReadBlockData(register, b); err != nil {
|
||||||
|
return 0, err
|
||||||
|
}
|
||||||
|
|
||||||
|
return int(b[0]), nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func driverParseRegister(pin string) (uint8, error) {
|
||||||
|
register, err := strconv.ParseUint(pin, 10, 8)
|
||||||
|
if err != nil {
|
||||||
|
return 0, fmt.Errorf("Could not parse the register from given pin '%s'", pin)
|
||||||
|
}
|
||||||
|
return uint8(register), nil
|
||||||
|
}
|
139
drivers/i2c/i2c_driver_test.go
Normal file
139
drivers/i2c/i2c_driver_test.go
Normal file
@ -0,0 +1,139 @@
|
|||||||
|
package i2c
|
||||||
|
|
||||||
|
import (
|
||||||
|
"errors"
|
||||||
|
"strings"
|
||||||
|
"testing"
|
||||||
|
|
||||||
|
"gobot.io/x/gobot"
|
||||||
|
"gobot.io/x/gobot/gobottest"
|
||||||
|
)
|
||||||
|
|
||||||
|
var _ gobot.Driver = (*Driver)(nil)
|
||||||
|
|
||||||
|
func initDriverWithStubbedAdaptor() (*Driver, *i2cTestAdaptor) {
|
||||||
|
a := newI2cTestAdaptor()
|
||||||
|
d := NewDriver(a, "I2C_BASIC", 0x15)
|
||||||
|
return d, a
|
||||||
|
}
|
||||||
|
|
||||||
|
func initTestDriver() *Driver {
|
||||||
|
d, _ := initDriverWithStubbedAdaptor()
|
||||||
|
return d
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestNewDriver(t *testing.T) {
|
||||||
|
// arrange
|
||||||
|
a := newI2cTestAdaptor()
|
||||||
|
// act
|
||||||
|
var di interface{} = NewDriver(a, "I2C_BASIC", 0x15)
|
||||||
|
// assert
|
||||||
|
d, ok := di.(*Driver)
|
||||||
|
if !ok {
|
||||||
|
t.Errorf("NewDriver() should have returned a *Driver")
|
||||||
|
}
|
||||||
|
gobottest.Assert(t, strings.Contains(d.name, "I2C_BASIC"), true)
|
||||||
|
gobottest.Assert(t, d.defaultAddress, 0x15)
|
||||||
|
gobottest.Assert(t, d.connector, a)
|
||||||
|
gobottest.Assert(t, d.connection, nil)
|
||||||
|
gobottest.Assert(t, d.afterStart(), nil)
|
||||||
|
gobottest.Assert(t, d.beforeHalt(), nil)
|
||||||
|
gobottest.Refute(t, d.Config, nil)
|
||||||
|
gobottest.Refute(t, d.Commander, nil)
|
||||||
|
gobottest.Refute(t, d.mutex, nil)
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestSetName(t *testing.T) {
|
||||||
|
// arrange
|
||||||
|
d := initTestDriver()
|
||||||
|
// act
|
||||||
|
d.SetName("TESTME")
|
||||||
|
// assert
|
||||||
|
gobottest.Assert(t, d.Name(), "TESTME")
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestConnection(t *testing.T) {
|
||||||
|
// arrange
|
||||||
|
d := initTestDriver()
|
||||||
|
// act, assert
|
||||||
|
gobottest.Refute(t, d.Connection(), nil)
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestStart(t *testing.T) {
|
||||||
|
// arrange
|
||||||
|
d, a := initDriverWithStubbedAdaptor()
|
||||||
|
// act, assert
|
||||||
|
gobottest.Assert(t, d.Start(), nil)
|
||||||
|
gobottest.Assert(t, 0x15, a.address)
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestStartConnectError(t *testing.T) {
|
||||||
|
// arrange
|
||||||
|
d, a := initDriverWithStubbedAdaptor()
|
||||||
|
a.Testi2cConnectErr(true)
|
||||||
|
// act, assert
|
||||||
|
gobottest.Assert(t, d.Start(), errors.New("Invalid i2c connection"))
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestHalt(t *testing.T) {
|
||||||
|
// arrange
|
||||||
|
d := initTestDriver()
|
||||||
|
// act, assert
|
||||||
|
gobottest.Assert(t, d.Halt(), nil)
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestWrite(t *testing.T) {
|
||||||
|
// arrange
|
||||||
|
const (
|
||||||
|
address = "82"
|
||||||
|
wantAddress = uint8(0x52)
|
||||||
|
value = 0x25
|
||||||
|
)
|
||||||
|
d, a := initDriverWithStubbedAdaptor()
|
||||||
|
d.Start()
|
||||||
|
// prepare all writes
|
||||||
|
numCallsWrite := 0
|
||||||
|
a.i2cWriteImpl = func([]byte) (int, error) {
|
||||||
|
numCallsWrite++
|
||||||
|
return 0, nil
|
||||||
|
}
|
||||||
|
// act
|
||||||
|
err := d.Write(address, value)
|
||||||
|
// assert
|
||||||
|
gobottest.Assert(t, err, nil)
|
||||||
|
gobottest.Assert(t, numCallsWrite, 1)
|
||||||
|
gobottest.Assert(t, a.written[0], wantAddress)
|
||||||
|
gobottest.Assert(t, a.written[1], uint8(value))
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestRead(t *testing.T) {
|
||||||
|
// arrange
|
||||||
|
const (
|
||||||
|
address = "83"
|
||||||
|
wantAddress = uint8(0x53)
|
||||||
|
want = uint8(0x44)
|
||||||
|
)
|
||||||
|
d, a := initDriverWithStubbedAdaptor()
|
||||||
|
d.Start()
|
||||||
|
// prepare all writes
|
||||||
|
numCallsWrite := 0
|
||||||
|
a.i2cWriteImpl = func(b []byte) (int, error) {
|
||||||
|
numCallsWrite++
|
||||||
|
return 0, nil
|
||||||
|
}
|
||||||
|
// prepare all reads
|
||||||
|
numCallsRead := 0
|
||||||
|
a.i2cReadImpl = func(b []byte) (int, error) {
|
||||||
|
numCallsRead++
|
||||||
|
b[0] = want
|
||||||
|
return len(b), nil
|
||||||
|
}
|
||||||
|
// act
|
||||||
|
val, err := d.Read(address)
|
||||||
|
// assert
|
||||||
|
gobottest.Assert(t, err, nil)
|
||||||
|
gobottest.Assert(t, val, int(want))
|
||||||
|
gobottest.Assert(t, numCallsWrite, 1)
|
||||||
|
gobottest.Assert(t, a.written[0], wantAddress)
|
||||||
|
gobottest.Assert(t, numCallsRead, 1)
|
||||||
|
}
|
77
examples/digispark_driver.go
Normal file
77
examples/digispark_driver.go
Normal file
@ -0,0 +1,77 @@
|
|||||||
|
// +build example
|
||||||
|
//
|
||||||
|
// Do not build by default.
|
||||||
|
|
||||||
|
package main
|
||||||
|
|
||||||
|
import (
|
||||||
|
"fmt"
|
||||||
|
"strconv"
|
||||||
|
"time"
|
||||||
|
|
||||||
|
"gobot.io/x/gobot"
|
||||||
|
"gobot.io/x/gobot/drivers/i2c"
|
||||||
|
"gobot.io/x/gobot/platforms/digispark"
|
||||||
|
)
|
||||||
|
|
||||||
|
// This is an example for using the generic I2C driver to write and read values
|
||||||
|
// to an i2c device. It is suitable for simple devices, e.g. EEPROM.
|
||||||
|
// The example was tested with the EEPROM part of PCA9501.
|
||||||
|
//
|
||||||
|
// Procedure:
|
||||||
|
// * write value to register (EEPROM address)
|
||||||
|
// * read value back from register (EEPROM address) and check for differences
|
||||||
|
func main() {
|
||||||
|
const (
|
||||||
|
defaultAddress = 0x7F
|
||||||
|
myAddress = 0x44 // needs to be adjusted for your configuration
|
||||||
|
)
|
||||||
|
board := digispark.NewAdaptor()
|
||||||
|
drv := i2c.NewDriver(board, "PCA9501-EEPROM", defaultAddress, i2c.WithAddress(myAddress))
|
||||||
|
var eepromAddr uint8 = 0x00
|
||||||
|
var register string
|
||||||
|
var valWr uint8 = 0xFF
|
||||||
|
var valRd int
|
||||||
|
var err error
|
||||||
|
|
||||||
|
work := func() {
|
||||||
|
gobot.Every(50*time.Millisecond, func() {
|
||||||
|
// write a value 0-255 to EEPROM address 255-0
|
||||||
|
eepromAddr--
|
||||||
|
valWr++
|
||||||
|
register = strconv.Itoa(int(eepromAddr))
|
||||||
|
err = drv.Write(register, int(valWr))
|
||||||
|
if err != nil {
|
||||||
|
fmt.Println("err write:", err)
|
||||||
|
}
|
||||||
|
|
||||||
|
// write process needs some time, so wait at least 5ms before read a value
|
||||||
|
// when decreasing to much, the check below will fail
|
||||||
|
time.Sleep(5 * time.Millisecond)
|
||||||
|
|
||||||
|
// read value back and check for unexpected differences
|
||||||
|
valRd, err = drv.Read(register)
|
||||||
|
if err != nil {
|
||||||
|
fmt.Println("err read:", err)
|
||||||
|
}
|
||||||
|
if int(valWr) != valRd {
|
||||||
|
fmt.Printf("addr: %d wr: %d differ rd: %d\n", eepromAddr, valWr, valRd)
|
||||||
|
}
|
||||||
|
|
||||||
|
if eepromAddr%10 == 0 {
|
||||||
|
fmt.Printf("addr: %d, wr: %d rd: %d\n", eepromAddr, valWr, valRd)
|
||||||
|
}
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
robot := gobot.NewRobot("simpleDriverI2c",
|
||||||
|
[]gobot.Connection{board},
|
||||||
|
[]gobot.Device{drv},
|
||||||
|
work,
|
||||||
|
)
|
||||||
|
|
||||||
|
err = robot.Start()
|
||||||
|
if err != nil {
|
||||||
|
fmt.Println(err)
|
||||||
|
}
|
||||||
|
}
|
@ -60,17 +60,18 @@ func TestRobotWorkRegistry(t *testing.T) {
|
|||||||
func TestRobotAutomationFunctions(t *testing.T) {
|
func TestRobotAutomationFunctions(t *testing.T) {
|
||||||
t.Run("Every with cancel", func(t *testing.T) {
|
t.Run("Every with cancel", func(t *testing.T) {
|
||||||
robot := NewRobot("testbot")
|
robot := NewRobot("testbot")
|
||||||
|
counter := 0
|
||||||
|
|
||||||
rw := robot.Every(context.Background(), time.Millisecond*10, func() {
|
rw := robot.Every(context.Background(), time.Millisecond*100, func() {
|
||||||
_ = 1 + 1 // perform mindless computation!
|
counter++
|
||||||
})
|
})
|
||||||
|
|
||||||
time.Sleep(time.Millisecond * 25)
|
time.Sleep(time.Millisecond * 225)
|
||||||
rw.CallCancelFunc()
|
rw.CallCancelFunc()
|
||||||
|
|
||||||
robot.WorkEveryWaitGroup.Wait()
|
robot.WorkEveryWaitGroup.Wait()
|
||||||
|
|
||||||
assert.Equal(t, 2, rw.tickCount)
|
assert.Equal(t, 2, counter)
|
||||||
postDeleteKeys := collectStringKeysFromWorkRegistry(robot.workRegistry)
|
postDeleteKeys := collectStringKeysFromWorkRegistry(robot.workRegistry)
|
||||||
assert.NotContains(t, postDeleteKeys, rw.id.String())
|
assert.NotContains(t, postDeleteKeys, rw.id.String())
|
||||||
})
|
})
|
||||||
|
Loading…
x
Reference in New Issue
Block a user