Statistics
| Branch: | Tag: | Revision:

amiro-lld / source / INA219 / v1 / alld_INA219_v1.c @ 7df78c60

History | View | Annotate | Download (13.259 KB)

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

5
This program is free software: you can redistribute it and/or modify
6
it under the terms of the GNU Lesser General Public License as published by
7
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
GNU Lesser General Public License for more details.
14

15
You should have received a copy of the GNU Lesser General Public License
16
along with this program.  If not, see <http://www.gnu.org/licenses/>.
17
*/
18

    
19
/**
20
 * @file    alld_INA219_v1.c
21
 * @brief   Power Monitor function implementations
22
 *
23
 * @addtogroup lld_power
24
 * @{
25
 */
26

    
27
#include <alld_INA219.h>
28

    
29
#if (defined(AMIROLLD_CFG_INA219) && (AMIROLLD_CFG_INA219 == 1)) || defined(__DOXYGEN__)
30

    
31
/******************************************************************************/
32
/* LOCAL DEFINITIONS                                                          */
33
/******************************************************************************/
34

    
35
/******************************************************************************/
36
/* EXPORTED VARIABLES                                                         */
37
/******************************************************************************/
38

    
39
/******************************************************************************/
40
/* LOCAL TYPES                                                                */
41
/******************************************************************************/
42

    
43
/******************************************************************************/
44
/* LOCAL VARIABLES                                                            */
45
/******************************************************************************/
46

    
47
/******************************************************************************/
48
/* LOCAL FUNCTIONS                                                            */
49
/******************************************************************************/
50

    
51
/******************************************************************************/
52
/* EXPORTED FUNCTIONS                                                         */
53
/******************************************************************************/
54

    
55
/**
56
 * @brief Read the value of one or more of the registers.
57
 * @param[in]   i2cd        i2c driver
58
 * @param[in]   inad        ina219 driver
59
 * @param[in]   addr        register address
60
 * @param[out]  data        register content
61
 * @param[in]   num         number of subsequent registers to read
62
 * @param[in]   timeout     timeout
63
 * @return                  An indicator whether the call was successfull
64
 */
65
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)
66
{
67
  apalDbgAssert(ina219 != NULL);
68
  apalDbgAssert(ina219->i2cd != NULL);
69
  apalDbgAssert(data != NULL);
70

    
71
  uint8_t buffer[num*2];
72
  apalExitStatus_t status = apalI2CMasterTransmit(ina219->i2cd, (INA219_LLD_I2C_ADDR_FIXED | ina219->addr), (uint8_t*)&addr, 1, buffer, 2*num, timeout);
73
  for (uint8_t dataIdx = 0; dataIdx < num; dataIdx++) {
74
    data[dataIdx] = (buffer[2*dataIdx] << 8) | buffer[2*dataIdx+1];
75
  }
76
  return status;
77
}
78

    
79
/**
80
 * @brief Write the value of one or more of the registers.
81
 * @param[in]   i2cd        i2c driver
82
 * @param[in]   inad        ina219 driver
83
 * @param[in]   addr        register address
84
 * @param[in]   data        data to write
85
 * @param[in]   num         number of subsequent registers to read
86
 * @param[in]   timeout     timeout
87
 * @return                  An indicator whether the call was successfull
88
 */
89
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)
90
{
91
  apalDbgAssert(ina219 != NULL);
92
  apalDbgAssert(ina219->i2cd != NULL);
93
  apalDbgAssert(data != NULL);
94

    
95
  uint8_t buffer[1+2*num];
96
  buffer[0] = addr;
97
  for (uint8_t dataIdx = 0; dataIdx < num; dataIdx++) {
98
    buffer[dataIdx*2+1] = data[dataIdx] >> 8;
99
    buffer[dataIdx*2+2] = data[dataIdx] & (0x00FFu);
100
  }
101
  return apalI2CMasterTransmit(ina219->i2cd, (INA219_LLD_I2C_ADDR_FIXED | ina219->addr), buffer, 1+2*num, NULL, 0, timeout);
102
}
103

    
104
/**
105
 * @brief Calibrate the ina219.
106
 * @param[in]   i2cd        i2c driver
107
 * @param[in]   inad        APAL_STATUS_SUCCESS;
108
 * @param[in]   calib_in    calibration input data
109
 * @param[out]  calib_out   output of the calibration
110
 * @param[in]   timeout     timeout
111
 * @return                  An indicator whether the call was successfull
112
 */
