Statistics
| Branch: | Tag: | Revision:

amiro-lld / drivers / INA219 / v1 / alld_INA219.c @ ed9a1bf5

History | View | Annotate | Download (13.098 KB)

1 d6728c5b Thomas Schöpping
/*
2
AMiRo-LLD is a compilation of low-level hardware drivers for the Autonomous Mini Robot (AMiRo) platform.
3 f69ec051 Thomas Schöpping
Copyright (C) 2016..2020  Thomas Schöpping et al.
4 d6728c5b Thomas Schöpping

5
This program is free software: you can redistribute it and/or modify
6 f0ca400f Thomas Schöpping
it under the terms of the GNU Lesser General Public License as published by
7 d6728c5b Thomas Schöpping
the Free Software Foundation, either version 3 of the License, or
8
(at your option) any later version.
9

10
This program is distributed in the hope that it will be useful,
11
but WITHOUT ANY WARRANTY; without even the implied warranty of
12
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
13 f0ca400f Thomas Schöpping
GNU Lesser General Public License for more details.
14 d6728c5b Thomas Schöpping

15 f0ca400f Thomas Schöpping
You should have received a copy of the GNU Lesser General Public License
16 d6728c5b Thomas Schöpping
along with this program.  If not, see <http://www.gnu.org/licenses/>.
17
*/
18
19 5e2f673b Marc Rothmann
/**
20 9466e34d Thomas Schöpping
 * @file    alld_INA219.c
21 5e2f673b Marc Rothmann
 * @brief   Power Monitor function implementations
22
 *
23
 * @addtogroup lld_power
24
 * @{
25
 */
26
27 1d5bcc82 Thomas Schöpping
#include <alld_INA219.h>
28 d6728c5b Thomas Schöpping
29 ef078306 Thomas Schöpping
/******************************************************************************/
30
/* LOCAL DEFINITIONS                                                          */
31
/******************************************************************************/
32
33
/******************************************************************************/
34
/* EXPORTED VARIABLES                                                         */
35
/******************************************************************************/
36
37
/******************************************************************************/
38
/* LOCAL TYPES                                                                */
39
/******************************************************************************/
40
41
/******************************************************************************/
42
/* LOCAL VARIABLES                                                            */
43
/******************************************************************************/
44
45
/******************************************************************************/
46
/* LOCAL FUNCTIONS                                                            */
47
/******************************************************************************/
48
49
/******************************************************************************/
50
/* EXPORTED FUNCTIONS                                                         */
51
/******************************************************************************/
52
53 d6728c5b Thomas Schöpping
/**
54
 * @brief Read the value of one or more of the registers.
55
 * @param[in]   i2cd        i2c driver
56
 * @param[in]   inad        ina219 driver
57
 * @param[in]   addr        register address
58
 * @param[out]  data        register content
59
 * @param[in]   num         number of subsequent registers to read
60
 * @param[in]   timeout     timeout
61
 * @return                  An indicator whether the call was successfull
62
 */
63 21076167 Thomas Schöpping
apalExitStatus_t ina219_lld_read_register(const INA219Driver* const ina219, const ina219_lld_register_t addr, uint16_t* const data, const uint8_t num, const apalTime_t timeout)
64 d6728c5b Thomas Schöpping
{
65
  apalDbgAssert(ina219 != NULL);
66
  apalDbgAssert(ina219->i2cd != NULL);
67
  apalDbgAssert(data != NULL);
68
69
  uint8_t buffer[num*2];
70
  apalExitStatus_t status = apalI2CMasterTransmit(ina219->i2cd, (INA219_LLD_I2C_ADDR_FIXED | ina219->addr), (uint8_t*)&addr, 1, buffer, 2*num, timeout);
71
  for (uint8_t dataIdx = 0; dataIdx < num; dataIdx++) {
72
    data[dataIdx] = (buffer[2*dataIdx] << 8) | buffer[2*dataIdx+1];
73
  }
74
  return status;
75
}
76
77
/**
78
 * @brief Write the value of one or more of the registers.
79
 * @param[in]   i2cd        i2c driver
80
 * @param[in]   inad        ina219 driver
81
 * @param[in]   addr        register address
82
 * @param[in]   data        data to write
83
 * @param[in]   num         number of subsequent registers to read
84
 * @param[in]   timeout     timeout
85
 * @return                  An indicator whether the call was successfull
86
 */
