forked from hybridgroup/gobot
-
Notifications
You must be signed in to change notification settings - Fork 0
/
ina3221_driver.go
212 lines (176 loc) · 6.35 KB
/
ina3221_driver.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
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
package i2c
// INA3221Driver is a driver for the Texas Instruments INA3221 device. The INA3221 is a three-channel
// current and bus voltage monitor with an I2C and SMBUS compatible interface.
//
// INA3221 data sheet and specifications can be found at http://www.ti.com/product/INA3221
//
// This module was tested with SwitchDoc Labs INA3221 breakout board found at http://www.switchdoc.com/
import (
"gobot.io/x/gobot"
)
// INA3221Channel type that defines which INA3221 channel to read from.
type INA3221Channel uint8
const (
ina3221Address uint8 = 0x40 // 1000000 (A0+A1=GND)
ina3221Read uint8 = 0x01
ina3221RegConfig uint8 = 0x00 // CONFIG REGISTER (R/W)
ina3221ConfigReset uint16 = 0x8000 // Reset Bit
ina3221ConfigEnableChan1 uint16 = 0x4000 // Enable INA3221 Channel 1
ina3221ConfigEnableChan2 uint16 = 0x2000 // Enable INA3221 Channel 2
ina3221ConfigEnableChan3 uint16 = 0x1000 // Enable INA3221 Channel 3
ina3221ConfigAvg2 uint16 = 0x0800 // AVG Samples Bit 2 - See table 3 spec
ina3221ConfigAvg1 uint16 = 0x0400 // AVG Samples Bit 1 - See table 3 spec
ina3221ConfigAvg0 uint16 = 0x0200 // AVG Samples Bit 0 - See table 3 spec
ina3221ConfigVBusCT2 uint16 = 0x0100 // VBUS bit 2 Conversion time - See table 4 spec
ina3221ConfigVBusCT1 uint16 = 0x0080 // VBUS bit 1 Conversion time - See table 4 spec
ina3221ConfigVBusCT0 uint16 = 0x0040 // VBUS bit 0 Conversion time - See table 4 spec
ina3221ConfigVShCT2 uint16 = 0x0020 // Vshunt bit 2 Conversion time - See table 5 spec
ina3221ConfigVShCT1 uint16 = 0x0010 // Vshunt bit 1 Conversion time - See table 5 spec
ina3221ConfigVShCT0 uint16 = 0x0008 // Vshunt bit 0 Conversion time - See table 5 spec
ina3221ConfigMode2 uint16 = 0x0004 // Operating Mode bit 2 - See table 6 spec
ina3221ConfigMode1 uint16 = 0x0002 // Operating Mode bit 1 - See table 6 spec
ina3221ConfigMode0 uint16 = 0x0001 // Operating Mode bit 0 - See table 6 spec
ina3221RegShuntVoltage1 uint8 = 0x01 // SHUNT VOLTAGE REGISTER (R)
ina3221RegBusVoltage1 uint8 = 0x02 // BUS VOLTAGE REGISTER (R)
ina3221ShuntResistorValue float64 = 0.1 // default shunt resistor value of 0.1 Ohm
INA3221Channel1 INA3221Channel = 1
INA3221Channel2 INA3221Channel = 2
INA3221Channel3 INA3221Channel = 3
)
// INA3221Driver is a driver for the INA3221 three-channel current and bus voltage monitoring device.
type INA3221Driver struct {
name string
connector Connector
connection Connection
Config
halt chan bool
}
// NewINA3221Driver creates a new driver with the specified i2c interface.
// Params:
// conn Connector - the Adaptor to use with this Driver
//
// Optional params:
// i2c.WithBus(int): bus to use with this driver
// i2c.WithAddress(int): address to use with this driver
func NewINA3221Driver(c Connector, options ...func(Config)) *INA3221Driver {
i := &INA3221Driver{
name: gobot.DefaultName("INA3221"),
connector: c,
Config: NewConfig(),
}
for _, option := range options {
option(i)
}
return i
}
// Name returns the name of the device.
func (i *INA3221Driver) Name() string {
return i.name
}
// SetName sets the name of the device.
func (i *INA3221Driver) SetName(name string) {
i.name = name
}
// Connection returns the connection of the device.
func (i *INA3221Driver) Connection() gobot.Connection {
return i.connector.(gobot.Connection)
}
// Start initializes the INA3221
func (i *INA3221Driver) Start() error {
var err error
bus := i.GetBusOrDefault(i.connector.GetDefaultBus())
address := i.GetAddressOrDefault(int(ina3221Address))
if i.connection, err = i.connector.GetConnection(address, bus); err != nil {
return err
}
if err := i.initialize(); err != nil {
return err
}
return nil
}
// Halt halts the device.
func (i *INA3221Driver) Halt() error {
return nil
}
// GetBusVoltage gets the bus voltage in Volts
func (i *INA3221Driver) GetBusVoltage(channel INA3221Channel) (float64, error) {
value, err := i.getBusVoltageRaw(channel)
if err != nil {
return 0, err
}
return float64(value) * .001, nil
}
// GetShuntVoltage Gets the shunt voltage in mV
func (i *INA3221Driver) GetShuntVoltage(channel INA3221Channel) (float64, error) {
value, err := i.getShuntVoltageRaw(channel)
if err != nil {
return 0, err
}
return float64(value) * float64(.005), nil
}
// GetCurrent gets the current value in mA, taking into account the config settings and current LSB
func (i *INA3221Driver) GetCurrent(channel INA3221Channel) (float64, error) {
value, err := i.GetShuntVoltage(channel)
if err != nil {
return 0, err
}
ma := value / ina3221ShuntResistorValue
return ma, nil
}
// GetLoadVoltage gets the load voltage in mV
func (i *INA3221Driver) GetLoadVoltage(channel INA3221Channel) (float64, error) {
bv, err := i.GetBusVoltage(channel)
if err != nil {
return 0, err
}
sv, err := i.GetShuntVoltage(channel)
if err != nil {
return 0, err
}
return bv + (sv / 1000.0), nil
}
// getBusVoltageRaw gets the raw bus voltage (16-bit signed integer, so +-32767)
func (i *INA3221Driver) getBusVoltageRaw(channel INA3221Channel) (uint16, error) {
val, err := i.readWordFromRegister(ina3221RegBusVoltage1 + (uint8(channel)-1)*2)
if err != nil {
return 0, err
}
value := uint32(val)
if value > 0x7FFF {
value -= 0x10000
}
return uint16(value), nil
}
// getShuntVoltageRaw gets the raw shunt voltage (16-bit signed integer, so +-32767)
func (i *INA3221Driver) getShuntVoltageRaw(channel INA3221Channel) (uint16, error) {
val, err := i.readWordFromRegister(ina3221RegShuntVoltage1 + (uint8(channel)-1)*2)
if err != nil {
return 0, err
}
value := uint32(val)
if value > 0x7FFF {
value -= 0x10000
}
return uint16(value), nil
}
// reads word from supplied register address
func (i *INA3221Driver) readWordFromRegister(reg uint8) (uint16, error) {
val, err := i.connection.ReadWordData(reg)
if err != nil {
return 0, err
}
return uint16((val << 8) | ((val >> 8) & 0xFF)), nil
}
// initialize initializes the INA3221 device
func (i *INA3221Driver) initialize() error {
config := ina3221ConfigEnableChan1 |
ina3221ConfigEnableChan2 |
ina3221ConfigEnableChan3 |
ina3221ConfigAvg1 |
ina3221ConfigVBusCT2 |
ina3221ConfigVShCT2 |
ina3221ConfigMode2 |
ina3221ConfigMode1 |
ina3221ConfigMode0
return i.connection.WriteWordData(ina3221RegConfig, config)
}