CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutSign UpSign In
Ardupilot

Real-time collaboration for Jupyter Notebooks, Linux Terminals, LaTeX, VS Code, R IDE, and more,
all in one place. Commercial Alternative to JupyterHub.

GitHub Repository: Ardupilot/ardupilot
Path: blob/master/libraries/AP_BattMonitor/AP_BattMonitor_SMBus_Generic.cpp
Views: 1798
1
#include "AP_BattMonitor_config.h"
2
3
#if AP_BATTERY_SMBUS_GENERIC_ENABLED
4
5
#include <AP_HAL/AP_HAL.h>
6
#include <AP_Common/AP_Common.h>
7
#include <AP_Math/AP_Math.h>
8
#include "AP_BattMonitor.h"
9
10
#include "AP_BattMonitor_SMBus_Generic.h"
11
12
uint8_t smbus_cell_ids[] = { 0x3f, // cell 1
13
0x3e, // cell 2
14
0x3d, // cell 3
15
0x3c, // cell 4
16
0x3b, // cell 5
17
0x3a, // cell 6
18
0x39, // cell 7
19
0x38, // cell 8
20
0x37, // cell 9
21
0x36, // cell 10
22
0x35, // cell 11
23
0x34, // cell 12
24
#if CONFIG_HAL_BOARD == HAL_BOARD_SITL
25
0x33, // cell 13
26
0x32 // cell 14
27
#endif
28
};
29
30
#define SMBUS_CELL_COUNT_CHECK_TIMEOUT 15 // check cell count for up to 15 seconds
31
32
/*
33
* Other potentially useful registers, listed here for future use
34
* #define BATTMONITOR_SMBUS_MAXELL_CHARGE_STATUS 0x0d // relative state of charge
35
* #define BATTMONITOR_SMBUS_MAXELL_BATTERY_STATUS 0x16 // battery status register including alarms
36
* #define BATTMONITOR_SMBUS_MAXELL_BATTERY_CYCLE_COUNT 0x17 // cycle count
37
* #define BATTMONITOR_SMBUS_MAXELL_DESIGN_VOLTAGE 0x19 // design voltage register
38
* #define BATTMONITOR_SMBUS_MAXELL_MANUFACTURE_DATE 0x1b // manufacturer date
39
* #define BATTMONITOR_SMBUS_MAXELL_SERIALNUM 0x1c // serial number register
40
* #define BATTMONITOR_SMBUS_MAXELL_HEALTH_STATUS 0x4f // state of health
41
* #define BATTMONITOR_SMBUS_MAXELL_SAFETY_ALERT 0x50 // safety alert
42
* #define BATTMONITOR_SMBUS_MAXELL_SAFETY_STATUS 0x51 // safety status
43
* #define BATTMONITOR_SMBUS_MAXELL_PF_ALERT 0x52 // safety status
44
* #define BATTMONITOR_SMBUS_MAXELL_PF_STATUS 0x53 // safety status
45
*/
46
47
// Constructor
48
AP_BattMonitor_SMBus_Generic::AP_BattMonitor_SMBus_Generic(AP_BattMonitor &mon,
49
AP_BattMonitor::BattMonitor_State &mon_state,
50
AP_BattMonitor_Params &params)
51
: AP_BattMonitor_SMBus(mon, mon_state, params, AP_BATTMONITOR_SMBUS_BUS_EXTERNAL)
52
{}
53
54
void AP_BattMonitor_SMBus_Generic::timer()
55
{
56
// check if PEC is supported
57
if (!check_pec_support()) {
58
return;
59
}
60
61
uint16_t data;
62
uint32_t tnow = AP_HAL::micros();
63
64
// read voltage (V)
65
if (read_word(BATTMONITOR_SMBUS_VOLTAGE, data)) {
66
_state.voltage = (float)data * 0.001f;
67
_state.last_time_micros = tnow;
68
_state.healthy = true;
69
}
70
71
// assert that BATTMONITOR_SMBUS_NUM_CELLS_MAX must be no more than smbus_cell_ids
72
static_assert(BATTMONITOR_SMBUS_NUM_CELLS_MAX <= ARRAY_SIZE(smbus_cell_ids), "BATTMONITOR_SMBUS_NUM_CELLS_MAX must be no more than smbus_cell_ids");
73
74
// check cell count
75
if (!_cell_count_fixed) {
76
if (_state.healthy) {
77
// when battery first becomes healthy, start check of cell count
78
if (_cell_count_check_start_us == 0) {
79
_cell_count_check_start_us = tnow;
80
}
81
if (tnow - _cell_count_check_start_us > (SMBUS_CELL_COUNT_CHECK_TIMEOUT * 1e6)) {
82
// give up checking cell count after 15sec of continuous healthy battery reads
83
_cell_count_fixed = true;
84
}
85
} else {
86
// if battery becomes unhealthy restart cell count check
87
_cell_count_check_start_us = 0;
88
}
89
}
90
91
// we loop over something limited by
92
// BATTMONITOR_SMBUS_NUM_CELLS_MAX but assign into something
93
// limited by AP_BATT_MONITOR_CELLS_MAX - so make sure we won't
94
// over-write:
95
static_assert(BATTMONITOR_SMBUS_NUM_CELLS_MAX <= ARRAY_SIZE(_state.cell_voltages.cells), "BATTMONITOR_SMBUS_NUM_CELLS_MAX must be <= number of cells in state voltages");
96
97
// read cell voltages
98
for (uint8_t i = 0; i < (_cell_count_fixed ? _cell_count : BATTMONITOR_SMBUS_NUM_CELLS_MAX); i++) {
99
if (read_word(smbus_cell_ids[i], data) && (data > 0) && (data < UINT16_MAX)) {
100
_has_cell_voltages = true;
101
_state.cell_voltages.cells[i] = data;
102
_last_cell_update_us[i] = tnow;
103
if (!_cell_count_fixed) {
104
_cell_count = MAX(_cell_count, i + 1);
105
}
106
} else if ((tnow - _last_cell_update_us[i]) > AP_BATTMONITOR_SMBUS_TIMEOUT_MICROS) {
107
_state.cell_voltages.cells[i] = UINT16_MAX;
108
}
109
}
110
111
// timeout after 5 seconds
112
if ((tnow - _state.last_time_micros) > AP_BATTMONITOR_SMBUS_TIMEOUT_MICROS) {
113
_state.healthy = false;
114
return;
115
}
116
117
// read current (A)
118
if (read_word(BATTMONITOR_SMBUS_CURRENT, data)) {
119
_state.current_amps = -(float)((int16_t)data) * 0.001f;
120
_state.last_time_micros = tnow;
121
}
122
123
read_full_charge_capacity();
124
125
// FIXME: Perform current integration if the remaining capacity can't be requested
126
read_remaining_capacity();
127
128
read_temp();
129
130
read_serial_number();
131
132
read_cycle_count();
133
}
134
135
// check if PEC supported with the version value in SpecificationInfo() function
136
// returns true once PEC is confirmed as working or not working
137
bool AP_BattMonitor_SMBus_Generic::check_pec_support()
138
{
139
// exit immediately if we have already confirmed pec support
140
if (_pec_confirmed) {
141
return true;
142
}
143
144
// specification info
145
uint16_t data;
146
if (!read_word(BATTMONITOR_SMBUS_SPECIFICATION_INFO, data)) {
147
return false;
148
}
149
150
// extract version
151
uint8_t version = (data & 0xF0) >> 4;
152
153
// version less than 0011b (i.e. 3) do not support PEC
154
if (version < 3) {
155
_pec_supported = false;
156
_pec_confirmed = true;
157
return true;
158
}
159
160
// check manufacturer name
161
uint8_t buff[AP_BATTMONITOR_SMBUS_READ_BLOCK_MAXIMUM_TRANSFER + 1] {};
162
if (read_block(BATTMONITOR_SMBUS_MANUFACTURE_NAME, buff, sizeof(buff))) {
163
// Hitachi maxell batteries do not support PEC
164
if (strcmp((char*)buff, "Hitachi maxell") == 0) {
165
_pec_supported = false;
166
_pec_confirmed = true;
167
return true;
168
}
169
}
170
171
// assume all other batteries support PEC
172
_pec_supported = true;
173
_pec_confirmed = true;
174
return true;
175
}
176
177
#endif // AP_BATTERY_SMBUS_GENERIC_ENABLED
178
179