113
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)
114
{
115
  apalDbgAssert(ina219 != NULL);
116
  apalDbgAssert(calib_in != NULL);
117
  apalDbgAssert(calib_out != NULL);
118

    
119
  uint16_t current_lsb_uA = calib_in->current_lsb_uA;
120
  if (current_lsb_uA < calib_in->max_expected_current_A / 0.032768f) {
121
    current_lsb_uA = calib_in->max_expected_current_A / 0.032768f;
122
  } else if (current_lsb_uA > calib_in->max_expected_current_A / 0.004096f) {
123
    current_lsb_uA = calib_in->max_expected_current_A / 0.004096f;
124
  }
125

    
126
  uint16_t calib_value = (uint16_t) (40960 / (current_lsb_uA * calib_in->shunt_resistance_0));
127

    
128
  float V_shunt_max;
129
  switch (calib_in->cfg_reg.options.gain) {
130
    case INA219_LLD_GAIN_1_40mV:
131
        V_shunt_max = 0.04f;
132
        break;
133
    case INA219_LLD_GAIN_2_80mV:
134
        V_shunt_max = 0.08f;
135
        break;
136
    case INA219_LLD_GAIN_4_160mV:
137
        V_shunt_max = 0.16f;
138
        break;
139
    case INA219_LLD_GAIN_8_320mV:
140
        V_shunt_max = 0.32f;
141
        break;
142
  }
143

    
144
  calib_out->max_current_before_overflow_A = (current_lsb_uA * 0.032767f >= V_shunt_max /calib_in->shunt_resistance_0) ?
145
                                                V_shunt_max / calib_in->shunt_resistance_0 :
146
                                                current_lsb_uA * 0.032767f;
147
  calib_out->max_shunt_voltage_before_overflow_V =
148
                                ((calib_out->max_current_before_overflow_A * calib_in->shunt_resistance_0) >= V_shunt_max) ?
149
                                                   V_shunt_max :
150
                                                   calib_out->max_current_before_overflow_A * calib_in->shunt_resistance_0;
151

    
152
  calib_out->current_lsb_uA = current_lsb_uA;
153
  calib_out->calibration = calib_value;
154

    
155
  ina219->current_lsb_uA = current_lsb_uA;
156

    
157
  return APAL_STATUS_SUCCESS;
158
}
159

    
160
/**
161
 * @brief Read the current configuration.
162
 * @param[in]   i2cd        i2c driver
163
 * @param[in]   inad        ina219 driver
164
 * @param[out]  cfg         current configuration
165
 * @param[in]   timeout     timeout
166
 * @return                  An indicator whether the call was successfull
167
 */
168
apalExitStatus_t ina219_lld_read_config(const INA219Driver* const ina219, ina219_lld_cfg_t* const cfg, const apalTime_t timeout)
169
{
170
  apalDbgAssert(ina219 != NULL);
171
  apalDbgAssert(cfg != NULL);
172

    
173
  return ina219_lld_read_register(ina219, INA219_LLD_REGISTER_CONFIGURATION, &cfg->data, 1, timeout);
174
}
175

    
176
/**
177
 * @brief Write a new configuration.
178
 * @param[in]   i2cd        i2c driver
179
 * @param[in]   inad        ina219 driver
180
 * @param[in]   cfg         new configuration
181
 * @param[in]   timeout     timeout
182
 * @return                  An indicator whether the call was successfull
183
 */
