-
Notifications
You must be signed in to change notification settings - Fork 0
/
sensor.go
168 lines (124 loc) · 4.07 KB
/
sensor.go
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
package ina219
import (
"math"
"periph.io/x/periph/conn/i2c"
"periph.io/x/periph/conn/i2c/i2creg"
)
const (
// BusDefault bind power sensor to the first available I2C bus
BusDefault string = ""
busVoltageMultiplier float64 = 0.001
shuntVoltageMultipler float64 = 0.01
powerDividend float64 = 8192.0
currentDivisor float64 = 409.6
)
// Sensor handles interfacing with the INA219 power sensor via I2C
type Sensor struct {
i2c *i2c.Dev
currentConfig Configuration
currentCalibration CalibrationSetting
}
// Close closes the underlying I2C connection for this sensor
func (me *Sensor) Close() error {
return me.i2c.Bus.(i2c.BusCloser).Close()
}
// SetConfig set the configuration options for this sensor
func (me *Sensor) SetConfig(config Configuration) error {
me.currentConfig = config
return me.writeRegU16BE(regConfiguration, config.Flatten())
}
// GetBusVoltage returns the current voltage from the bus sensor in V, or any errors encountered while reading the sensor
func (me *Sensor) GetBusVoltage() (float64, error) {
rawValue, err := me.readRegU16BE(regBusVoltage)
if err != nil {
return math.NaN(), err
}
signedRawValue := int16((rawValue >> 3) * 4)
return float64(signedRawValue) * busVoltageMultiplier, nil
}
// GetShuntVoltage returns the current voltage from the shunt sensor in mV, or any errors encountered while reading the sensor
func (me *Sensor) GetShuntVoltage() (float64, error) {
rawValue, err := me.readRegS16BE(regShuntVoltage)
if err != nil {
return math.NaN(), err
}
return float64(rawValue) * shuntVoltageMultipler, nil
}
// GetCurrent returns the current amp draw from the sensor in mA, or any errors encountered while reading the sensor
func (me *Sensor) GetCurrent() (float64, error) {
rawValue, err := me.readRegS16BE(regCurrent)
if err != nil {
return math.NaN(), err
}
divider := float64(me.currentCalibration) / currentDivisor
return float64(rawValue) / divider, nil
}
// GetPower returns the current power from the sensor in mW, or any errors encountered while reading the sensor
func (me *Sensor) GetPower() (float64, error) {
rawValue, err := me.readRegS16BE(regPower)
if err != nil {
return math.NaN(), err
}
multiplier := powerDividend / float64(me.currentCalibration)
return float64(rawValue) * multiplier, nil
}
// SetPowerSavingMode enables or disables the power saving operating mode on this sensor.
// Returns any errors that occur during operating mode change.
func (me *Sensor) SetPowerSavingMode(enabled bool) error {
if enabled {
me.currentConfig.OperatingMode = ModePowerDown
} else {
me.currentConfig.OperatingMode = ModeShuntBusContinuous
}
return me.SetConfig(me.currentConfig)
}
// SetCalibrationRegister set the calibration value for this sensor.
// Returns any errors that occur during calibration writing
func (me *Sensor) SetCalibrationRegister(val CalibrationSetting) error {
me.currentCalibration = val
return me.writeRegU16BE(regCalibration, uint16(val))
}
func (me *Sensor) writeRegU16BE(reg register, val uint16) error {
_, err := me.i2c.Write([]byte{byte(reg), byte((val & 0xFF00) >> 8), byte(val & 0x00FF)})
return err
}
func (me *Sensor) readRegS16BE(reg register) (int16, error) {
res := make([]byte, 2)
if err := me.i2c.Tx([]byte{byte(reg)}, res); err != nil {
return 0, err
}
result := int16(res[0]) << 8
result |= int16(res[1]) & 0x00FF
return result, nil
}
func (me *Sensor) readRegU16BE(reg register) (uint16, error) {
res := make([]byte, 2)
if err := me.i2c.Tx([]byte{byte(reg)}, res); err != nil {
return 0, err
}
result := uint16(res[0]) << 8
result |= uint16(res[1]) & 0x00FF
return result, nil
}
// NewSensor creates and initializes a new Power sensor
func NewSensor(address uint16, bus string) (*Sensor, error) {
b, err := i2creg.Open(bus)
if err != nil {
return nil, err
}
s := &Sensor{
i2c: &i2c.Dev{
Bus: b,
Addr: address,
},
}
if err = s.SetConfig(DefaultConfiguration()); err != nil {
s.Close()
return nil, err
}
if err = s.SetCalibrationRegister(V32A2); err != nil {
s.Close()
return nil, err
}
return s, nil
}