87 21076167 Thomas Schöpping
apalExitStatus_t ina219_lld_write_register(const INA219Driver* const ina219, const ina219_lld_register_t addr, const uint16_t* const data, const uint8_t num, const apalTime_t timeout)
88 d6728c5b Thomas Schöpping
{
89
  apalDbgAssert(ina219 != NULL);
90
  apalDbgAssert(ina219->i2cd != NULL);
91
  apalDbgAssert(data != NULL);
92
93
  uint8_t buffer[1+2*num];
94
  buffer[0] = addr;
95
  for (uint8_t dataIdx = 0; dataIdx < num; dataIdx++) {
96
    buffer[dataIdx*2+1] = data[dataIdx] >> 8;
97
    buffer[dataIdx*2+2] = data[dataIdx] & (0x00FFu);
98
  }
99
  return apalI2CMasterTransmit(ina219->i2cd, (INA219_LLD_I2C_ADDR_FIXED | ina219->addr), buffer, 1+2*num, NULL, 0, timeout);
100
}
101
102
/**
103
 * @brief Calibrate the ina219.
104
 * @param[in]   i2cd        i2c driver
105
 * @param[in]   inad        APAL_STATUS_SUCCESS;
106
 * @param[in]   calib_in    calibration input data
107
 * @param[out]  calib_out   output of the calibration
108
 * @param[in]   timeout     timeout
109
 * @return                  An indicator whether the call was successfull
110
 */
111 21076167 Thomas Schöpping
apalExitStatus_t ina219_lld_calibration(INA219Driver* const ina219, const ina219_lld_calib_input_t* const calib_in, ina219_lld_calib_output_t* const calib_out)
112 d6728c5b Thomas Schöpping
{
113
  apalDbgAssert(ina219 != NULL);
114
  apalDbgAssert(calib_in != NULL);
115
  apalDbgAssert(calib_out != NULL);
116
117
  uint16_t current_lsb_uA = calib_in->current_lsb_uA;
118
  if (current_lsb_uA < calib_in->max_expected_current_A / 0.032768f) {
119
    current_lsb_uA = calib_in->max_expected_current_A / 0.032768f;
120
  } else if (current_lsb_uA > calib_in->max_expected_current_A / 0.004096f) {
121
    current_lsb_uA = calib_in->max_expected_current_A / 0.004096f;
122
  }
123
124
  uint16_t calib_value = (uint16_t) (40960 / (current_lsb_uA * calib_in->shunt_resistance_0));
125
126
  float V_shunt_max;
127
  switch (calib_in->cfg_reg.options.gain) {
128
    case INA219_LLD_GAIN_1_40mV:
129
        V_shunt_max = 0.04f;
130
        break;
131
    case INA219_LLD_GAIN_2_80mV:
132
        V_shunt_max = 0.08f;
133
        break;
134
    case INA219_LLD_GAIN_4_160mV:
135
        V_shunt_max = 0.16f;
136
        break;
137
    case INA219_LLD_GAIN_8_320mV:
138
        V_shunt_max = 0.32f;
139
        break;
140
  }
141
142
  calib_out->max_current_before_overflow_A = (current_lsb_uA * 0.032767f >= V_shunt_max /calib_in->shunt_resistance_0) ?
143
                                                V_shunt_max / calib_in->shunt_resistance_0 :
144
                                                current_lsb_uA * 0.032767f;
145
  calib_out->max_shunt_voltage_before_overflow_V =
146
                                ((calib_out->max_current_before_overflow_A * calib_in->shunt_resistance_0) >= V_shunt_max) ?
147
                                                   V_shunt_max :
148
                                                   calib_out->max_current_before_overflow_A * calib_in->shunt_resistance_0;
149
150
  calib_out->current_lsb_uA = current_lsb_uA;
151
  calib_out->calibration = calib_value;
152
153
  ina219->current_lsb_uA = current_lsb_uA;
154
155
  return APAL_STATUS_SUCCESS;
156
}
157
158
/**
159
 * @brief Read the current configuration.
160
 * @param[in]   i2cd        i2c driver
161
 * @param[in]   inad        ina219 driver
162
 * @param[out]  cfg         current configuration
163
 * @param[in]   timeout     timeout
164
 * @return                  An indicator whether the call was successfull
165
 */
