-
Notifications
You must be signed in to change notification settings - Fork 6
/
Copy pathina228.c
165 lines (133 loc) · 4.56 KB
/
ina228.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
152
153
154
155
156
157
158
159
160
161
162
163
164
165
/*
* INA228 - TI Current/Voltage/Power Monitor Code
* Copyright (C) 2021 Craig Peacock
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License
* as published by the Free Software Foundation; either version 3
* of the License, or (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
* 02110-1301, USA.
*/
#include <stdio.h>
#include <string.h>
#include <stdint.h>
#include <stdbool.h>
#include <unistd.h>
#include <byteswap.h>
#include "i2c.h"
#include "ina228.h"
/*
* SHUNT_CAL is a conversion constant that represents the shunt resistance
* used to calculate current value in Amps. This also sets the resolution
* (CURRENT_LSB) for the current register.
*
* SHUNT_CAL is 15 bits wide (0 - 32768)
*
* SHUNT_CAL = 13107.2 x 10^6 x CURRENT_LSB x Rshunt
*
* CURRENT_LSB = Max Expected Current / 2^19
*/
#define CURRENT_LSB 0.000015625
#define SHUNT_CAL 1024
void ina228_init(uint32_t i2c_master_port, uint8_t i2c_slave_addr)
{
i2c_write_short(i2c_master_port, i2c_slave_addr, INA228_CONFIG, 0x8000); // Reset
printf("Manufacturer ID: 0x%04X\r\n",i2c_read_short(i2c_master_port, INA228_SLAVE_ADDRESS, INA228_MANUFACTURER_ID));
printf("Device ID: 0x%04X\r\n",i2c_read_short(i2c_master_port, INA228_SLAVE_ADDRESS, INA228_DEVICE_ID));
i2c_write_short(i2c_master_port, i2c_slave_addr, INA228_SHUNT_CAL, SHUNT_CAL);
printf("\r\n");
}
float ina228_voltage(uint32_t i2c_master_port, uint8_t i2c_slave_addr)
{
int32_t iBusVoltage;
float fBusVoltage;
bool sign;
i2c_read_buf(i2c_master_port, i2c_slave_addr, INA228_VBUS, (uint8_t *)&iBusVoltage, 3);
sign = iBusVoltage & 0x80;
iBusVoltage = bswap_32(iBusVoltage & 0xFFFFFF) >> 12;
if (sign) iBusVoltage += 0xFFF00000;
fBusVoltage = (iBusVoltage) * 0.0001953125;
return (fBusVoltage);
}
float ina228_dietemp(uint32_t i2c_master_port, uint8_t i2c_slave_addr)
{
uint16_t iDieTemp;
float fDieTemp;
iDieTemp = i2c_read_short(i2c_master_port, i2c_slave_addr, INA228_DIETEMP);
fDieTemp = (iDieTemp) * 0.0078125;
return (fDieTemp);
}
float ina228_shuntvoltage(uint32_t i2c_master_port, uint8_t i2c_slave_addr)
{
int32_t iShuntVoltage;
float fShuntVoltage;
bool sign;
i2c_read_buf(i2c_master_port, i2c_slave_addr, INA228_VSHUNT, (uint8_t *)&iShuntVoltage, 3);
sign = iShuntVoltage & 0x80;
iShuntVoltage = bswap_32(iShuntVoltage & 0xFFFFFF) >> 12;
if (sign) iShuntVoltage += 0xFFF00000;
fShuntVoltage = (iShuntVoltage) * 0.0003125; // Output in mV when ADCRange = 0
//fShuntVoltage = (iShuntVoltage) * 0.000078125; // Output in mV when ADCRange = 1
return (fShuntVoltage);
}
float ina228_current(uint32_t i2c_master_port, uint8_t i2c_slave_addr)
{
int32_t iCurrent;
float fCurrent;
bool sign;
i2c_read_buf(i2c_master_port, i2c_slave_addr, INA228_CURRENT, (uint8_t *)&iCurrent, 3);
sign = iCurrent & 0x80;
iCurrent = bswap_32(iCurrent & 0xFFFFFF) >> 12;
if (sign) iCurrent += 0xFFF00000;
fCurrent = (iCurrent) * CURRENT_LSB;
return (fCurrent);
}
float ina228_power(uint32_t i2c_master_port, uint8_t i2c_slave_addr)
{
uint32_t iPower;
float fPower;
i2c_read_buf(i2c_master_port, i2c_slave_addr, INA228_POWER, (uint8_t *)&iPower, 3);
iPower = bswap_32(iPower & 0xFFFFFF) >> 8;
fPower = 3.2 * CURRENT_LSB * iPower;
return (fPower);
}
/*
* Returns energy in Joules.
* 1 Watt = 1 Joule per second
* 1 W/hr = Joules / 3600
*/
float ina228_energy(uint32_t i2c_master_port, uint8_t i2c_slave_addr)
{
uint64_t iEnergy;
float fEnergy;
i2c_read_buf(i2c_master_port, i2c_slave_addr, INA228_ENERGY, (uint8_t *)&iEnergy, 5);
iEnergy = bswap_64(iEnergy & 0xFFFFFFFFFF) >> 24;
fEnergy = 16 * 3.2 * CURRENT_LSB * iEnergy;
return (fEnergy);
}
/*
* Returns electric charge in Coulombs.
* 1 Coulomb = 1 Ampere per second.
* Hence Amp-Hours (Ah) = Coulombs / 3600
*/
float ina228_charge(uint32_t i2c_master_port, uint8_t i2c_slave_addr)
{
int64_t iCharge;
float fCharge;
bool sign;
i2c_read_buf(i2c_master_port, i2c_slave_addr, INA228_CHARGE, (uint8_t *)&iCharge, 5);
sign = iCharge & 0x80;
iCharge = bswap_64(iCharge & 0xFFFFFFFFFF) >> 24;
if (sign) iCharge += 0xFFFFFF0000000000;
fCharge = CURRENT_LSB * iCharge;
return (fCharge);
}