From 69655b6c0333dc33da5669191a073b639b7bc579 Mon Sep 17 00:00:00 2001 From: Cullen Jennings Date: Thu, 19 May 2016 19:48:57 -0600 Subject: [PATCH] Add basic support for INA219 current sensor --- CONTRIBUTORS | 1 + samples/.gitignore | 1 + samples/ina219.go | 49 +++++++++++++++ sensor/ina219/ina219.go | 131 ++++++++++++++++++++++++++++++++++++++++ 4 files changed, 182 insertions(+) create mode 100644 samples/ina219.go create mode 100644 sensor/ina219/ina219.go diff --git a/CONTRIBUTORS b/CONTRIBUTORS index f44d830..a4e1e42 100644 --- a/CONTRIBUTORS +++ b/CONTRIBUTORS @@ -6,3 +6,4 @@ Nikesh Vora Steve Beaulac Al S-M Ben Delarre +Cullen Jennings diff --git a/samples/.gitignore b/samples/.gitignore index af9b180..5158351 100644 --- a/samples/.gitignore +++ b/samples/.gitignore @@ -8,6 +8,7 @@ gpio gpiodetect gpiodirect gpioshort +ina219 l3gd20 led ledshort diff --git a/samples/ina219.go b/samples/ina219.go new file mode 100644 index 0000000..43de691 --- /dev/null +++ b/samples/ina219.go @@ -0,0 +1,49 @@ +// +build ignore + +package main + +import ( + "flag" + "fmt" + "time" + + "github.com/kidoman/embd" + "github.com/kidoman/embd/sensor/ina219" + + _ "github.com/kidoman/embd/host/all" +) + +func main() { + flag.Parse() + + if err := embd.InitI2C(); err != nil { + panic(err) + } + defer embd.CloseI2C() + + bus := embd.NewI2CBus(1) + + ina := ina219.New(bus, 0x40, 0.1) + defer ina.Close() + + for { + sv, err := ina.ShuntVoltage() + if err != nil { + panic(err) + } + + v, err := ina.Voltage() + if err != nil { + panic(err) + } + + c, err := ina.Current() + if err != nil { + panic(err) + } + + fmt.Printf("Shunt Voltage=%v Voltage=%v Current=%v\n", sv, v, c) + + time.Sleep(500 * time.Millisecond) + } +} diff --git a/sensor/ina219/ina219.go b/sensor/ina219/ina219.go new file mode 100644 index 0000000..5cc76c3 --- /dev/null +++ b/sensor/ina219/ina219.go @@ -0,0 +1,131 @@ +// Package ina219 allows interfacing with Texas Instruments INA219 current +// monitor. This is a high side current and voltage monitor with and I2C +// interfcace. + +// TODO - add options to config voltage range, sensitivity and averaging + +package ina219 + +import ( + "math" + "sync" + + "github.com/golang/glog" + "github.com/kidoman/embd" +) + +const ( + configReg = 0x00 + shuntVReg = 0x01 + busVReg = 0x02 + powerReg = 0x03 + currentReg = 0x04 + calibReg = 0x05 +) + +// INA219 represents a Bosch INA219 current sensor. +type INA219 struct { + Bus embd.I2CBus + + address byte + shuntResitance float64 + + initialized bool + mu sync.RWMutex +} + +func New(bus embd.I2CBus, addr byte, shunt float64) *INA219 { + ina := INA219{ + Bus: bus, + address: addr, + shuntResitance: shunt, + } + return &ina +} + +func (d *INA219) setup() error { + d.mu.RLock() + if d.initialized { + d.mu.RUnlock() + return nil + } + d.mu.RUnlock() + + d.mu.Lock() + defer d.mu.Unlock() + + config := uint16(0x219F) // 12, bit no integration, 32v bus range , 40mV shunt range + err := d.Bus.WriteWordToReg(d.address, configReg, config) + if err != nil { + return err + } + + calib := uint16(0.5 + 40.96/d.shuntResitance) + + err = d.Bus.WriteWordToReg(d.address, calibReg, calib) // .1 ohm sense resitor + if err != nil { + return err + } + + glog.V(1).Infof("ina219: initaliized") + + d.initialized = true + + return nil +} + +func (d *INA219) ShuntVoltage() (float64, error) { + if err := d.setup(); err != nil { + return math.NaN(), err + } + + v, err := d.Bus.ReadWordFromReg(d.address, shuntVReg) + if err != nil { + return math.NaN(), err + } + + voltage := float64(v) / 100000.0 + + return voltage, nil +} + +func (d *INA219) Voltage() (float64, error) { + if err := d.setup(); err != nil { + return math.NaN(), err + } + + v, err := d.Bus.ReadWordFromReg(d.address, busVReg) + if err != nil { + return math.NaN(), err + } + + voltage := float64(v>>3) / 250.0 + + return voltage, nil +} + +func (d *INA219) Current() (float64, error) { + if err := d.setup(); err != nil { + return math.NaN(), err + } + + v, err := d.Bus.ReadWordFromReg(d.address, currentReg) + if err != nil { + return math.NaN(), err + } + + current := float64(v) / 1000.0 + + return current, nil +} + +// Close +func (d *INA219) Close() error { + // put in power down mode + config := uint16(0x0000) + err := d.Bus.WriteWordToReg(d.address, configReg, config) + if err != nil { + return err + } + return nil +}