184
apalExitStatus_t ina219_lld_write_config(const INA219Driver* const ina219, ina219_lld_cfg_t cfg, const apalTime_t timeout)
185
{
186
  apalDbgAssert(ina219 != NULL);
187

    
188
  return ina219_lld_write_register(ina219, INA219_LLD_REGISTER_CONFIGURATION, &cfg.data, 1, timeout);
189
}
190

    
191
/**
192
 * @brief Read the current calibration value.
193
 * @param[in]   i2cd        i2c driver
194
 * @param[in]   inad        ina219 driver
195
 * @param[out]  calib       current calibration value
196
 * @param[in]   timeout     timeout
197
 * @return                  An indicator whether the call was successfull
198
 */
199
apalExitStatus_t ina219_lld_read_calibration(const INA219Driver* const ina219, uint16_t* const calib, const apalTime_t timeout)
200
{
201
  apalDbgAssert(ina219 != NULL);
202
  apalDbgAssert(calib != NULL);
203

    
204
  return ina219_lld_read_register(ina219, INA219_LLD_REGISTER_CALIBRATION, calib, 1, timeout);
205
}
206

    
207
/**
208
 * @brief Write a new calibration value.
209
 * @param[in]   i2cd        i2c driver
210
 * @param[in]   inad        ina219 driver
211
 * @param[in]   calib       new calibration value
212
 * @param[in]   timeout     timeout
213
 * @return                  An indicator whether the call was successfull
214
 */
215
apalExitStatus_t ina219_lld_write_calibration(const INA219Driver* const ina219, const uint16_t calib, const apalTime_t timeout)
216
{
217
  apalDbgAssert(ina219 != NULL);
218

    
219
  return ina219_lld_write_register(ina219, INA219_LLD_REGISTER_CALIBRATION, &calib, 1, timeout);
220
}
221

    
222
/**
223
 * @brief Reset the ina219.
224
 * @param[in]   i2cd        i2c driver
225
 * @param[in]   inad        ina219 driver
226
 * @param[in]   timeout     timeout
227
 * @return                  An indicator whether the call was successfull
228
 */
229
apalExitStatus_t ina219_lld_reset(const INA219Driver* const ina219, const apalTime_t timeout)
230
{
231
  apalDbgAssert(ina219 != NULL);
232

    
233
  uint16_t data = 0x8000;
234
  return ina219_lld_write_register(ina219, INA219_LLD_REGISTER_CONFIGURATION, &data, 1, timeout);
235
}
236

    
237
/**
238
 * @brief Read the current shunt voltage (uV).
239
 * @param[in]   i2cd        i2c driver
240
 * @param[in]   inad        ina219 driver
241
 * @param[out]  data        shunt voltage
242
 * @param[in]   timeout     timeout
243
 * @return                  An indicator whether the call was successfull
244
 */
245
apalExitStatus_t ina219_lld_read_shunt_voltage(const INA219Driver* const ina219, int32_t* const data, const apalTime_t timeout)
246
{
247
  apalDbgAssert(ina219 != NULL);
248
  apalDbgAssert(data != NULL);
249

    
250
  uint16_t buffer = 0;
251
  apalExitStatus_t status = ina219_lld_read_register(ina219, INA219_LLD_REGISTER_SHUNT_VOLTAGE, &buffer, 1, timeout);
252

    
253
  switch (ina219->config->options.gain) {
254
    case INA219_LLD_GAIN_8_320mV:
255
      *data = (int32_t)(buffer & 0x7FFFu) * ((buffer & 0x8000u) ? -10 : 10);
256
      break;
257
    case INA219_LLD_GAIN_4_160mV:
258
      *data = (int32_t)(buffer & 0x3FFFu) * ((buffer & 0xC000u) ? -10 : 10);
259
      break;
260
    case INA219_LLD_GAIN_2_80mV:
261
      *data = (int32_t)(buffer & 0x1FFFu) * ((buffer & 0xE000u) ? -10 : 10);
262
      break;
263
    case INA219_LLD_GAIN_1_40mV:
264
      *data = (int32_t)(buffer & 0x0FFFu) * ((buffer & 0xF000u) ? -10 : 10);
265
      break;
266
  }
267

    
268
  return status;
269
}
270

    
271
/**
272
 * @brief Read the current bus voltage (uV).
273
 * @param[in]   i2cd        i2c driver
274
 * @param[in]   inad        ina219 driver
275
 * @param[out]  data        bus voltage
276
 * @param[in]   timeout     timeout
277
 * @return                  An indicator whether the call was successfull
278
 */
