mirror of
https://gitee.com/mirrors_PX4/PX4-Autopilot.git
synced 2026-10-14 22:33:34 +08:00
batt_smbus: Adds functions for reading out the SBS Info
Functions added for reading out the following info: - Manufacturer Name - Device Name - Serial Number - Device Chemistry
This commit is contained in:
@@ -88,8 +88,11 @@
|
||||
#define BATT_SMBUS_FULL_CHARGE_CAPACITY 0x10 ///< capacity when fully charged
|
||||
#define BATT_SMBUS_DESIGN_CAPACITY 0x18 ///< design capacity register
|
||||
#define BATT_SMBUS_DESIGN_VOLTAGE 0x19 ///< design voltage register
|
||||
#define BATT_SMBUS_SERIALNUM 0x1c ///< serial number register
|
||||
#define BATT_SMBUS_MANUFACTURE_NAME 0x20 ///< manufacturer name
|
||||
#define BATT_SMBUS_MANUFACTURE_DATE 0x1B ///< manufacture date register
|
||||
#define BATT_SMBUS_SERIAL_NUMBER 0x1C ///< serial number register
|
||||
#define BATT_SMBUS_MANUFACTURER_NAME 0x20 ///< manufacturer name
|
||||
#define BATT_SMBUS_DEVICE_NAME 0x21 ///< device name register
|
||||
#define BATT_SMBUS_DEVICE_CHEMISTRY 0x22 ///< device chemistry register
|
||||
#define BATT_SMBUS_MANUFACTURER_DATA 0x23 ///< manufacturer data
|
||||
#define BATT_SMBUS_MANUFACTURE_INFO 0x25 ///< cell voltage register
|
||||
#define BATT_SMBUS_CURRENT 0x2a ///< current register
|
||||
@@ -139,6 +142,57 @@ public:
|
||||
*/
|
||||
int search();
|
||||
|
||||
/**
|
||||
* Get the SBS manufacturer name of the battery device
|
||||
*
|
||||
* @param manufacturer_name pointer a buffer into which the manufacturer name is to be written
|
||||
* @param max_length the maximum number of bytes to attempt to read from the manufacturer name register, including the null character that is appended to the end
|
||||
*
|
||||
* @return the number of bytes read
|
||||
*/
|
||||
uint8_t manufacturer_name(uint8_t *man_name, uint8_t max_length);
|
||||
|
||||
/**
|
||||
* Return the SBS manufacture date of the battery device
|
||||
*
|
||||
* @return the date in the following format:
|
||||
* see Smart Battery Data Specification, Revision 1.1
|
||||
* http://sbs-forum.org/specs/sbdat110.pdf for more details
|
||||
* Date as uint16_t = (year-1980) * 512 + month * 32 + day
|
||||
* | Field | Bits | Format | Allowable Values |
|
||||
* | ----- | ---- | ------------------ | ------------------------------------------ |
|
||||
* | Day 0-4 5-bit binary value 1-31 (corresponds to day) |
|
||||
* | Month 5-8 4-bit binary value 1-12 (corresponds to month number) |
|
||||
* | Year 9-15 7-bit binary value 0-127 (corresponds to year biased by 1980) |
|
||||
* otherwise, return 0 on failure
|
||||
*/
|
||||
uint16_t manufacture_date();
|
||||
|
||||
/**
|
||||
* Get the SBS device name of the battery device
|
||||
*
|
||||
* @param dev_name pointer a buffer into which the device name is to be written
|
||||
* @param max_length the maximum number of bytes to attempt to read from the device name register, including the null character that is appended to the end
|
||||
*
|
||||
* @return the number of bytes read
|
||||
*/
|
||||
uint8_t device_name(uint8_t *dev_name, uint8_t max_length);
|
||||
|
||||
/**
|
||||
* Return the SBS serial number of the battery device
|
||||
*/
|
||||
uint16_t serial_number();
|
||||
|
||||
/**
|
||||
* Get the SBS device chemistry of the battery device
|
||||
*
|
||||
* @param dev_chem pointer a buffer into which the device chemistry is to be written
|
||||
* @param max_length the maximum number of bytes to attempt to read from the device chemistry register, including the null character that is appended to the end
|
||||
*
|
||||
* @return the number of bytes read
|
||||
*/
|
||||
uint8_t device_chemistry(uint8_t *dev_chem, uint8_t max_length);
|
||||
|
||||
protected:
|
||||
/**
|
||||
* Check if the device can be contacted
|
||||
@@ -222,6 +276,12 @@ void batt_smbus_usage();
|
||||
|
||||
extern "C" __EXPORT int batt_smbus_main(int argc, char *argv[]);
|
||||
|
||||
int manufacturer_name();
|
||||
int manufacture_date();
|
||||
int device_name();
|
||||
int serial_number();
|
||||
int device_chemistry();
|
||||
|
||||
BATT_SMBUS::BATT_SMBUS(int bus, uint16_t batt_smbus_addr) :
|
||||
I2C("batt_smbus", BATT_SMBUS0_DEVICE_PATH, bus, batt_smbus_addr, 100000),
|
||||
_enabled(false),
|
||||
@@ -368,6 +428,82 @@ BATT_SMBUS::search()
|
||||
return OK;
|
||||
}
|
||||
|
||||
uint8_t
|
||||
BATT_SMBUS::manufacturer_name(uint8_t *man_name, uint8_t max_length)
|
||||
{
|
||||
uint8_t len = read_block(BATT_SMBUS_MANUFACTURER_NAME, man_name, max_length, false);
|
||||
|
||||
if (len > 0) {
|
||||
if (len >= max_length - 1) {
|
||||
man_name[max_length - 1] = 0;
|
||||
|
||||
} else {
|
||||
man_name[len] = 0;
|
||||
}
|
||||
}
|
||||
|
||||
return len;
|
||||
}
|
||||
|
||||
uint16_t
|
||||
BATT_SMBUS::manufacture_date()
|
||||
{
|
||||
uint16_t man_date;
|
||||
|
||||
if (read_reg(BATT_SMBUS_MANUFACTURE_DATE, man_date) == OK) {
|
||||
return man_date;
|
||||
}
|
||||
|
||||
// Return 0 if could not read the date correctly
|
||||
return 0;
|
||||
}
|
||||
|
||||
uint8_t
|
||||
BATT_SMBUS::device_name(uint8_t *dev_name, uint8_t max_length)
|
||||
{
|
||||
uint8_t len = read_block(BATT_SMBUS_DEVICE_NAME, dev_name, max_length, false);
|
||||
|
||||
if (len > 0) {
|
||||
if (len >= max_length - 1) {
|
||||
dev_name[max_length - 1] = 0;
|
||||
|
||||
} else {
|
||||
dev_name[len] = 0;
|
||||
}
|
||||
}
|
||||
|
||||
return len;
|
||||
}
|
||||
|
||||
uint16_t
|
||||
BATT_SMBUS::serial_number()
|
||||
{
|
||||
uint16_t serial_num;
|
||||
|
||||
if (read_reg(BATT_SMBUS_SERIAL_NUMBER, serial_num) == OK) {
|
||||
return serial_num;
|
||||
}
|
||||
|
||||
return -1;
|
||||
}
|
||||
|
||||
uint8_t
|
||||
BATT_SMBUS::device_chemistry(uint8_t *dev_chem, uint8_t max_length)
|
||||
{
|
||||
uint8_t len = read_block(BATT_SMBUS_DEVICE_CHEMISTRY, dev_chem, max_length, false);
|
||||
|
||||
if (len > 0) {
|
||||
if (len >= max_length - 1) {
|
||||
dev_chem[max_length - 1] = 0;
|
||||
|
||||
} else {
|
||||
dev_chem[len] = 0;
|
||||
}
|
||||
}
|
||||
|
||||
return len;
|
||||
}
|
||||
|
||||
int
|
||||
BATT_SMBUS::probe()
|
||||
{
|
||||
@@ -451,28 +587,28 @@ 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;
|
||||
/*
|
||||
// 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...");
|
||||
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;
|
||||
}
|
||||
} 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
|
||||
if (_batt_topic != -1) {
|
||||
@@ -693,12 +829,92 @@ BATT_SMBUS::ManufacturerAccess(uint16_t cmd)
|
||||
void
|
||||
batt_smbus_usage()
|
||||
{
|
||||
warnx("missing command: try 'start', 'test', 'stop', 'search'");
|
||||
warnx("missing command: try 'start', 'test', 'stop', 'search', 'man_name', 'man_date', 'dev_name', 'serial_num', 'dev_chem', 'sbs_info'");
|
||||
warnx("options:");
|
||||
warnx(" -b i2cbus (%d)", BATT_SMBUS_I2C_BUS);
|
||||
warnx(" -a addr (0x%x)", BATT_SMBUS_ADDR);
|
||||
}
|
||||
|
||||
int
|
||||
manufacturer_name()
|
||||
{
|
||||
uint8_t man_name[21];
|
||||
uint8_t len = g_batt_smbus->manufacturer_name(man_name, sizeof(man_name));
|
||||
|
||||
if (len > 0) {
|
||||
warnx("The manufacturer name: %s", man_name);
|
||||
return OK;
|
||||
|
||||
} else {
|
||||
warnx("Unable to read manufacturer name.");
|
||||
}
|
||||
|
||||
return -1;
|
||||
}
|
||||
|
||||
int
|
||||
manufacture_date()
|
||||
{
|
||||
uint16_t man_date = g_batt_smbus->manufacture_date();
|
||||
|
||||
if (man_date > 0) {
|
||||
// Convert the uint16_t into human-readable date format
|
||||
uint16_t year = ((man_date >> 9) & 0xFF) + 1980;
|
||||
uint8_t month = (man_date >> 5) & 0xF;
|
||||
uint8_t day = man_date & 0x1F;
|
||||
warnx("The manufacturer date is: %d which is %4d-%02d-%02d", man_date, year, month, day);
|
||||
return OK;
|
||||
|
||||
} else {
|
||||
warnx("Unable to read the manufacturer date.");
|
||||
}
|
||||
|
||||
return -1;
|
||||
}
|
||||
|
||||
int
|
||||
device_name()
|
||||
{
|
||||
uint8_t device_name[21];
|
||||
uint8_t len = g_batt_smbus->device_name(device_name, sizeof(device_name));
|
||||
|
||||
if (len > 0) {
|
||||
warnx("The device name: %s", device_name);
|
||||
return OK;
|
||||
|
||||
} else {
|
||||
warnx("Unable to read device name.");
|
||||
}
|
||||
|
||||
return -1;
|
||||
}
|
||||
|
||||
int
|
||||
serial_number()
|
||||
{
|
||||
uint16_t serial_num = g_batt_smbus->serial_number();
|
||||
warnx("The serial number: 0x%04x (%d in decimal)", serial_num, serial_num);
|
||||
|
||||
return OK;
|
||||
}
|
||||
|
||||
int
|
||||
device_chemistry()
|
||||
{
|
||||
uint8_t device_chemistry[5];
|
||||
uint8_t len = g_batt_smbus->device_chemistry(device_chemistry, sizeof(device_chemistry));
|
||||
|
||||
if (len > 0) {
|
||||
warnx("The device chemistry: %s", device_chemistry);
|
||||
return OK;
|
||||
|
||||
} else {
|
||||
warnx("Unable to read device chemistry.");
|
||||
}
|
||||
|
||||
return -1;
|
||||
}
|
||||
|
||||
int
|
||||
batt_smbus_main(int argc, char *argv[])
|
||||
{
|
||||
@@ -776,6 +992,40 @@ batt_smbus_main(int argc, char *argv[])
|
||||
exit(0);
|
||||
}
|
||||
|
||||
if (!strcmp(verb, "man_name")) {
|
||||
manufacturer_name();
|
||||
exit(0);
|
||||
}
|
||||
|
||||
if (!strcmp(verb, "man_date")) {
|
||||
manufacture_date();
|
||||
exit(0);
|
||||
}
|
||||
|
||||
if (!strcmp(verb, "dev_name")) {
|
||||
device_name();
|
||||
exit(0);
|
||||
}
|
||||
|
||||
if (!strcmp(verb, "serial_num")) {
|
||||
serial_number();
|
||||
exit(0);
|
||||
}
|
||||
|
||||
if (!strcmp(verb, "dev_chem")) {
|
||||
device_chemistry();
|
||||
exit(0);
|
||||
}
|
||||
|
||||
if (!strcmp(verb, "sbs_info")) {
|
||||
manufacturer_name();
|
||||
manufacture_date();
|
||||
device_name();
|
||||
serial_number();
|
||||
device_chemistry();
|
||||
exit(0);
|
||||
}
|
||||
|
||||
batt_smbus_usage();
|
||||
exit(0);
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user