166 21076167 Thomas Schöpping
apalExitStatus_t ina219_lld_read_config(const INA219Driver* const ina219, ina219_lld_cfg_t* const cfg, const apalTime_t timeout)
167 d6728c5b Thomas Schöpping
{
168
  apalDbgAssert(ina219 != NULL);
169
  apalDbgAssert(cfg != NULL);
170
171
  return ina219_lld_read_register(ina219, INA219_LLD_REGISTER_CONFIGURATION, &cfg->data, 1, timeout);
172
}
173
174
/**
175
 * @brief Write a new configuration.
176
 * @param[in]   i2cd        i2c driver
177
 * @param[in]   inad        ina219 driver
178
 * @param[in]   cfg         new configuration
179
 * @param[in]   timeout     timeout
180
 * @return                  An indicator whether the call was successfull
181
 */
182 21076167 Thomas Schöpping
apalExitStatus_t ina219_lld_write_config(const INA219Driver* const ina219, ina219_lld_cfg_t cfg, const apalTime_t timeout)
183 d6728c5b Thomas Schöpping
{
184
  apalDbgAssert(ina219 != NULL);
185
186
  return ina219_lld_write_register(ina219, INA219_LLD_REGISTER_CONFIGURATION, &cfg.data, 1, timeout);
187
}
188
189
/**
190
 * @brief Read the current calibration value.
191
 * @param[in]   i2cd        i2c driver
192
 * @param[in]   inad        ina219 driver
193
 * @param[out]  calib       current calibration value
194
 * @param[in]   timeout     timeout
195
 * @return                  An indicator whether the call was successfull
196
 */
197 21076167 Thomas Schöpping
apalExitStatus_t ina219_lld_read_calibration(const INA219Driver* const ina219, uint16_t* const calib, const apalTime_t timeout)
198 d6728c5b Thomas Schöpping
{
199
  apalDbgAssert(ina219 != NULL);
200
  apalDbgAssert(calib != NULL);
201
202
  return ina219_lld_read_register(ina219, INA219_LLD_REGISTER_CALIBRATION, calib, 1, timeout);
203
}
204
205
/**
206
 * @brief Write a new calibration value.
207
 * @param[in]   i2cd        i2c driver
208
 * @param[in]   inad        ina219 driver
209
 * @param[in]   calib       new calibration value
210
 * @param[in]   timeout     timeout
211
 * @return                  An indicator whether the call was successfull
212
 */
213 21076167 Thomas Schöpping
apalExitStatus_t ina219_lld_write_calibration(const INA219Driver* const ina219, const uint16_t calib, const apalTime_t timeout)
214 d6728c5b Thomas Schöpping
{
215
  apalDbgAssert(ina219 != NULL);
216
217
  return ina219_lld_write_register(ina219, INA219_LLD_REGISTER_CALIBRATION, &calib, 1, timeout);
218
}
219
220
/**
221
 * @brief Reset the ina219.
222
 * @param[in]   i2cd        i2c driver
223
 * @param[in]   inad        ina219 driver
224
 * @param[in]   timeout     timeout
225
 * @return                  An indicator whether the call was successfull
226
 */
227 21076167 Thomas Schöpping
apalExitStatus_t ina219_lld_reset(const INA219Driver* const ina219, const apalTime_t timeout)
228 d6728c5b Thomas Schöpping
{
229
  apalDbgAssert(ina219 != NULL);
230
231
  uint16_t data = 0x8000;
232
  return ina219_lld_write_register(ina219, INA219_LLD_REGISTER_CONFIGURATION, &data, 1, timeout);
233
}
234
235
/**
236
 * @brief Read the current shunt voltage (uV).
237
 * @param[in]   i2cd        i2c driver
238
 * @param[in]   inad        ina219 driver
239
 * @param[out]  data        shunt voltage
240
 * @param[in]   timeout     timeout
241
 * @return                  An indicator whether the call was successfull
242
 */
243 21076167 Thomas Schöpping
apalExitStatus_t ina219_lld_read_shunt_voltage(const INA219Driver* const ina219, int32_t* const data, const apalTime_t timeout)
244 d6728c5b Thomas Schöpping
{
245
  apalDbgAssert(ina219 != NULL);
246
  apalDbgAssert(data != NULL);
247
248
  uint16_t buffer = 0;
249
  apalExitStatus_t status = ina219_lld_read_register(ina219, INA219_LLD_REGISTER_SHUNT_VOLTAGE, &buffer, 1, timeout);
250
251
  switch (ina219->config->options.gain) {
252
    case INA219_LLD_GAIN_8_320mV:
253
      *data = (int32_t)(buffer & 0x7FFFu) * ((buffer & 0x8000u) ? -10 : 10);
254
      break;
255
    case INA219_LLD_GAIN_4_160mV:
256
      *data = (int32_t)(buffer & 0x3FFFu) * ((buffer & 0xC000u) ? -10 : 10);
257
      break;
258
    case INA219_LLD_GAIN_2_80mV:
259
      *data = (int32_t)(buffer & 0x1FFFu) * ((buffer & 0xE000u) ? -10 : 10);
260
      break;
261
    case INA219_LLD_GAIN_1_40mV:
262
      *data = (int32_t)(buffer & 0x0FFFu) * ((buffer & 0xF000u) ? -10 : 10);
263
      break;
264
  }
265
266
  return status;
267
}
268
269
/**
270
 * @brief Read the current bus voltage (uV).
271
 * @param[in]   i2cd        i2c driver
272
 * @param[in]   inad        ina219 driver
273
 * @param[out]  data        bus voltage
274
 * @param[in]   timeout     timeout
275
 * @return                  An indicator whether the call was successfull
276
 */
