-
Notifications
You must be signed in to change notification settings - Fork 0
/
INA219.c
151 lines (133 loc) · 4.35 KB
/
INA219.c
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
// Copyright (c) 2018 Cirque Corp. Restrictions apply. See: www.cirque.com/sw-license
#include "INA219.h"
static uint8_t _slaveAddress = 0x40;
/************************************************************/
/************************************************************/
/******************* HELPER FUNCTIONS ***********************/
static void WriteRegister(uint8_t reg, uint16_t value)
{
I2C_beginTransmission(_slaveAddress);
I2C_write(reg);
I2C_write((value >> 8) & 0xFF);
I2C_write(value & 0xFF);
I2C_endTransmission(true);
}
static uint16_t ReadRegister(uint8_t reg)
{
I2C_beginTransmission(_slaveAddress);
I2C_write(reg);
I2C_endTransmission(false); // NOTE: according to 8.5.6, no STOP condition
I2C_request(_slaveAddress, 2, true);
return ((I2C_read() << 8) | I2C_read());
}
// Checks the Conversion Ready bit (CNVR) in INA219, returns true if set
// INA219 sets this bit when conversions, plus any additional calculations are complete
bool INA219_dataReady(void) // Status Register, CNVR bit
{
if((ReadRegister(REGISTER__BUS_VOLTAGE) & 0x0002) != 0)
return true;
return false;
}
// Triggers a conversion for current measurement. The number of samples to be averaged (internal to INA219)
// is set by INA219_shuntADCAveraging()
static void INA219_triggerShuntMeasurement(uint16_t averagingMask)
{
uint16_t temp = ReadRegister(REGISTER__CONFIG);
temp &= ~CONFIG__SHUNT_ADC_AVERAGE_128;
temp |= CONFIG__MODE_SHUNT_TRIG | averagingMask;
WriteRegister(REGISTER__CONFIG, temp);
}
// Triggers a conversion for current measurement. The number of samples to be averaged (internal to INA219)
// is set by INA219_shuntADCAveraging()
static void INA219_triggerBusMeasurement(uint16_t averagingMask)
{
uint16_t temp = ReadRegister(REGISTER__CONFIG);
temp &= ~CONFIG__SHUNT_ADC_AVERAGE_128;
temp |= CONFIG__MODE_BUS_TRIG | averagingMask;
WriteRegister(REGISTER__CONFIG, temp);
}
/************************************************************/
/************************************************************/
/******************** PUBLIC FUNCTIONS *********************/
// Assigns an I2C slave address and opens the I2C port @ 400kHz
// NOTE: This function must be called before calling any other INA219 functions
void INA219_init(uint8_t slaveAddress)
{
_slaveAddress = slaveAddress;
I2C_init(400000);
WriteRegister(REGISTER__CALIBRATION, 13421);
}
// Writes <data> to the config register (Reg: 0x00)
// NOTE: Use CONFIG__ register masks in INA219.h for easy configuration
void INA219_config(uint16_t data)
{
WriteRegister(REGISTER__CONFIG, data);
}
// Resets all internal INA219 registers to POR defaults
void INA219_reset(void)
{
uint16_t temp = ReadRegister(REGISTER__CONFIG);
temp |= CONFIG__RESET;
WriteRegister(REGISTER__CONFIG, temp);
}
// Measures voltage between IN+ and IN- (across shunt resistor) in uV
// NOTE: Use CONFIG__SHUNT_ADC_AVERAGE masks in INA219.h for setting
int32_t INA219_measureShuntVoltage(uint16_t averagingMask)
{
int32_t temp = 0;
uint32_t delay = 0;
INA219_triggerShuntMeasurement(averagingMask);
switch(averagingMask)
{
case CONFIG__SHUNT_ADC_AVERAGE_1:
delay = CONFIG_DELAY_1;
break;
case CONFIG__SHUNT_ADC_AVERAGE_2:
delay = CONFIG_DELAY_2;
break;
case CONFIG__SHUNT_ADC_AVERAGE_4:
delay = CONFIG_DELAY_4;
break;
case CONFIG__SHUNT_ADC_AVERAGE_8:
delay = CONFIG_DELAY_8;
break;
case CONFIG__SHUNT_ADC_AVERAGE_16:
delay = CONFIG_DELAY_16;
break;
case CONFIG__SHUNT_ADC_AVERAGE_32:
delay = CONFIG_DELAY_32;
break;
case CONFIG__SHUNT_ADC_AVERAGE_64:
delay = CONFIG_DELAY_64;
break;
case CONFIG__SHUNT_ADC_AVERAGE_128:
delay = CONFIG_DELAY_128;
break;
}
if (delay > 0)
{
delayMicroseconds(delay);
}
else
{
while(!INA219_dataReady());
}
temp = (int16_t) ReadRegister(REGISTER__SHUNT_VOLTAGE);
temp *= 10;
return temp;
}
// Measures voltage at IN- pin in mV
// NOTE: Use CONFIG__BUS_ADC_AVERAGE masks in INA219.h for setting
int32_t INA219_measureBusVoltage(uint16_t averagingMask, uint32_t delay)
{
INA219_triggerBusMeasurement(averagingMask);
if (delay > 0)
{
delayMicroseconds(delay);
}
else
{
while(!INA219_dataReady());
}
return (int32_t)((ReadRegister(REGISTER__BUS_VOLTAGE) >> 3) * 4);
}