mirror of
https://github.com/tinygo-org/drivers.git
synced 2026-08-11 10:23:44 +00:00
ina260: add new i2c device
This commit is contained in:
@@ -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