-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathBQ34Z100.h
573 lines (506 loc) · 16.7 KB
/
BQ34Z100.h
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
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
486
487
488
489
490
491
492
493
494
495
496
497
498
499
500
501
502
503
504
505
506
507
508
509
510
511
512
513
514
515
516
517
518
519
520
521
522
523
524
525
526
527
528
529
530
531
532
533
534
535
536
537
538
539
540
541
542
543
544
545
546
547
548
549
550
551
552
553
554
555
556
557
558
559
560
561
562
563
564
565
566
567
568
569
570
571
572
573
/**
* @file BQ34Z100.h
* @author Kyle Marino, Jamie Smith, Tyler Sehon
* @brief Software Driver for BQ34Z100-G1 Battery Gauge
*
* Datasheet: http://www.ti.com/lit/ds/symlink/bq34z100-g1.pdf
*
* Existing arduino code to reference from unknown author: https://github.com/Ralim/BQ34Z100
* Partial library from TI that may be useful: http://www.ti.com/lit/an/slua801/slua801.pdf
* Battery information: https://www.batteryspace.com/polymerli-ioncell37v1400mah703562-10c518wh10adrainrate-ullisted.aspx
*/
#ifndef BQ34Z100_H
#define BQ34Z100_H
#include <mbed.h>
#include <cstdint>
/**
* @name Definitions
* @{
*/
#define GAUGE_ADDRESS 0xAA
/**
* @name Battery configuration settings
* @note Run flashSettings() then reset the sensor to save the settings.
* @{
*/
#define DESIGNCAP 1400 /** mAh, per cell (Page 48, offset 11) */
#define DESIGNENERGY 5180 /** mWh, per cell (Page 48, offset 14) */
#define CELLCOUNT 0x04 /** number of series cells (Page 65, offset 7) */
#define LEDCONFIG 0x4b /** 5-LED Expander with I2C host comm (Page 64, offset 5) */
#define VOLTSEL true /** Switches to an external battery voltage divider */
#define ZEROCHARGEVOLT 3375 /** mV, charge cut-off voltage/Cell terminate voltages */
#define FLASH_UPDATE_OK_VOLT 2800 /** mV, below this voltage per cell flash writes will not go through */
#define QMAX0 1400 /** mAh, datasheet says to use c-rate current */
/**
* @}
*/
/**
* @brief Voltage Divider Gain
*
* The voltage divider works by this formula: Gain = (TOP_LEG_R / BOTTOM_LEG_R) * 1000
*
* Top leg resistance (TOP LEG R): 294Kohm
* Bottom leg resistance (BOTTOM LEG R): 16.5Kohm
*
* This only works if you enable the external voltage divider (VOLTSEL) option for the sensor
* Note: requires calibration after setting in flash
*/
#define VOLTAGEGAIN 17818
#define LOADSELECT 0x01 /** "Load Select defines the type of power or current model to be used to compute load-compensated capacity in the Impedance Track algorithm" */
#define LOADMODE 0x00 /** "Load Mode is used to select either the constant current or constant power model for the Impedance Track algorithm" */
/**
* @brief Reset Voltage
*
* Voltage (in mV) to reset to after unsuccessful voltage calibration
* Recommended value is 1.5x the current battery voltage
*/
#define RESETVOLTAGE 22200
/**
* @brief Sense Resistor value
*
* mOhms, value of guage sense resistor
*/
#define SENSE_RES 15.0f
/**
* @brief External Thermistor Enable
*
* If 1, use an external thermistor connected to the IT pin.
* If 0, use the internal temp sensor.
*/
#define USE_EXTERNAL_THERMISTOR 0
/**
* @}
*/
/**
* @brief The BQ34Z100 Driver
*
* Reads the current state of the main battery, can determine charge
* remaining inside as well as read instantaneous voltage, current, or temperature.
*/
class BQ34Z100
{
public:
/**
* @brief Create an GQ34Z100-G1 object connected to the I2C object
*
* @param i2c Reference to the i2c bus used
* @param hz The I2C bus frequency (400kHz acc. to datasheet).
*/
BQ34Z100(I2C& i2c, int hz = 400000);
/**
* @brief Returns the status of key features
*
* Instructs the fuel gauge to return status information to Control addresses 0x00/0x01.
*/
uint16_t getStatus();
/**
* @brief Toggle CALIBRATION mode enable
*
* @note Use before enterCal or exitCal()
*
* Instructs the fuel gauge to enable entry and exit to CALIBRATION mode.
*/
void enableCal();
/**
* @brief Enters CALIBRATION mode
*/
void enterCal();
/**
* @brief Exits CALIBRATION mode
*/
void exitCal();
/**
* @brief Enables the Impedance Track algorithm
*
* This algorithm uses voltage measurements, characteristics, and properties to create
* state of charge (SOC) predictions.
*/
void ITEnable();
/**
* @brief Gets the state of charge (SOC) of the battery.
*
* @return Predicted remaining battery capacity as a percentage of total capacity.
*/
uint8_t getSOC();
/**
* @brief Returns the expected margin of error in the SOC calculation.
*
* @return Returns a percentage from 1% to 100%
*/
uint16_t getError();
/**
* @brief Gets the remaining battery capacity.
*
* @return The battery capacity remaining. Unit is 1 mAh per bit.
*/
uint16_t getRemaining();
/**
* @brief Returns the measured battery voltage.
*
* @return Battery voltage in mV in the range 0 to 65535.
*/
uint16_t getVoltage();
/**
* @brief Gets the current flow through the sense resistor.
*
* Returns the average current flowing through the sense resistor
* @return Returns the average current.
*/
int16_t getCurrent();
/**
* @brief Gets the internal sensor temperature in Celcius.
*
* The device returns an internal temperature in units of 0.1K
* This function grabs the temperature in K and converts to Celcius
*
* @return Temperature in units of Celcius.
*/
double getTemperature();
/**
* @brief Returns the current ChemID
*
* Returns the ChemID configured inside the chip.
*
* @return ChemID as a hex number. e.g. programming ID 2109 would cause
* this function to return 8457 (0x2109).
*/
uint16_t getChemID();
/**
* @brief Returns a percentage ratio of prediced full charge capacity (FCC) over design capacity.
*
* Just as an old battery will not be able to charge fully to its design capacity,
* our battery may behave similarly.
*
* This sensor will tell us how "healthy" our battery is.
*
* @return Percentage ratio from 0 to 100 of predicted FCC over design capacity.
*/
uint16_t getStateOfHealth();
/**
* @brief Returns the pack serial number programmed in the data flash
*
* @return Serial number from the data flash.
*/
int getSerial();
/**
* @brief Perform a full reset.
*
* Instructs the fuel gauge to perform a full reset.
* This command is only available when the fuel gauge is UNSEALED.
*/
void reset();
/**
* @brief Unseals the device for DATA FLASH access.
*
* Unseals the device using the Control() command if the device is sealed.
* This is the first step in the sequence of steps required to read DATA FLASH.
*/
void unseal();
/**
* @brief Seals the device, prohibiting DATA FLASH access.
*
* Instructs the fuel gauge to transition from UNSEALED state to SEALED state.
* This blocks access to certain flash registers.
*/
void seal();
/**
* @name Data Flash functions
* @{
*/
/**
* @brief Changes to a different register in BlockData()
*
* @param subclass
* @param offset
*/
void changePage(char subclass, uint16_t offset);
/**
* @brief Updates the checksum
*
* Reads the checksum and updates it using the flashbytes array.
* Required by the sensor to save changes to the flash.
*/
void updateChecksum();
/**
* @brief Reads the blockData in the current page.
*
* Saves the read data to the flashbyte array.
*/
void readFlash();
/**
* @brief Writes to DATA FLASH.
*
* Writes new data, first to flashbytes array, then updates on the sensor as well
*
* @note Requires update of the checksum after changes are made
*
* @param index subclass ID (index)
* @param value offset
* @param len The length of the write.
*/
void writeFlash(uint8_t index, uint32_t value, int len);
/**
* @brief Returns the flashbytes array.
*
* The flashbytes array stores the last updated page in flash.
*
* @return Pointer to the flashbytes array.
*/
uint8_t* getFlashBytes();
/**
* @brief Update the Data page in the Data Flash.
*
* This reconfigures certain data parameters of the Data subclass within the Data Flash.
*
* The parameters configured in this method are:
* - the design capacity
* - the design energy
*/
void changePage48();
/**
* @brief Update the Registers page in the Data Flash.
*
* This reconfigures certain data parameters of the Registers subclass within the Data Flash.
*
* The parameters configured in this method are:
* - voltage divider enable
* - calibration enable
* - internal temperature sensor enable
* - number of cells in the battery
* - LED config mode
*/
void changePage64();
/**
* @brief Update the IT Cfg page in the Data Flash.
*
* This reconfigures certain data parameters of the IT Cfg subclass within the Data Flash.
*
* The parameters configured in this method are:
* - LOADSELECT
* - LOADMODE
* - ZEROCHARGEVOLT (cell terminate voltage)
*/
void changePage80();
/**
* @brief Update the State page in the Data Flash.
*
* This reconfigures certain data parameters of the State subclass within the Data Flash.
*
* The data parameters configured in this method are:
* - QMax Cell 0
*/
void changePage82();
/**
* @brief Calibrates the Voltage Divider register.
*
* @note Voltage divider changes seem to require a chip reset to take effect,
* so we must reset the chip between each calibration.
*
* @param currentVoltage The actual battery voltage in mV
* @return The voltage divider ratio written
*/
uint16_t calibrateVoltage(uint16_t currentVoltage);
/**
* @brief Reset the Voltage Divider object.
*
* If too much calibration is done, you may want to reset the Voltage Divider.
* This function sets the voltage divider register to RESETVOLTAGE.
*/
void resetVoltageDivider();
/**
* @brief Calibrate current shunt.
*
* Calibrate CCGain and CCOffset registers, which control current shunt
* and therefore affect the current and voltage readouts.
*
* @param calCurrent Calibration current input.
*/
void calibrateShunt(int16_t calCurrent);
/**
* @brief Set the Sense Resistor
*
* Calibrate shunt works to set the sense resistor as well, but
* requires an external current measurement.
*/
void setSenseResistor();
/**
* @brief Read the device type
*
* Device type should be 0x100 for the BQ34Z100.
*
* @return Device type
*/
uint16_t readDeviceType();
/**
* @brief Read the firmware version.
*
* @return Contents of the FW version register.
*/
uint16_t readFWVersion();
/**
* @brief Read the hardware version.
*
* @return Contents of the HW version register.
*/
uint16_t readHWVersion();
/**
* @brief Convert float value to a Xemics floating point.
*
* Documented in this app note: http://www.ti.com/lit/pdf/slva148
*
* @param value Float value
* @return Xemics floating point value
*/
static uint32_t floatToXemics(float value);
/**
* @brief Convert Xemics floating point to a float value.
*
* @param xemics Xemics floating point value
* @return Float value
*/
static float xemicsToFloat(uint32_t xemics);
/**
* @brief Read the Update Status register from flash.
*
* See datasheet section 7.3.6.10
*
* @return Status of the Impedance Track algorithm and learning process.
*/
uint8_t getUpdateStatus();
/**
* @brief Get the Gas Gauge Status Flags.
*
* Uses the Flags and FlagsB commands to get the contents of the Gas Gauge Status Register.
*
* @return Contents of the Gas Gauge Status register, depicting current operation status.
*/
std::pair<uint16_t, uint16_t> getFlags();
/**
* @}
*/
private:
/**
* @brief Top-level commands
*
* The first byte that you can send on an I2C transaction
*/
enum class Command : uint8_t
{
Control = 0x0,
StateOfCharge = 0x2,
MaxError = 0x3,
RemainingCapacity = 0x4,
FullChargeCapacity = 0x6,
Voltage = 0x8,
AverageCurrent = 0xA,
Temperature = 0xC,
Flags = 0xE,
Current = 0x10,
FlagsB = 0x12,
SerialNumber = 0x28,
InternalTemperature = 0x2A,
CycleCount = 0x2C,
StateOfHealth = 0x2E,
DataFlashClass = 0x3E,
DataFlashBlock = 0x3F,
BlockData = 0x40,
BlockDataCheckSum = 0x60,
BlockDataControl = 0x61
};
/**
* @brief Subcommands for the "Control" Command
*/
enum class Control : uint16_t
{
CONTROL_STATUS = 0x0,
DEVICE_TYPE = 0x1,
FW_VERSION = 0x02,
HW_VERSION = 0x03,
RESET_DATA = 0x5,
PREV_MACWRITE = 0x7,
CHEM_ID = 0x8,
BOARD_OFFSET = 0x9,
CC_OFFSET = 0xA,
CC_OFFSET_SAVE = 0xB,
DF_VERSION = 0xC,
SET_FULLSLEEP = 0x10,
STATIC_CHEM_CHECKSUM = 0x17,
SEALED = 0x20,
IT_ENABLE = 0x21,
CAL_ENABLE = 0x2D,
RESET = 0x41,
EXIT_CAL = 0x80,
ENTER_CAL = 0x81,
OFFSET_CAL = 0x82,
UNSEAL_KEY1 = 0x0414,
UNSEAL_KEY2 = 0x3672
};
/** @brief Reference to I2C interface */
I2C& _i2c;
/** @brief Current flash page that we have read */
uint8_t currFlashPage = 0;
/** @brief 32 bit block index into current flash page */
uint8_t currFlashBlockIndex = 0;
/** @brief Stores page in flash memory on Hamster */
uint8_t flashbytes[32];
/**
* @name I2C Commands
* @{
*/
/**
* @brief Sends a control command
*
* Issuing a Control() command requires a subsequent two-byte subcommand.
* These additional bytes specify the particular control function desired.
*
* This function writes two bytes with the LSB first.
* e.g. sending Control(0x0414) translates into WRITE 0x00 0x14 0x04, Command1 = 0x04, and Command2 = 0x14.
*
* @param control The control command to be sent.
*/
void sendControlCommand(Control control);
/**
* @brief Sends a control command and reads the result.
*
* Sends a Control() command then reads two bytes from the Control register (0x00)
*
* @param control The control command to be sent.
*
* @return the result of the control command
*/
uint16_t readControlCommand(Control control);
/**
* @brief Writes one byte over I2C to the device.
*
* Used to send commands.
*
* @param command command to send
* @param cmd byte of command
*/
void write(Command command, const uint8_t cmd);
/**
* @brief Writes two bytes over I2C to the device.
*
* Used to send two-byte subcommands.
* e.g. sending the start subcommand WRITE 01 00 to Register 00 requires write(0x00, 0x01, 0x00)
*
* @param command command to send
* @param cmd1 first byte of command
* @param cmd2 second byte of command
*/
void write(Command command, const uint8_t cmd1, const uint8_t cmd2);
/**
* @brief Reads over I2C from the device.
*
* @param command
* @param length number of bytes to read
* @return uint32_t
*/
uint32_t read(Command command, const uint8_t length);
/**
* @}
*/
/** @brief Calculate the checksum of the current flashbytes array */
uint8_t calcChecksum();
};
#endif