-
Notifications
You must be signed in to change notification settings - Fork 2
Expand file tree
/
Copy pathBQ76952.hpp
More file actions
295 lines (258 loc) · 9.33 KB
/
Copy pathBQ76952.hpp
File metadata and controls
295 lines (258 loc) · 9.33 KB
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
#pragma once
#include <EVT/io/I2C.hpp>
#include <EVT/io/GPIO.hpp>
#include <BMSInfo.hpp>
#include <BQSetting.hpp>
#include <co_obj.h>
namespace BMS::DEV {
/**
* Represents the functionality of the BQ76952. This is a layer of abstraction
* which handles the I2C communication between the host and the BQ chip.
*
* Part of the logic contained is the ability to write out BQ settings to the
* BQ chip itself. This will be able to handle taking in settings and making
* the corresponding I2C commands to write out the settings.
* TI Technical Reference Manual: https://www.ti.com/lit/ug/sluuby2b/sluuby2b.pdf
*/
class BQ76952 {
public:
/**
* The number of cells connected to the BQ chip
*/
static constexpr uint8_t NUM_CELLS = 12;
/**
* Represents the status of operation of the BQ76952
*
* This can be used to represent the state of the BQ76952 or the
* result of a BQ76952 operation.
*/
enum class Status {
/** Operation took place successfully */
OK = 0x00,
/** Timeout waiting for an operation */
TIMEOUT = 0x10,
/** Failed at the I2C level to communicate with the BQ */
I2C_ERROR = 0x20,
/** Failed the specific BQ operation (not I2C related) */
ERROR = 0x40,
};
/**
* Create a new instance of the BQ76952 which will communicate over the
* given I2C bus with the given address
*
* @param[in] i2c I2C interface to use to communicate on the bus
* @param[in] i2cAddress The address of the BQ76952 to use
* @param[in] resetPin GPIO instance to reset the BQ
*/
BQ76952(EVT::core::IO::I2C& i2c, uint8_t i2cAddress, EVT::core::IO::GPIO& resetPin);
/**
* Write out the given setting
*
* @param[in] setting The BQ setting to write out
*/
Status writeSetting(BQSetting& setting);
/**
* Enter CONFIG_UPDATE mode
*
* This is the mode that the BQ chip should be in whenever modifying
* settings. If settings are modified, and the BQ is not in CONFIG_UPDATE
* mode, the results are unpredictable. For more information, see Section
* 7.6 of the BQ76952 Technical Reference Manual.
*
* @return The result of attempting to enter config update mode
*/
Status enterConfigUpdateMode();
/**
* Exit CONFIG_UPDATE mode
*
* @return The result of attempting to exit config update mode
*/
Status exitConfigUpdateMode();
/**
* Execute a direct read request
*
* @param[in] reg The I2C register address to read from
* @param[out] result The data that was read
* @return The status of the read request attempt
*/
Status makeDirectRead(uint8_t reg, uint16_t* result);
/**
* Execute a subcommand read request
*
* @param[in] reg The subcommand register address
* @param[out] result The result of the read request
* @return The status of the read request attempt
*/
Status makeSubcommandRead(uint16_t reg, uint32_t* result);
/**
* Run a subcommand that has no result
*
* @param[in] reg The subcommand register address
* @return The status of the subcommand attempt
*/
BQ76952::Status commandOnlySubcommand(uint16_t reg);
/**
* Execute RAM read request
*
* @param[in] reg The RAM register to read from
* @param[out] result The data that was read
* @return The status of the read request
*/
Status makeRAMRead(uint16_t reg, uint32_t* result);
/**
* Execute a direct command write
*
* This involves writing out at most 16 bits to a register.
*
* @param[in] reg The I2C register address to write to
* @param[in] data The data to write out
* @return The status of the write request attempt
*/
Status makeDirectWrite(uint8_t reg, uint16_t data);
/**
* Write out a subcommand settings
*
* Subcommands take in a 16-bit address which is written out to I2C
* registers 0x3E and 0x3F in little endian. Data associated with the
* command is written into 0x40-0x44, also in little endian.
*
* @param[in] setting The setting to write out
* @return The result of the setting write attempt
* Status::I2C_ERROR => Failed to communicate with the BQ
* Status::ERROR => Setting not accepted by BQ
* Status::OK => Successfully wrote out the setting
*/
Status writeRAMSetting(BQSetting& setting);
/**
* Check to see if the BQ chip is in configure mode
*
* Configure mode is a state where the BQ chip is able to handle making
* settings changes. This mode is discussed in detail in the BQ datasheet.
*
* @param[out] result Populated with true if the BQ chip is in config mode
* @return The status of attempting to get the current mode
* Status::I2C_ERROR => Failed to communicate with the BQ
* Status::ERROR => BQ encountered an error attempting to read
* Status::OK => Configure mode state read successfully
*/
Status inConfigMode(bool* result);
/**
* Attempt to see if the BQ chip can be communicated with
*
* This will read the ID of the BQ chip, and verify it matches the
* expected value.
*
* @return Status::OK on success, Status::ERROR otherwise
*/
Status communicationStatus();
/**
* Fill a buffer with each cell voltage
*
* @param[out] cellVoltages The buffer to fill with the cell voltage, must
* be NUM_CELLS in size
* @param[out] sum The total voltage across all cells
* @param[out] voltageInfo A struct containing the values below
* @return The status of the read attempt
*/
Status getCellVoltage(uint16_t cellVoltages[NUM_CELLS], uint32_t& sum, CellVoltageInfo& voltageInfo);
/**
* Determine the state of balancing on a given cell
*
* @param[in] targetCell The target cell to check the balancing of
* @param[out] balancing Updates to whether the cell is balancing
* @return The status of the read attempt
*/
Status isBalancing(uint8_t targetCell, bool* balancing);
/**
* Write out the balancing state to the target cell
*
* Writing a 1 enables balancing; writing a 0 disables balancing
*
* @param[in] targetCell The target cell to change the balance state of
* @param[in] enable 1 for enabling balancing 0 otherwise
* @return The status of the write attempt
*/
Status setBalancing(uint8_t targetCell, uint8_t enable);
/**
* Read the current running through pack
*
* @param[out] current Current running through the pack
* @return The status of the read attempt
*/
Status getCurrent(int16_t& current);
/**
* Read the total voltage of the pack
*
* @param[out] totalVoltage Total voltage of the pack
* @return The status of the read attempt
*/
Status getTotalVoltage(uint16_t& totalVoltage);
/**
* Read the temperature information measured by the BQ
*
* @param[out] bqTempInfo Temperature information measured by the BQ
* @return The status of the read attempt
*/
Status getTemps(BqTempInfo& bqTempInfo);
/**
* Read BQ status information
*
* @param[out] bqStatusArr BQ status information
* @return The status of the read attempt
*/
Status getBQStatus(uint8_t bqStatusArr[7]);
/**
* Reset the BQ
*/
void reset();
/** CANopen interface for probing the state of the balancing */
//CO_OBJ_TYPE balancingCANOpen;
private:
/** Used for commands and subcommands */
static constexpr uint8_t COMMAND_ADDR = 0x3E;
static constexpr uint8_t READ_BACK_ADDR = 0x40;
/** Keep track of various states of the BQ chip */
static constexpr uint8_t BATTERY_STATUS_ADDR = 0x12;
static constexpr uint8_t RAM_BASE_ADDR = 0x3E;
static constexpr uint8_t RAM_CHECKSUM_ADDR = 0x60;
/** Base address where the cell voltages are located */
static constexpr uint8_t CELL_VOLTAGE_BASE_ADDR = 0x14;
/** Addresses for controlling balancing */
static constexpr uint16_t BALANCING_CONFIG_ADDR = 0x9335;
static constexpr uint16_t ACTIVE_BALANCING_ADDR = 0x0083;
/** Used to enter and exit config mode */
static constexpr uint8_t ENTER_CONFIG[2] = {0x90, 0x00};
static constexpr uint8_t EXIT_CONFIG[2] = {0x92, 0x00};
/**
* Contains a mapping between the target cell and the corresponding
* location in the `CB_ACTIVE_CELLS` bitmap. The idea that each cell is
* an index into this lookup table.
* NOTE: Cells are numbered starting at 1, so to get the bit position
* for the first cell (cell 1) use index 0 (cell number - 1)
*/
static constexpr uint8_t CELL_BALANCE_MAPPING[] = {
0,
1,
2,
3,
4,
5,
6,
8,
10,
12,
14,
15,
};
/** Timeout waiting to read values from the BQ76952 in milliseconds */
static constexpr uint8_t TIMEOUT = 10;
/** The name of the BQ chip that should be stored in the BQ chip */
static constexpr uint16_t BQ_ID = 0x7695;
/** I2C bus to communicate over */
EVT::core::IO::I2C& i2c;
/** The address of the BQ on the I2C bus */
uint8_t i2cAddress;
/** Reset pin of the BQ */
EVT::core::IO::GPIO& resetPin;
};
}// namespace BMS::DEV