279
apalExitStatus_t ina219_lld_read_bus_voltage(const INA219Driver* const ina219, uint32_t* const data, const apalTime_t timeout)
280
{
281
  apalDbgAssert(ina219 != NULL);
282
  apalDbgAssert(data != NULL);
283

    
284
  uint16_t buffer = 0;
285
  apalExitStatus_t status = ina219_lld_read_register(ina219, INA219_LLD_REGISTER_BUS_VOLTAGE, &buffer, 1, timeout);
286
  if (buffer & 0x01) {
287
    status = APAL_STATUS_ERROR;
288
  }
289
  *data = (uint32_t)(buffer >> 3) * 4000;
290
  return status;
291
}
292

    
293
/**
294
 * @brief Read the power (uW).
295
 * @param[in]   i2cd        i2c driver
296
 * @param[in]   inad        ina219 driver
297
 * @param[out]  data        power
298
 * @param[in]   timeout     timeout
299
 * @return                  An indicator whether the call was successfull
300
 */
301
apalExitStatus_t ina219_lld_read_power(const INA219Driver* const ina219, uint32_t* const data, const apalTime_t timeout)
302
{
303
  apalDbgAssert(ina219 != NULL);
304
  apalDbgAssert(data != NULL);
305

    
306
  uint16_t buffer = 0;
307
  apalExitStatus_t status = ina219_lld_read_register(ina219, INA219_LLD_REGISTER_POWER, &buffer, 1, timeout);
308
  *data = (uint32_t)buffer * 20 * ina219->current_lsb_uA;
309
  return status;
310
}
311

    
312
/**
313
 * @brief Read the current (uA).
314
 * @param[in]   i2cd        i2c driver
315
 * @param[in]   inad        ina219 driver
316
 * @param[out]  data        current
317
 * @param[in]   timeout     timeout
318
 * @return                  An indicator whether the call was successfull
319
 */
320
apalExitStatus_t ina219_lld_read_current(const INA219Driver* const ina219, int16_t* const data, const apalTime_t timeout)
321
{
322
  apalDbgAssert(ina219 != NULL);
323
  apalDbgAssert(data != NULL);
324

    
325
  uint16_t buffer = 0;
326
  apalExitStatus_t status = ina219_lld_read_register(ina219, INA219_LLD_REGISTER_CURRENT, &buffer, 1, timeout);
327
  *data = ((int16_t) buffer) * ina219->current_lsb_uA;
328
  return status;
329
}
330

    
331
/**
332
 * @brief Read the bus conversion ready flag.
333
 * @param[in]   i2cd        i2c driver
334
 * @param[in]   inad        ina219 driver
335
 * @param[out]  buscnv      conversion ready flag
336
 * @param[in]   timeout     timeout
337
 * @return                  An indicator whether the call was successfull
338
 */
339
apalExitStatus_t ina219_lld_bus_conversion_ready(const INA219Driver* const ina219, uint16_t* const buscnv, const apalTime_t timeout)
340
{
341
  apalDbgAssert(ina219 != NULL);
342
  apalDbgAssert(buscnv != NULL);
343

    
344
  apalExitStatus_t status = ina219_lld_read_register(ina219, INA219_LLD_REGISTER_BUS_VOLTAGE, buscnv, 1, timeout);
345
  *buscnv >>= 1;
346
  *buscnv &= 1;
347
  return status;
348
}
349

    
350
#endif /* defined(AMIROLLD_CFG_INA219) && (AMIROLLD_CFG_INA219 == 1) */
351

    
352
/** @} */