mirror of
https://github.com/PX4/PX4-Autopilot.git
synced 2026-05-27 18:27:05 +08:00
batt_smbus: read button status from the smart battery
This is a cherry-pick of commit 8bd17a4b0cd9c1432cb57a9a80a215692f532370 in 3drobotics/PX4Firmware-solo Conflicts: src/drivers/batt_smbus/batt_smbus.cpp src/drivers/drv_irlock.h src/lib/ecl
This commit is contained in:
committed by
Lorenz Meier
parent
7fc0b0925c
commit
6ac26c680d
@@ -3,3 +3,4 @@ float32 voltage_v # Battery voltage in volts, 0 if unknown
|
|||||||
float32 voltage_filtered_v # Battery voltage in volts, filtered, 0 if unknown
|
float32 voltage_filtered_v # Battery voltage in volts, filtered, 0 if unknown
|
||||||
float32 current_a # Battery current in amperes, -1 if unknown
|
float32 current_a # Battery current in amperes, -1 if unknown
|
||||||
float32 discharged_mah # Discharged amount in mAh, -1 if unknown
|
float32 discharged_mah # Discharged amount in mAh, -1 if unknown
|
||||||
|
bool is_powering_off # Power off event imminent indication, false if unknown
|
||||||
|
|||||||
@@ -90,13 +90,15 @@
|
|||||||
#define BATT_SMBUS_DESIGN_VOLTAGE 0x19 ///< design voltage register
|
#define BATT_SMBUS_DESIGN_VOLTAGE 0x19 ///< design voltage register
|
||||||
#define BATT_SMBUS_SERIALNUM 0x1c ///< serial number register
|
#define BATT_SMBUS_SERIALNUM 0x1c ///< serial number register
|
||||||
#define BATT_SMBUS_MANUFACTURE_NAME 0x20 ///< manufacturer name
|
#define BATT_SMBUS_MANUFACTURE_NAME 0x20 ///< manufacturer name
|
||||||
|
#define BATT_SMBUS_MANUFACTURER_DATA 0x23 ///< manufacturer data
|
||||||
#define BATT_SMBUS_MANUFACTURE_INFO 0x25 ///< cell voltage register
|
#define BATT_SMBUS_MANUFACTURE_INFO 0x25 ///< cell voltage register
|
||||||
#define BATT_SMBUS_CURRENT 0x2a ///< current register
|
#define BATT_SMBUS_CURRENT 0x2a ///< current register
|
||||||
#define BATT_SMBUS_MEASUREMENT_INTERVAL_MS (1000000 / 10) ///< time in microseconds, measure at 10Hz
|
#define BATT_SMBUS_MEASUREMENT_INTERVAL_US (1000000 / 10) ///< time in microseconds, measure at 10Hz
|
||||||
#define BATT_SMBUS_TIMEOUT_MS 10000000 ///< timeout looking for battery 10seconds after startup
|
#define BATT_SMBUS_TIMEOUT_US 10000000 ///< timeout looking for battery 10seconds after startup
|
||||||
|
|
||||||
|
#define BATT_SMBUS_BUTTON_DEBOUNCE_MS 300 ///< button holds longer than this time will cause a power off event
|
||||||
|
|
||||||
#define BATT_SMBUS_MANUFACTURER_ACCESS 0x00
|
#define BATT_SMBUS_MANUFACTURER_ACCESS 0x00
|
||||||
#define BATT_SMBUS_MANUFACTURER_DATA 0x23
|
|
||||||
#define BATT_SMBUS_MANUFACTURER_BLOCK_ACCESS 0x44
|
#define BATT_SMBUS_MANUFACTURER_BLOCK_ACCESS 0x44
|
||||||
|
|
||||||
#define BATT_SMBUS_PEC_POLYNOMIAL 0x07 ///< Polynomial for calculating PEC
|
#define BATT_SMBUS_PEC_POLYNOMIAL 0x07 ///< Polynomial for calculating PEC
|
||||||
@@ -208,6 +210,7 @@ private:
|
|||||||
orb_id_t _batt_orb_id; ///< uORB battery topic ID
|
orb_id_t _batt_orb_id; ///< uORB battery topic ID
|
||||||
uint64_t _start_time; ///< system time we first attempt to communicate with battery
|
uint64_t _start_time; ///< system time we first attempt to communicate with battery
|
||||||
uint16_t _batt_capacity; ///< battery's design capacity in mAh (0 means unknown)
|
uint16_t _batt_capacity; ///< battery's design capacity in mAh (0 means unknown)
|
||||||
|
uint8_t _button_press_counts; ///< count of button presses detected
|
||||||
};
|
};
|
||||||
|
|
||||||
namespace
|
namespace
|
||||||
@@ -220,14 +223,15 @@ void batt_smbus_usage();
|
|||||||
extern "C" __EXPORT int batt_smbus_main(int argc, char *argv[]);
|
extern "C" __EXPORT int batt_smbus_main(int argc, char *argv[]);
|
||||||
|
|
||||||
BATT_SMBUS::BATT_SMBUS(int bus, uint16_t batt_smbus_addr) :
|
BATT_SMBUS::BATT_SMBUS(int bus, uint16_t batt_smbus_addr) :
|
||||||
I2C("batt_smbus", BATT_SMBUS_DEVICE_PATH, bus, batt_smbus_addr, 400000),
|
I2C("batt_smbus", BATT_SMBUS0_DEVICE_PATH, bus, batt_smbus_addr, 100000),
|
||||||
_enabled(false),
|
_enabled(false),
|
||||||
_work{},
|
_work{},
|
||||||
_reports(nullptr),
|
_reports(nullptr),
|
||||||
_batt_topic(nullptr),
|
_batt_topic(-1),
|
||||||
_batt_orb_id(nullptr),
|
_batt_orb_id(nullptr),
|
||||||
_start_time(0),
|
_start_time(0),
|
||||||
_batt_capacity(0)
|
_batt_capacity(0),
|
||||||
|
_button_press_counts(0)
|
||||||
{
|
{
|
||||||
// work_cancel in the dtor will explode if we don't do this...
|
// work_cancel in the dtor will explode if we don't do this...
|
||||||
memset(&_work, 0, sizeof(_work));
|
memset(&_work, 0, sizeof(_work));
|
||||||
@@ -318,8 +322,8 @@ BATT_SMBUS::test()
|
|||||||
|
|
||||||
if (updated) {
|
if (updated) {
|
||||||
if (orb_copy(ORB_ID(battery_status), sub, &status) == OK) {
|
if (orb_copy(ORB_ID(battery_status), sub, &status) == OK) {
|
||||||
warnx("V=%4.2f C=%4.2f DismAh=%4.2f Cap:%d", (float)status.voltage_v, (float)status.current_a,
|
warnx("V=%4.2f C=%4.2f DismAh=%4.2f Cap:%d Shutdown:%d", (double)status.voltage_v, (double)status.current_a,
|
||||||
(float)status.discharged_mah, (int)_batt_capacity);
|
(double)status.discharged_mah, (int)_batt_capacity, (int)status.is_powering_off);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -402,7 +406,7 @@ BATT_SMBUS::cycle()
|
|||||||
uint64_t now = hrt_absolute_time();
|
uint64_t now = hrt_absolute_time();
|
||||||
|
|
||||||
// exit without rescheduling if we have failed to find a battery after 10 seconds
|
// exit without rescheduling if we have failed to find a battery after 10 seconds
|
||||||
if (!_enabled && (now - _start_time > BATT_SMBUS_TIMEOUT_MS)) {
|
if (!_enabled && (now - _start_time > BATT_SMBUS_TIMEOUT_US)) {
|
||||||
warnx("did not find smart battery");
|
warnx("did not find smart battery");
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
@@ -424,7 +428,7 @@ BATT_SMBUS::cycle()
|
|||||||
new_report.voltage_v = ((float)tmp) / 1000.0f;
|
new_report.voltage_v = ((float)tmp) / 1000.0f;
|
||||||
|
|
||||||
// read current
|
// read current
|
||||||
uint8_t buff[4];
|
uint8_t buff[6];
|
||||||
|
|
||||||
if (read_block(BATT_SMBUS_CURRENT, buff, 4, false) == 4) {
|
if (read_block(BATT_SMBUS_CURRENT, buff, 4, false) == 4) {
|
||||||
new_report.current_a = -(float)((int32_t)((uint32_t)buff[3] << 24 | (uint32_t)buff[2] << 16 | (uint32_t)buff[1] << 8 |
|
new_report.current_a = -(float)((int32_t)((uint32_t)buff[3] << 24 | (uint32_t)buff[2] << 16 | (uint32_t)buff[1] << 8 |
|
||||||
@@ -447,14 +451,35 @@ BATT_SMBUS::cycle()
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// read the button press indicator
|
||||||
|
if (read_block(BATT_SMBUS_MANUFACTURER_DATA, buff, 6, false) == 6) {
|
||||||
|
bool pressed = (buff[1] >> 3) & 0x01;
|
||||||
|
|
||||||
|
if(_button_press_counts >= ((BATT_SMBUS_BUTTON_DEBOUNCE_MS * 1000) / BATT_SMBUS_MEASUREMENT_INTERVAL_US)) {
|
||||||
|
// battery will power off
|
||||||
|
new_report.is_powering_off = true;
|
||||||
|
// warn only once
|
||||||
|
if(_button_press_counts++ == ((BATT_SMBUS_BUTTON_DEBOUNCE_MS * 1000) / BATT_SMBUS_MEASUREMENT_INTERVAL_US)) {
|
||||||
|
warnx("system is shutting down NOW...");
|
||||||
|
}
|
||||||
|
} else if(pressed) {
|
||||||
|
// battery will power off if the button is held
|
||||||
|
_button_press_counts++;
|
||||||
|
} else {
|
||||||
|
// button released early, reset counters
|
||||||
|
_button_press_counts = 0;
|
||||||
|
new_report.is_powering_off = false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
// publish to orb
|
// publish to orb
|
||||||
if (_batt_topic != nullptr) {
|
if (_batt_topic != -1) {
|
||||||
orb_publish(_batt_orb_id, _batt_topic, &new_report);
|
orb_publish(_batt_orb_id, _batt_topic, &new_report);
|
||||||
|
|
||||||
} else {
|
} else {
|
||||||
_batt_topic = orb_advertise(_batt_orb_id, &new_report);
|
_batt_topic = orb_advertise(_batt_orb_id, &new_report);
|
||||||
|
|
||||||
if (_batt_topic == nullptr) {
|
if (_batt_topic < 0) {
|
||||||
errx(1, "ADVERT FAIL");
|
errx(1, "ADVERT FAIL");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -474,7 +499,7 @@ BATT_SMBUS::cycle()
|
|||||||
|
|
||||||
// schedule a fresh cycle call when the measurement is done
|
// schedule a fresh cycle call when the measurement is done
|
||||||
work_queue(HPWORK, &_work, (worker_t)&BATT_SMBUS::cycle_trampoline, this,
|
work_queue(HPWORK, &_work, (worker_t)&BATT_SMBUS::cycle_trampoline, this,
|
||||||
USEC2TICK(BATT_SMBUS_MEASUREMENT_INTERVAL_MS));
|
USEC2TICK(BATT_SMBUS_MEASUREMENT_INTERVAL_US));
|
||||||
}
|
}
|
||||||
|
|
||||||
int
|
int
|
||||||
|
|||||||
Reference in New Issue
Block a user