mirror of
https://github.com/tinygo-org/drivers.git
synced 2026-08-13 11:23:40 +00:00
ina260: add new i2c device
This commit is contained in:
@@ -185,6 +185,8 @@ endif
|
|||||||
@md5sum ./build/test.hex
|
@md5sum ./build/test.hex
|
||||||
tinygo build -size short -o ./build/test.hex -target=xiao ./examples/pcf8563/timer/
|
tinygo build -size short -o ./build/test.hex -target=xiao ./examples/pcf8563/timer/
|
||||||
@md5sum ./build/test.hex
|
@md5sum ./build/test.hex
|
||||||
|
tinygo build -size short -o ./build/test.hex -target=feather-m0 ./examples/ina260/main.go
|
||||||
|
@md5sum ./build/test.hex
|
||||||
|
|
||||||
DRIVERS = $(wildcard */)
|
DRIVERS = $(wildcard */)
|
||||||
NOTESTS = build examples flash semihosting pcd8544 shiftregister st7789 microphone mcp3008 gps microbitmatrix \
|
NOTESTS = build examples flash semihosting pcd8544 shiftregister st7789 microphone mcp3008 gps microbitmatrix \
|
||||||
|
|||||||
@@ -80,6 +80,7 @@ The following 61 devices are supported.
|
|||||||
| [HD44780 LCD controller](https://www.sparkfun.com/datasheets/LCD/HD44780.pdf) | GPIO/I2C |
|
| [HD44780 LCD controller](https://www.sparkfun.com/datasheets/LCD/HD44780.pdf) | GPIO/I2C |
|
||||||
| [HUB75 RGB led matrix](https://cdn-learn.adafruit.com/downloads/pdf/32x16-32x32-rgb-led-matrix.pdf) | SPI |
|
| [HUB75 RGB led matrix](https://cdn-learn.adafruit.com/downloads/pdf/32x16-32x32-rgb-led-matrix.pdf) | SPI |
|
||||||
| [ILI9341 TFT color display](https://cdn-shop.adafruit.com/datasheets/ILI9341.pdf) | SPI |
|
| [ILI9341 TFT color display](https://cdn-shop.adafruit.com/datasheets/ILI9341.pdf) | SPI |
|
||||||
|
| [INA260 Volt/Amp/Power meter](https://www.ti.com/lit/ds/symlink/ina260.pdf) | I2C |
|
||||||
| [4x4 Membrane Keypad](https://cdn.sparkfun.com/assets/f/f/a/5/0/DS-16038.pdf) | GPIO |
|
| [4x4 Membrane Keypad](https://cdn.sparkfun.com/assets/f/f/a/5/0/DS-16038.pdf) | GPIO |
|
||||||
| [L293x motor driver](https://www.ti.com/lit/ds/symlink/l293d.pdf) | GPIO/PWM |
|
| [L293x motor driver](https://www.ti.com/lit/ds/symlink/l293d.pdf) | GPIO/PWM |
|
||||||
| [L9110x motor driver](https://www.elecrow.com/download/datasheet-l9110.pdf) | GPIO/PWM |
|
| [L9110x motor driver](https://www.elecrow.com/download/datasheet-l9110.pdf) | GPIO/PWM |
|
||||||
|
|||||||
@@ -0,0 +1,63 @@
|
|||||||
|
package main
|
||||||
|
|
||||||
|
import (
|
||||||
|
"machine"
|
||||||
|
"time"
|
||||||
|
|
||||||
|
"tinygo.org/x/drivers/ina260"
|
||||||
|
)
|
||||||
|
|
||||||
|
func main() {
|
||||||
|
machine.I2C0.Configure(machine.I2CConfig{})
|
||||||
|
|
||||||
|
dev := ina260.New(machine.I2C0)
|
||||||
|
dev.Configure(ina260.Config{
|
||||||
|
AverageMode: ina260.AVGMODE_16,
|
||||||
|
VoltConvTime: ina260.CONVTIME_140USEC,
|
||||||
|
CurrentConvTime: ina260.CONVTIME_140USEC,
|
||||||
|
Mode: ina260.MODE_CONTINUOUS | ina260.MODE_VOLTAGE | ina260.MODE_CURRENT,
|
||||||
|
})
|
||||||
|
|
||||||
|
if dev.Connected() {
|
||||||
|
println("INA260 detected")
|
||||||
|
} else {
|
||||||
|
println("INA260 NOT detected")
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
for {
|
||||||
|
microvolts := dev.Voltage()
|
||||||
|
microamps := dev.Current()
|
||||||
|
microwatts := dev.Power()
|
||||||
|
|
||||||
|
println(fmtD(microvolts, 4, 3), "mV,", fmtD(microamps, 4, 3), "mA,", fmtD(microwatts, 4, 3), "mW")
|
||||||
|
|
||||||
|
time.Sleep(10 * time.Millisecond)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func fmtD(val int32, i int, f int) string {
|
||||||
|
result := make([]byte, i+f+1)
|
||||||
|
neg := false
|
||||||
|
|
||||||
|
if val < 0 {
|
||||||
|
val = -val
|
||||||
|
neg = true
|
||||||
|
}
|
||||||
|
|
||||||
|
for p := len(result) - 1; p >= 0; p-- {
|
||||||
|
result[p] = byte(int32('0') + (val % 10))
|
||||||
|
val = val / 10
|
||||||
|
|
||||||
|
if p == i+1 && p > 0 {
|
||||||
|
p--
|
||||||
|
result[p] = '.'
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if neg {
|
||||||
|
result[0] = '-'
|
||||||
|
}
|
||||||
|
|
||||||
|
return string(result)
|
||||||
|
}
|
||||||
@@ -0,0 +1,112 @@
|
|||||||
|
package ina260
|
||||||
|
|
||||||
|
import "tinygo.org/x/drivers"
|
||||||
|
|
||||||
|
// Device wraps an I2C connection to an INA260 device.
|
||||||
|
type Device struct {
|
||||||
|
bus drivers.I2C
|
||||||
|
Address uint16
|
||||||
|
}
|
||||||
|
|
||||||
|
// Config holds the configuration of the INA260 device.
|
||||||
|
type Config struct {
|
||||||
|
// One of AVGMODE_XXX
|
||||||
|
AverageMode byte
|
||||||
|
|
||||||
|
// One of CONVTIME_XXXXUSEC
|
||||||
|
VoltConvTime byte
|
||||||
|
|
||||||
|
// One of CONVTIME_XXXXUSEC
|
||||||
|
CurrentConvTime byte
|
||||||
|
|
||||||
|
// Multiple of MODE_XXXX
|
||||||
|
Mode byte
|
||||||
|
}
|
||||||
|
|
||||||
|
// New creates a new INA260 connection. The I2C bus must already be
|
||||||
|
// configured.
|
||||||
|
//
|
||||||
|
// This function only creates the Device object, it does not touch the device.
|
||||||
|
func New(bus drivers.I2C) Device {
|
||||||
|
return Device{
|
||||||
|
bus: bus,
|
||||||
|
Address: Address,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Configure sets up the device.
|
||||||
|
//
|
||||||
|
// This only needs to be called to override built-in defaults. By default,
|
||||||
|
// the device starts with:
|
||||||
|
//
|
||||||
|
// * AverageMode = AVGMODE_1
|
||||||
|
// * VoltConvTime = CONVTIME_1100USEC
|
||||||
|
// * CurrentConvTime = CONVTIME_1100USEC
|
||||||
|
// * Mode = MODE_CONTINUOUS | MODE_VOLTAGE | MODE_CURRENT
|
||||||
|
//
|
||||||
|
func (d *Device) Configure(cfg Config) {
|
||||||
|
var val uint16
|
||||||
|
|
||||||
|
val = uint16(cfg.AverageMode&0x7) << 9
|
||||||
|
val |= uint16(cfg.VoltConvTime&0x7) << 6
|
||||||
|
val |= uint16(cfg.CurrentConvTime&0x7) << 3
|
||||||
|
val |= uint16(cfg.Mode & 0x7)
|
||||||
|
|
||||||
|
d.WriteRegister(REG_CONFIG, val)
|
||||||
|
}
|
||||||
|
|
||||||
|
// Resets the device, setting all registers to default values
|
||||||
|
func (d *Device) Reset() {
|
||||||
|
d.WriteRegister(REG_CONFIG, 0x8000)
|
||||||
|
}
|
||||||
|
|
||||||
|
// Connected returns whether an INA260 has been found.
|
||||||
|
func (d *Device) Connected() bool {
|
||||||
|
return d.ReadRegister(REG_MANF_ID) == MANF_ID &&
|
||||||
|
(d.ReadRegister(REG_DIE_ID)&DEVICE_ID_MASK) == DEVICE_ID
|
||||||
|
}
|
||||||
|
|
||||||
|
// Gets the measured current in µA (max resolution 1.25mA)
|
||||||
|
func (d *Device) Current() int32 {
|
||||||
|
val := d.ReadRegister(REG_CURRENT)
|
||||||
|
|
||||||
|
if val&0x8000 == 0 {
|
||||||
|
return int32(val) * 1250
|
||||||
|
}
|
||||||
|
|
||||||
|
// Two's complement, convert to signed int
|
||||||
|
return -(int32(^val) + 1) * 1250
|
||||||
|
}
|
||||||
|
|
||||||
|
// Gets the measured voltage in µV (max resolution 1.25mV)
|
||||||
|
func (d *Device) Voltage() int32 {
|
||||||
|
val := d.ReadRegister(REG_BUSVOLTAGE)
|
||||||
|
|
||||||
|
if val&0x8000 == 0 {
|
||||||
|
return int32(val) * 1250
|
||||||
|
}
|
||||||
|
|
||||||
|
// Two's complement, convert to signed int
|
||||||
|
return -(int32(^val) + 1) * 1250
|
||||||
|
}
|
||||||
|
|
||||||
|
// Gets the measured power in µW (max resolution 10mW)
|
||||||
|
func (d *Device) Power() int32 {
|
||||||
|
return int32(d.ReadRegister(REG_POWER)) * 10000
|
||||||
|
}
|
||||||
|
|
||||||
|
// Read a register
|
||||||
|
func (d *Device) ReadRegister(reg uint8) uint16 {
|
||||||
|
data := []byte{0, 0}
|
||||||
|
d.bus.ReadRegister(uint8(d.Address), reg, data)
|
||||||
|
return (uint16(data[0]) << 8) | uint16(data[1])
|
||||||
|
}
|
||||||
|
|
||||||
|
// Write to a register
|
||||||
|
func (d *Device) WriteRegister(reg uint8, v uint16) {
|
||||||
|
data := []byte{0, 0}
|
||||||
|
data[0] = byte(v >> 8)
|
||||||
|
data[1] = byte(v & 0xff)
|
||||||
|
|
||||||
|
d.bus.WriteRegister(uint8(d.Address), reg, data)
|
||||||
|
}
|
||||||
@@ -0,0 +1,80 @@
|
|||||||
|
package ina260
|
||||||
|
|
||||||
|
import (
|
||||||
|
"testing"
|
||||||
|
|
||||||
|
qt "github.com/frankban/quicktest"
|
||||||
|
"tinygo.org/x/drivers/tester"
|
||||||
|
)
|
||||||
|
|
||||||
|
func TestDefaultI2CAddress(t *testing.T) {
|
||||||
|
c := qt.New(t)
|
||||||
|
bus := tester.NewI2CBus(c)
|
||||||
|
dev := New(bus)
|
||||||
|
c.Assert(dev.Address, qt.Equals, uint16(Address))
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestConnected(t *testing.T) {
|
||||||
|
c := qt.New(t)
|
||||||
|
bus := tester.NewI2CBus(c)
|
||||||
|
fake := tester.NewI2CDevice16(c, Address)
|
||||||
|
fake.Registers = defaultRegisters()
|
||||||
|
bus.AddDevice(fake)
|
||||||
|
|
||||||
|
dev := New(bus)
|
||||||
|
c.Assert(dev.Connected(), qt.Equals, true)
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestVoltage(t *testing.T) {
|
||||||
|
c := qt.New(t)
|
||||||
|
bus := tester.NewI2CBus(c)
|
||||||
|
fake := tester.NewI2CDevice16(c, Address)
|
||||||
|
fake.Registers = defaultRegisters()
|
||||||
|
fake.Registers[REG_BUSVOLTAGE] = 0x2570
|
||||||
|
bus.AddDevice(fake)
|
||||||
|
|
||||||
|
dev := New(bus)
|
||||||
|
// Datasheet: 2570h = 11.98V = 11980mV = 11980000uV
|
||||||
|
c.Assert(dev.Voltage(), qt.Equals, int32(11980000))
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestCurrent(t *testing.T) {
|
||||||
|
c := qt.New(t)
|
||||||
|
bus := tester.NewI2CBus(c)
|
||||||
|
fake := tester.NewI2CDevice16(c, Address)
|
||||||
|
fake.Registers = defaultRegisters()
|
||||||
|
fake.Registers[REG_CURRENT] = 0x2710
|
||||||
|
bus.AddDevice(fake)
|
||||||
|
|
||||||
|
dev := New(bus)
|
||||||
|
// Datasheet: 2710h = 12.5A = 12500mA = 12500000uA
|
||||||
|
c.Assert(dev.Current(), qt.Equals, int32(12500000))
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestPower(t *testing.T) {
|
||||||
|
c := qt.New(t)
|
||||||
|
bus := tester.NewI2CBus(c)
|
||||||
|
fake := tester.NewI2CDevice16(c, Address)
|
||||||
|
fake.Registers = defaultRegisters()
|
||||||
|
fake.Registers[REG_POWER] = 0x3A7F
|
||||||
|
bus.AddDevice(fake)
|
||||||
|
|
||||||
|
dev := New(bus)
|
||||||
|
// 3A7Fh = 149.75W = 149750mW = 149750000uW
|
||||||
|
c.Assert(dev.Power(), qt.Equals, int32(149750000))
|
||||||
|
}
|
||||||
|
|
||||||
|
// defaultRegisters returns the default values for all of the device's registers.
|
||||||
|
// set TI INA260 datasheet for power-on defaults
|
||||||
|
func defaultRegisters() map[uint8]uint16 {
|
||||||
|
return map[uint8]uint16{
|
||||||
|
REG_CONFIG: 0x6127,
|
||||||
|
REG_CURRENT: 0x0000,
|
||||||
|
REG_BUSVOLTAGE: 0x0000,
|
||||||
|
REG_POWER: 0x0000,
|
||||||
|
REG_MASKENABLE: 0x0000,
|
||||||
|
REG_ALERTLIMIT: 0x0000,
|
||||||
|
REG_MANF_ID: 0x5449,
|
||||||
|
REG_DIE_ID: 0x2270,
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,50 @@
|
|||||||
|
package ina260
|
||||||
|
|
||||||
|
// The default I2C address for this device.
|
||||||
|
//
|
||||||
|
// The actual address is configurable by connecting address pins.
|
||||||
|
const Address = 0x40
|
||||||
|
|
||||||
|
// Registers
|
||||||
|
const (
|
||||||
|
REG_CONFIG = 0x00
|
||||||
|
REG_CURRENT = 0x01
|
||||||
|
REG_BUSVOLTAGE = 0x02
|
||||||
|
REG_POWER = 0x03
|
||||||
|
REG_MASKENABLE = 0x06
|
||||||
|
REG_ALERTLIMIT = 0x07
|
||||||
|
REG_MANF_ID = 0xFE
|
||||||
|
REG_DIE_ID = 0xFF
|
||||||
|
)
|
||||||
|
|
||||||
|
// Well-Known Values
|
||||||
|
const (
|
||||||
|
MANF_ID = 0x5449 // TI
|
||||||
|
DEVICE_ID = 0x2270 // 227h
|
||||||
|
DEVICE_ID_MASK = 0xFFF0
|
||||||
|
|
||||||
|
AVGMODE_1 = 0
|
||||||
|
AVGMODE_4 = 1
|
||||||
|
AVGMODE_16 = 2
|
||||||
|
AVGMODE_64 = 3
|
||||||
|
AVGMODE_128 = 4
|
||||||
|
AVGMODE_256 = 5
|
||||||
|
AVGMODE_512 = 6
|
||||||
|
AVGMODE_1024 = 7
|
||||||
|
|
||||||
|
CONVTIME_140USEC = 0
|
||||||
|
CONVTIME_204USEC = 1
|
||||||
|
CONVTIME_332USEC = 2
|
||||||
|
CONVTIME_588USEC = 3
|
||||||
|
CONVTIME_1100USEC = 4 // 1.1 ms
|
||||||
|
CONVTIME_2116USEC = 5 // 2.1 ms
|
||||||
|
CONVTIME_4156USEC = 6 // 4.2 ms
|
||||||
|
CONVTIME_8244USEC = 7 // 8.2 ms
|
||||||
|
|
||||||
|
MODE_CONTINUOUS = 0x4
|
||||||
|
MODE_TRIGGERED = 0x0
|
||||||
|
MODE_VOLTAGE = 0x2
|
||||||
|
MODE_NO_VOLTAGE = 0x0
|
||||||
|
MODE_CURRENT = 0x1
|
||||||
|
MODE_NO_CURRENT = 0x0
|
||||||
|
)
|
||||||
Reference in New Issue
Block a user