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_Solo.cpp
Views: 1798
1
#include "AP_BattMonitor_config.h"
2
3
#if AP_BATTERY_SMBUS_SOLO_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
#include <utility>
10
11
#include "AP_BattMonitor_SMBus_Solo.h"
12
13
#define BATTMONITOR_SMBUS_SOLO_CELL_VOLTAGE 0x28 // cell voltage register
14
#define BATTMONITOR_SMBUS_SOLO_CELL_VOLTAGE_EXT 0x29 // cell voltage register up to 6s
15
#define BATTMONITOR_SMBUS_SOLO_CURRENT 0x2a // current register
16
#define BATTMONITOR_SMBUS_SOLO_BUTTON_DEBOUNCE 6 // button held down for 5 intervals will cause a power off event
17
#define BATTMONITOR_SMBUS_SOLO_NUM_CELLS 4 // solo's battery pack is 4S
18
#define BATTMONITOR_SMBUS_SOLO_NUM_CELLS_EXT 6 // extended BMS supports up to 6s
19
20
/*
21
* Other potentially useful registers, listed here for future use
22
* #define BATTMONITOR_SMBUS_SOLO_VOLTAGE 0x09 // voltage register
23
* #define BATTMONITOR_SMBUS_SOLO_BATTERY_STATUS 0x16 // battery status register including alarms
24
* #define BATTMONITOR_SMBUS_SOLO_DESIGN_CAPACITY 0x18 // design capacity register
25
* #define BATTMONITOR_SMBUS_SOLO_DESIGN_VOLTAGE 0x19 // design voltage register
26
* #define BATTMONITOR_SMBUS_SOLO_SERIALNUM 0x1c // serial number register
27
* #define BATTMONITOR_SMBUS_SOLO_MANUFACTURE_NAME 0x20 // manufacturer name
28
* #define BATTMONITOR_SMBUS_SOLO_DEVICE_NAME 0x21 // device name
29
* #define BATTMONITOR_SMBUS_SOLO_DEVICE_CHEMISTRY 0x22 // device chemistry
30
* #define BATTMONITOR_SMBUS_SOLO_MANUFACTURE_INFO 0x25 // manufacturer info including cell voltage
31
*/
32
33
// Constructor
34
AP_BattMonitor_SMBus_Solo::AP_BattMonitor_SMBus_Solo(AP_BattMonitor &mon,
35
AP_BattMonitor::BattMonitor_State &mon_state,
36
AP_BattMonitor_Params &params)
37
: AP_BattMonitor_SMBus(mon, mon_state, params, AP_BATTMONITOR_SMBUS_BUS_INTERNAL)
38
{
39
_pec_supported = true;
40
}
41
42
void AP_BattMonitor_SMBus_Solo::timer()
43
{
44
uint8_t buff[12];
45
uint32_t tnow = AP_HAL::micros();
46
47
48
// read cell voltages
49
if (!_use_extended && read_block(BATTMONITOR_SMBUS_SOLO_CELL_VOLTAGE, buff, 8)) {
50
float pack_voltage_mv = 0.0f;
51
for (uint8_t i = 0; i < BATTMONITOR_SMBUS_SOLO_NUM_CELLS; i++) {
52
uint16_t cell = buff[(i * 2) + 1] << 8 | buff[i * 2];
53
_state.cell_voltages.cells[i] = cell;
54
pack_voltage_mv += (float)cell;
55
}
56
_has_cell_voltages = true;
57
58
// accumulate the pack voltage out of the total of the cells
59
// because the Solo's I2C bus is so noisy, it's worth not spending the
60
// time and bus bandwidth to request the pack voltage as a separate
61
// transaction
62
_state.voltage = pack_voltage_mv * 1e-3f;
63
_state.last_time_micros = tnow;
64
_state.healthy = true;
65
}
66
67
68
// read extended cell voltages
69
if (read_block(BATTMONITOR_SMBUS_SOLO_CELL_VOLTAGE_EXT, buff, 12)) {
70
float pack_voltage_mv = 0.0f;
71
for (uint8_t i = 0; i < BATTMONITOR_SMBUS_SOLO_NUM_CELLS_EXT; i++) {
72
uint16_t cell = buff[(i * 2) + 1] << 8 | buff[i * 2];
73
_state.cell_voltages.cells[i] = cell;
74
pack_voltage_mv += (float)cell;
75
}
76
_has_cell_voltages = true;
77
78
// accumulate the pack voltage out of the total of the cells
79
_state.voltage = pack_voltage_mv * 1e-3f;
80
_state.last_time_micros = tnow;
81
_state.healthy = true;
82
// stop requesting 4-cell packets.
83
_use_extended = true;
84
}
85
86
// timeout after 5 seconds
87
if ((tnow - _state.last_time_micros) > AP_BATTMONITOR_SMBUS_TIMEOUT_MICROS) {
88
_state.healthy = false;
89
// do not attempt to ready any more data from battery
90
return;
91
}
92
93
// read current
94
if (read_block(BATTMONITOR_SMBUS_SOLO_CURRENT, buff, 4) == 4) {
95
_state.current_amps = -(float)((int32_t)((uint32_t)buff[3]<<24 | (uint32_t)buff[2]<<16 | (uint32_t)buff[1]<<8 | (uint32_t)buff[0])) * 0.001f;
96
_state.last_time_micros = tnow;
97
}
98
99
read_full_charge_capacity();
100
read_remaining_capacity();
101
102
// read the button press indicator
103
if (read_block(BATTMONITOR_SMBUS_MANUFACTURE_DATA, buff, 6) == 6) {
104
bool pressed = (buff[1] >> 3) & 0x01;
105
106
if (_button_press_count >= BATTMONITOR_SMBUS_SOLO_BUTTON_DEBOUNCE) {
107
// vehicle will power off, set state flag
108
_state.is_powering_off = true;
109
} else if (pressed) {
110
// battery will power off if the button is held
111
_button_press_count++;
112
} else {
113
// button released, reset counters
114
_button_press_count = 0;
115
}
116
}
117
118
read_temp();
119
120
read_serial_number();
121
122
read_cycle_count();
123
}
124
125
#endif // AP_BATTERY_SMBUS_SOLO_ENABLED
126
127