277 21076167 Thomas Schöpping
apalExitStatus_t ina219_lld_read_bus_voltage(const INA219Driver* const ina219, uint32_t* const data, const apalTime_t timeout)
278 d6728c5b Thomas Schöpping
{
279
  apalDbgAssert(ina219 != NULL);
280
  apalDbgAssert(data != NULL);
281
282
  uint16_t buffer = 0;
283
  apalExitStatus_t status = ina219_lld_read_register(ina219, INA219_LLD_REGISTER_BUS_VOLTAGE, &buffer, 1, timeout);
284
  if (buffer & 0x01) {
285
    status = APAL_STATUS_ERROR;
286
  }
287
  *data = (uint32_t)(buffer >> 3) * 4000;
288
  return status;
289
}
290
291
/**
292
 * @brief Read the power (uW).
293
 * @param[in]   i2cd        i2c driver
294
 * @param[in]   inad        ina219 driver
295
 * @param[out]  data        power
296
 * @param[in]   timeout     timeout
297
 * @return                  An indicator whether the call was successfull
298
 */
299 21076167 Thomas Schöpping
apalExitStatus_t ina219_lld_read_power(const INA219Driver* const ina219, uint32_t* const data, const apalTime_t timeout)
300 d6728c5b Thomas Schöpping
{
301
  apalDbgAssert(ina219 != NULL);
302
  apalDbgAssert(data != NULL);
303
304
  uint16_t buffer = 0;
305
  apalExitStatus_t status = ina219_lld_read_register(ina219, INA219_LLD_REGISTER_POWER, &buffer, 1, timeout);
306
  *data = (uint32_t)buffer * 20 * ina219->current_lsb_uA;
307
  return status;
308
}
309
310
/**
311
 * @brief Read the current (uA).
312
 * @param[in]   i2cd        i2c driver
313
 * @param[in]   inad        ina219 driver
314
 * @param[out]  data        current
315
 * @param[in]   timeout     timeout
316
 * @return                  An indicator whether the call was successfull
317
 */
318 21076167 Thomas Schöpping
apalExitStatus_t ina219_lld_read_current(const INA219Driver* const ina219, int16_t* const data, const apalTime_t timeout)
319 d6728c5b Thomas Schöpping
{
320
  apalDbgAssert(ina219 != NULL);
321
  apalDbgAssert(data != NULL);
322
323
  uint16_t buffer = 0;
324
  apalExitStatus_t status = ina219_lld_read_register(ina219, INA219_LLD_REGISTER_CURRENT, &buffer, 1, timeout);
325
  *data = ((int16_t) buffer) * ina219->current_lsb_uA;
326
  return status;
327
}
328
329
/**
330
 * @brief Read the bus conversion ready flag.
331
 * @param[in]   i2cd        i2c driver
332
 * @param[in]   inad        ina219 driver
333
 * @param[out]  buscnv      conversion ready flag
334
 * @param[in]   timeout     timeout
335
 * @return                  An indicator whether the call was successfull
336
 */
337 21076167 Thomas Schöpping
apalExitStatus_t ina219_lld_bus_conversion_ready(const INA219Driver* const ina219, uint16_t* const buscnv, const apalTime_t timeout)
338 d6728c5b Thomas Schöpping
{
339
  apalDbgAssert(ina219 != NULL);
340
  apalDbgAssert(buscnv != NULL);
341
342
  apalExitStatus_t status = ina219_lld_read_register(ina219, INA219_LLD_REGISTER_BUS_VOLTAGE, buscnv, 1, timeout);
343
  *buscnv >>= 1;
344
  *buscnv &= 1;
345
  return status;
346
}
347
348 5e2f673b Marc Rothmann
/** @} */