PX4 Firmware
PX4 Autopilot Software http://px4.io
batt_smbus.cpp
Go to the documentation of this file.
1 /****************************************************************************
2  *
3  * Copyright (c) 2012-2018 PX4 Development Team. All rights reserved.
4  *
5  * Redistribution and use in source and binary forms, with or without
6  * modification, are permitted provided that the following conditions
7  * are met:
8  *
9  * 1. Redistributions of source code must retain the above copyright
10  * notice, this list of conditions and the following disclaimer.
11  * 2. Redistributions in binary form must reproduce the above copyright
12  * notice, this list of conditions and the following disclaimer in
13  * the documentation and/or other materials provided with the
14  * distribution.
15  * 3. Neither the name PX4 nor the names of its contributors may be
16  * used to endorse or promote products derived from this software
17  * without specific prior written permission.
18  *
19  * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
20  * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
21  * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
22  * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
23  * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
24  * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
25  * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS
26  * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED
27  * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
28  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
29  * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
30  * POSSIBILITY OF SUCH DAMAGE.
31  *
32  ****************************************************************************/
33 
34 /**
35  * @file batt_smbus.h
36  *
37  * Header for a battery monitor connected via SMBus (I2C).
38  * Designed for BQ40Z50-R1/R2
39  *
40  * @author Jacob Dahl <dahl.jakejacob@gmail.com>
41  * @author Alex Klimaj <alexklimaj@gmail.com>
42  */
43 
44 #include "batt_smbus.h"
45 
46 #include <lib/parameters/param.h>
47 
48 extern "C" __EXPORT int batt_smbus_main(int argc, char *argv[]);
49 
50 BATT_SMBUS::BATT_SMBUS(SMBus *interface, const char *path) :
51  ScheduledWorkItem(MODULE_NAME, px4::device_bus_to_wq(interface->get_device_id())),
52  _interface(interface)
53 {
54  battery_status_s new_report = {};
56 
57  int battsource = 1;
58  param_set(param_find("BAT_SOURCE"), &battsource);
59 
60  _interface->init();
61  // unseal() here to allow an external config script to write to protected flash.
62  // This is neccessary to avoid bus errors due to using standard i2c mode instead of SMbus mode.
63  // The external config script should then seal() the device.
64  unseal();
65 }
66 
68 {
71 
72  if (_manufacturer_name != nullptr) {
73  delete[] _manufacturer_name;
74  }
75 
76  if (_interface != nullptr) {
77  delete _interface;
78  }
79 
80  int battsource = 0;
81  param_set(param_find("BAT_SOURCE"), &battsource);
82 }
83 
84 int BATT_SMBUS::task_spawn(int argc, char *argv[])
85 {
87 
88  int myoptind = 1;
89  int ch;
90  const char *myoptarg = nullptr;
91 
92  while ((ch = px4_getopt(argc, argv, "XTRIA", &myoptind, &myoptarg)) != EOF) {
93  switch (ch) {
94  case 'X':
96  break;
97 
98  case 'T':
100  break;
101 
102  case 'R':
104  break;
105 
106  case 'I':
108  break;
109 
110  case 'A':
111  busid = BATT_SMBUS_BUS_ALL;
112  break;
113 
114  default:
115  print_usage();
116  return PX4_ERROR;
117  }
118  }
119 
120  for (unsigned i = 0; i < NUM_BUS_OPTIONS; i++) {
121 
122  if (!is_running() && (busid == BATT_SMBUS_BUS_ALL || smbus_bus_options[i].busid == busid)) {
123 
124  SMBus *interface = new SMBus(smbus_bus_options[i].busnum, BATT_SMBUS_ADDR);
125  BATT_SMBUS *dev = new BATT_SMBUS(interface, smbus_bus_options[i].devpath);
126 
127  int result = dev->get_startup_info();
128 
129  if (result != PX4_OK) {
130  delete dev;
131  continue;
132  }
133 
134  // Successful read of device type, we've found our battery
135  _object.store(dev);
136  _task_id = task_id_is_work_queue;
137 
138  dev->ScheduleOnInterval(BATT_SMBUS_MEASUREMENT_INTERVAL_US);
139 
140  return PX4_OK;
141 
142  }
143  }
144 
145  PX4_WARN("Not found.");
146  return PX4_ERROR;
147 }
148 
150 {
151  if (should_exit()) {
152  ScheduleClear();
153  exit_and_cleanup();
154  return;
155  }
156 
157  // Get the current time.
158  uint64_t now = hrt_absolute_time();
159 
160  // Read data from sensor.
161  battery_status_s new_report = {};
162 
163  // Set time of reading.
164  new_report.timestamp = now;
165 
166  new_report.connected = true;
167 
168  // Temporary variable for storing SMBUS reads.
169  uint16_t result;
170 
171  int ret = _interface->read_word(BATT_SMBUS_VOLTAGE, result);
172 
173  ret |= get_cell_voltages();
174 
175  // Convert millivolts to volts.
176  new_report.voltage_v = ((float)result) / 1000.0f;
177  new_report.voltage_filtered_v = new_report.voltage_v;
178 
179  // Read current.
180  ret |= _interface->read_word(BATT_SMBUS_CURRENT, result);
181 
182  new_report.current_a = (-1.0f * ((float)(*(int16_t *)&result)) / 1000.0f);
183  new_report.current_filtered_a = new_report.current_a;
184 
185  // Read average current.
187 
188  float average_current = (-1.0f * ((float)(*(int16_t *)&result)) / 1000.0f);
189 
190  new_report.average_current_a = average_current;
191 
192  // If current is high, turn under voltage protection off. This is neccessary to prevent
193  // a battery from cutting off while flying with high current near the end of the packs capacity.
194  set_undervoltage_protection(average_current);
195 
196  // Read run time to empty.
198  new_report.run_time_to_empty = result;
199 
200  // Read average time to empty.
202  new_report.average_time_to_empty = result;
203 
204  // Read remaining capacity.
206 
207  // Calculate remaining capacity percent with complementary filter.
208  new_report.remaining = 0.8f * _last_report.remaining + 0.2f * (1.0f - (float)((float)(_batt_capacity - result) /
209  (float)_batt_capacity));
210 
211  // Calculate total discharged amount.
212  new_report.discharged_mah = _batt_startup_capacity - result;
213 
214  // Check if max lifetime voltage delta is greater than allowed.
216  new_report.warning = battery_status_s::BATTERY_WARNING_CRITICAL;
217  }
218 
219  // Propagate warning state.
220  else {
221  if (new_report.remaining > _low_thr) {
222  new_report.warning = battery_status_s::BATTERY_WARNING_NONE;
223 
224  } else if (new_report.remaining > _crit_thr) {
225  new_report.warning = battery_status_s::BATTERY_WARNING_LOW;
226 
227  } else if (new_report.remaining > _emergency_thr) {
228  new_report.warning = battery_status_s::BATTERY_WARNING_CRITICAL;
229 
230  } else {
231  new_report.warning = battery_status_s::BATTERY_WARNING_EMERGENCY;
232  }
233  }
234 
235  // Read battery temperature and covert to Celsius.
236  ret |= _interface->read_word(BATT_SMBUS_TEMP, result);
237  new_report.temperature = ((float)result / 10.0f) + CONSTANTS_ABSOLUTE_NULL_CELSIUS;
238 
239  new_report.capacity = _batt_capacity;
240  new_report.cycle_count = _cycle_count;
241  new_report.serial_number = _serial_number;
242  new_report.cell_count = _cell_count;
243  new_report.voltage_cell_v[0] = _cell_voltages[0];
244  new_report.voltage_cell_v[1] = _cell_voltages[1];
245  new_report.voltage_cell_v[2] = _cell_voltages[2];
246  new_report.voltage_cell_v[3] = _cell_voltages[3];
247 
248  // Only publish if no errors.
249  if (!ret) {
251 
252  _last_report = new_report;
253  }
254 }
255 
257 {
258  ScheduleClear();
259 }
260 
262 {
263  ScheduleOnInterval(BATT_SMBUS_MEASUREMENT_INTERVAL_US);
264 }
265 
267 {
268  // Temporary variable for storing SMBUS reads.
269  uint16_t result = 0;
270 
271  int ret = _interface->read_word(BATT_SMBUS_CELL_1_VOLTAGE, result);
272  // Convert millivolts to volts.
273  _cell_voltages[0] = ((float)result) / 1000.0f;
274 
276  // Convert millivolts to volts.
277  _cell_voltages[1] = ((float)result) / 1000.0f;
278 
280  // Convert millivolts to volts.
281  _cell_voltages[2] = ((float)result) / 1000.0f;
282 
284  // Convert millivolts to volts.
285  _cell_voltages[3] = ((float)result) / 1000.0f;
286 
287  //Calculate max cell delta
289  float max_cell_voltage = _cell_voltages[0];
290 
291  for (uint8_t i = 1; i < (sizeof(_cell_voltages) / sizeof(_cell_voltages[0])); i++) {
293  max_cell_voltage = math::max(_min_cell_voltage, _cell_voltages[i]);
294  }
295 
296  // Calculate the max difference between the min and max cells with complementary filter.
297  _max_cell_voltage_delta = (0.5f * (max_cell_voltage - _min_cell_voltage)) +
299 
300  return ret;
301 }
302 
303 void BATT_SMBUS::set_undervoltage_protection(float average_current)
304 {
305  // Disable undervoltage protection if armed. Enable if disarmed and cell voltage is above limit.
306  if (average_current > BATT_CURRENT_UNDERVOLTAGE_THRESHOLD) {
308  // Disable undervoltage protection
309  uint8_t protections_a_tmp = BATT_SMBUS_ENABLED_PROTECTIONS_A_CUV_DISABLED;
310  uint16_t address = BATT_SMBUS_ENABLED_PROTECTIONS_A_ADDRESS;
311 
312  if (dataflash_write(address, &protections_a_tmp, 1) == PX4_OK) {
314  PX4_WARN("Disabled CUV");
315 
316  } else {
317  PX4_WARN("Failed to disable CUV");
318  }
319  }
320 
321  } else {
324  // Enable undervoltage protection
325  uint8_t protections_a_tmp = BATT_SMBUS_ENABLED_PROTECTIONS_A_DEFAULT;
326  uint16_t address = BATT_SMBUS_ENABLED_PROTECTIONS_A_ADDRESS;
327 
328  if (dataflash_write(address, &protections_a_tmp, 1) == PX4_OK) {
330  PX4_WARN("Enabled CUV");
331 
332  } else {
333  PX4_WARN("Failed to enable CUV");
334  }
335  }
336  }
337  }
338 
339 }
340 
341 //@NOTE: Currently unused, could be helpful for debugging a parameter set though.
342 int BATT_SMBUS::dataflash_read(uint16_t &address, void *data)
343 {
345 
346  // address is 2 bytes
347  int result = _interface->block_write(code, &address, 2, true);
348 
349  if (result != PX4_OK) {
350  return result;
351  }
352 
353  // @NOTE: The data buffer MUST be 32 bytes.
354  result = _interface->block_read(code, data, DATA_BUFFER_SIZE + 2, true);
355 
356  // When reading a BATT_SMBUS_MANUFACTURER_BLOCK_ACCESS the first 2 bytes will be the command code
357  // We will remove these since we do not care about the command code.
358  //memcpy(data, &((uint8_t *)data)[2], DATA_BUFFER_SIZE);
359 
360  return result;
361 }
362 
363 int BATT_SMBUS::dataflash_write(uint16_t &address, void *data, const unsigned length)
364 {
366 
367  uint8_t tx_buf[DATA_BUFFER_SIZE + 2] = {};
368 
369  tx_buf[0] = ((uint8_t *)&address)[0];
370  tx_buf[1] = ((uint8_t *)&address)[1];
371  memcpy(&tx_buf[2], data, length);
372 
373  // code (1), byte_count (1), addr(2), data(32) + pec
374  int result = _interface->block_write(code, tx_buf, length + 2, false);
375 
376  return result;
377 }
378 
380 {
381  int result = 0;
382  // The name field is 21 characters, add one for null terminator.
383  const unsigned name_length = 22;
384 
385  // Try and get battery SBS info.
386  if (_manufacturer_name == nullptr) {
387  char man_name[name_length] = {};
388  result = manufacturer_name((uint8_t *)man_name, sizeof(man_name));
389 
390  if (result != PX4_OK) {
391  PX4_WARN("Failed to get manufacturer name");
392  return PX4_ERROR;
393  }
394 
395  _manufacturer_name = new char[sizeof(man_name)];
396  }
397 
398  uint16_t serial_num;
399  result = _interface->read_word(BATT_SMBUS_SERIAL_NUMBER, serial_num);
400 
401  uint16_t remaining_cap;
402  result |= _interface->read_word(BATT_SMBUS_REMAINING_CAPACITY, remaining_cap);
403 
404  uint16_t cycle_count;
405  result |= _interface->read_word(BATT_SMBUS_CYCLE_COUNT, cycle_count);
406 
407  uint16_t full_cap;
409 
410  if (!result) {
411  _serial_number = serial_num;
412  _batt_startup_capacity = remaining_cap;
413  _cycle_count = cycle_count;
414  _batt_capacity = full_cap;
415  }
416 
417  if (lifetime_data_flush() == PX4_OK) {
418  // Flush needs time to complete, otherwise device is busy. 100ms not enough, 200ms works.
419  px4_usleep(200000);
420 
421  if (lifetime_read_block_one() == PX4_OK) {
423  PX4_WARN("Battery Damaged Will Not Fly. Lifetime max voltage difference: %4.2f",
425  }
426  }
427 
428  } else {
429  PX4_WARN("Failed to flush lifetime data");
430  }
431 
432  // Read battery threshold params on startup.
433  param_get(param_find("BAT_CRIT_THR"), &_crit_thr);
434  param_get(param_find("BAT_LOW_THR"), &_low_thr);
435  param_get(param_find("BAT_EMERGEN_THR"), &_emergency_thr);
436 
437  return result;
438 }
439 
441 {
442  uint16_t serial_num = 0;
443 
444  if (_interface->read_word(BATT_SMBUS_SERIAL_NUMBER, serial_num) == PX4_OK) {
445  return serial_num;
446  }
447 
448  return PX4_ERROR;
449 }
450 
452 {
453  uint16_t date;
454  int result = _interface->read_word(BATT_SMBUS_MANUFACTURE_DATE, date);
455 
456  if (result != PX4_OK) {
457  return result;
458  }
459 
460  return date;
461 }
462 
463 int BATT_SMBUS::manufacturer_name(uint8_t *man_name, const uint8_t length)
464 {
465  uint8_t code = BATT_SMBUS_MANUFACTURER_NAME;
466  uint8_t rx_buf[21] = {};
467 
468  // Returns 21 bytes, add 1 byte for null terminator.
469  int result = _interface->block_read(code, rx_buf, length - 1, true);
470 
471  memcpy(man_name, rx_buf, sizeof(rx_buf));
472 
473  man_name[21] = '\0';
474 
475  return result;
476 }
477 
479 {
480  PX4_INFO("Running");
481  print_message(_last_report);
482  return 0;
483 }
484 
485 int BATT_SMBUS::manufacturer_read(const uint16_t cmd_code, void *data, const unsigned length)
486 {
488 
489  uint8_t address[2] = {};
490  address[0] = ((uint8_t *)&cmd_code)[0];
491  address[1] = ((uint8_t *)&cmd_code)[1];
492 
493  int result = _interface->block_write(code, address, 2, false);
494 
495  if (result != PX4_OK) {
496  return result;
497  }
498 
499  // returns the 2 bytes of addr + data[]
500  result = _interface->block_read(code, data, length + 2, true);
501  memcpy(data, &((uint8_t *)data)[2], length);
502 
503  return result;
504 }
505 
506 int BATT_SMBUS::manufacturer_write(const uint16_t cmd_code, void *data, const unsigned length)
507 {
509 
510  uint8_t address[2] = {};
511  address[0] = ((uint8_t *)&cmd_code)[0];
512  address[1] = ((uint8_t *)&cmd_code)[1];
513 
514  uint8_t tx_buf[DATA_BUFFER_SIZE + 2] = {};
515  memcpy(tx_buf, address, 2);
516 
517  if (data != nullptr) {
518  memcpy(&tx_buf[2], data, length);
519  }
520 
521  int result = _interface->block_write(code, tx_buf, length + 2, false);
522 
523  return result;
524 }
525 
527 {
528  // See bq40z50 technical reference.
529  uint16_t keys[2] = {0x0414, 0x3672};
530 
532 
534 
535  return ret;
536 }
537 
539 {
540  // See bq40z50 technical reference.
541  uint16_t reg = BATT_SMBUS_SEAL;
542 
543  return manufacturer_write(reg, nullptr, 0);
544 }
545 
547 {
548  uint16_t flush = BATT_SMBUS_LIFETIME_FLUSH;
549 
550  return manufacturer_write(flush, nullptr, 0);
551 }
552 
554 {
555 
556  uint8_t lifetime_block_one[32] = {};
557 
558  if (PX4_OK != manufacturer_read(BATT_SMBUS_LIFETIME_BLOCK_ONE, lifetime_block_one, 32)) {
559  PX4_INFO("Failed to read lifetime block 1.");
560  return PX4_ERROR;
561  }
562 
563  //Get max cell voltage delta and convert from mV to V.
564  _lifetime_max_delta_cell_voltage = (float)(lifetime_block_one[17] << 8 | lifetime_block_one[16]) / 1000.0f;
565 
566  PX4_INFO("Max Cell Delta: %4.2f", (double)_lifetime_max_delta_cell_voltage);
567 
568  return PX4_OK;
569 }
570 
571 int BATT_SMBUS::custom_command(int argc, char *argv[])
572 {
573  const char *input = argv[0];
574  uint8_t man_name[22];
575  int result = 0;
576 
577  if (!is_running()) {
578  PX4_ERR("not running");
579  return -1;
580  }
581 
582  BATT_SMBUS *obj = get_instance();
583 
584  if (!strcmp(input, "man_info")) {
585 
586  result = obj->manufacturer_name(man_name, sizeof(man_name));
587  PX4_INFO("The manufacturer name: %s", man_name);
588 
589  result = obj->manufacture_date();
590  PX4_INFO("The manufacturer date: %d", result);
591 
592  uint16_t serial_num = 0;
593  serial_num = obj->get_serial_number();
594  PX4_INFO("The serial number: %d", serial_num);
595 
596  return 0;
597  }
598 
599  if (!strcmp(input, "unseal")) {
600  obj->unseal();
601  return 0;
602  }
603 
604  if (!strcmp(input, "seal")) {
605  obj->seal();
606  return 0;
607  }
608 
609  if (!strcmp(input, "suspend")) {
610  obj->suspend();
611  return 0;
612  }
613 
614  if (!strcmp(input, "resume")) {
615  obj->resume();
616  return 0;
617  }
618 
619  if (!strcmp(input, "serial_num")) {
620  uint16_t serial_num = obj->get_serial_number();
621  PX4_INFO("Serial number: %d", serial_num);
622  return 0;
623  }
624 
625  if (!strcmp(input, "write_flash")) {
626  if (argc >= 3) {
627  uint16_t address = atoi(argv[1]);
628  unsigned length = atoi(argv[2]);
629  uint8_t tx_buf[32] = {};
630 
631  if (length > 32) {
632  PX4_WARN("Data length out of range: Max 32 bytes");
633  return 1;
634  }
635 
636  // Data needs to be fed in 1 byte (0x01) at a time.
637  for (unsigned i = 0; i < length; i++) {
638  if ((unsigned)argc <= 3 + i) {
639  tx_buf[i] = atoi(argv[3 + i]);
640  }
641  }
642 
643  if (PX4_OK != obj->dataflash_write(address, tx_buf, length)) {
644  PX4_INFO("Dataflash write failed: %d", address);
645  px4_usleep(100000);
646  return 1;
647 
648  } else {
649  px4_usleep(100000);
650  return 0;
651  }
652  }
653  }
654 
655  print_usage();
656 
657  return PX4_ERROR;
658 }
659 
661 {
662  PRINT_MODULE_DESCRIPTION(
663  R"DESCR_STR(
664 ### Description
665 Smart battery driver for the BQ40Z50 fuel gauge IC.
666 
667 ### Examples
668 To write to flash to set parameters. address, number_of_bytes, byte0, ... , byteN
669 $ batt_smbus -X write_flash 19069 2 27 0
670 
671 )DESCR_STR");
672 
673  PRINT_MODULE_USAGE_NAME("batt_smbus", "driver");
674 
675  PRINT_MODULE_USAGE_COMMAND("start");
676  PRINT_MODULE_USAGE_PARAM_FLAG('X', "BATT_SMBUS_BUS_I2C_EXTERNAL", true);
677  PRINT_MODULE_USAGE_PARAM_FLAG('T', "BATT_SMBUS_BUS_I2C_EXTERNAL1", true);
678  PRINT_MODULE_USAGE_PARAM_FLAG('R', "BATT_SMBUS_BUS_I2C_EXTERNAL2", true);
679  PRINT_MODULE_USAGE_PARAM_FLAG('I', "BATT_SMBUS_BUS_I2C_INTERNAL", true);
680  PRINT_MODULE_USAGE_PARAM_FLAG('A', "BATT_SMBUS_BUS_ALL", true);
681 
682  PRINT_MODULE_USAGE_COMMAND_DESCR("man_info", "Prints manufacturer info.");
683  PRINT_MODULE_USAGE_COMMAND_DESCR("unseal", "Unseals the devices flash memory to enable write_flash commands.");
684  PRINT_MODULE_USAGE_COMMAND_DESCR("seal", "Seals the devices flash memory to disbale write_flash commands.");
685  PRINT_MODULE_USAGE_COMMAND_DESCR("suspend", "Suspends the driver from rescheduling the cycle.");
686  PRINT_MODULE_USAGE_COMMAND_DESCR("resume", "Resumes the driver from suspension.");
687 
688  PRINT_MODULE_USAGE_COMMAND_DESCR("write_flash", "Writes to flash. The device must first be unsealed with the unseal command.");
689  PRINT_MODULE_USAGE_ARG("address", "The address to start writing.", true);
690  PRINT_MODULE_USAGE_ARG("number of bytes", "Number of bytes to send.", true);
691  PRINT_MODULE_USAGE_ARG("data[0]...data[n]", "One byte of data at a time separated by spaces.", true);
692  PRINT_MODULE_USAGE_DEFAULT_COMMANDS();
693 
694  return PX4_OK;
695 }
696 
697 int batt_smbus_main(int argc, char *argv[])
698 {
699  return BATT_SMBUS::main(argc, argv);
700 }
int lifetime_data_flush()
This command flushes the RAM Lifetime Data to data flash to help streamline evaluation testing...
Definition: batt_smbus.cpp:546
#define BATT_SMBUS_SERIAL_NUMBER
serial number register
Definition: batt_smbus.h:80
float max_cell_voltage_delta
perf_counter_t _cycle
Definition: batt_smbus.h:255
int unseal()
Unseals the battery to allow writing to restricted flash.
Definition: batt_smbus.cpp:526
static int task_spawn(int argc, char *argv[])
Definition: batt_smbus.cpp:84
static constexpr float CONSTANTS_ABSOLUTE_NULL_CELSIUS
Definition: geo.h:59
__EXPORT int batt_smbus_main(int argc, char *argv[])
Definition: batt_smbus.cpp:697
#define BATT_SMBUS_CELL_3_VOLTAGE
Definition: batt_smbus.h:88
uint16_t _batt_startup_capacity
Definition: batt_smbus.h:276
#define BATT_SMBUS_MEASUREMENT_INTERVAL_US
time in microseconds, measure at 10Hz
Definition: batt_smbus.h:81
__EXPORT int param_get(param_t param, void *val)
Copy the value of a parameter.
Definition: parameters.cpp:589
#define BATT_SMBUS_LIFETIME_BLOCK_ONE
Definition: batt_smbus.h:91
int block_read(const uint8_t cmd_code, void *data, const uint8_t length, bool use_pec)
Sends a block read command.
Definition: SMBus.cpp:93
int main(int argc, char **argv)
Definition: main.cpp:3
#define DATA_BUFFER_SIZE
Definition: batt_smbus.h:57
float _max_cell_voltage_delta
Definition: batt_smbus.h:259
int block_write(const uint8_t cmd_code, void *data, uint8_t byte_count, bool use_pec)
Sends a block write command.
Definition: SMBus.cpp:120
void set_undervoltage_protection(float average_current)
Enables or disables the cell under voltage protection emergency shut off.
Definition: batt_smbus.cpp:303
__EXPORT int param_set(param_t param, const void *val)
Set the value of a parameter.
Definition: parameters.cpp:814
Definition: I2C.hpp:51
int read_word(const uint8_t cmd_code, uint16_t &data)
Sends a read word command.
Definition: SMBus.cpp:53
#define BATT_SMBUS_ENABLED_PROTECTIONS_A_CUV_DISABLED
Definition: batt_smbus.h:96
int manufacturer_name(uint8_t *manufacturer_name, const uint8_t length)
Gets the SBS manufacturer name of the battery device.
Definition: batt_smbus.cpp:463
#define BATT_SMBUS_CELL_1_VOLTAGE
Definition: batt_smbus.h:86
orb_advert_t orb_advertise(const struct orb_metadata *meta, const void *data)
Definition: uORB.cpp:43
float voltage_cell_v[4]
float _min_cell_voltage
Definition: batt_smbus.h:261
#define BATT_SMBUS_CELL_4_VOLTAGE
Definition: batt_smbus.h:89
static bool is_running()
Definition: dataman.cpp:415
#define BATT_SMBUS_CYCLE_COUNT
number of cycles the battery has experienced
Definition: batt_smbus.h:75
BATT_SMBUS(SMBus *interface, const char *path)
Definition: batt_smbus.cpp:50
#define BATT_CURRENT_UNDERVOLTAGE_THRESHOLD
Threshold in amps to disable undervoltage protection.
Definition: batt_smbus.h:62
#define BATT_SMBUS_ENABLED_PROTECTIONS_A_DEFAULT
Definition: batt_smbus.h:95
uint16_t _cycle_count
Definition: batt_smbus.h:279
battery_status_s _last_report
Definition: batt_smbus.h:264
static int custom_command(int argc, char *argv[])
Definition: batt_smbus.cpp:571
Global flash based parameter store.
void resume()
Definition: batt_smbus.cpp:261
char * _manufacturer_name
Definition: batt_smbus.h:294
#define BATT_SMBUS_TEMP
temperature register
Definition: batt_smbus.h:69
#define ORB_ID(_name)
Generates a pointer to the uORB metadata structure for a given topic.
Definition: uORB.h:87
#define BATT_SMBUS_REMAINING_CAPACITY
predicted remaining battery capacity as a percentage
Definition: batt_smbus.h:74
#define BATT_SMBUS_CELL_2_VOLTAGE
Definition: batt_smbus.h:87
int write_word(const uint8_t cmd_code, uint16_t data)
Sends a write word command.
Definition: SMBus.cpp:77
#define BATT_SMBUS_MANUFACTURER_BLOCK_ACCESS
Definition: batt_smbus.h:84
void perf_free(perf_counter_t handle)
Free a counter.
#define BATT_SMBUS_VOLTAGE
voltage register
Definition: batt_smbus.h:70
float _low_thr
Definition: batt_smbus.h:291
uint8_t * data
Definition: dataman.cpp:149
#define BATT_SMBUS_CURRENT
current register
Definition: batt_smbus.h:67
Vector< float, 6 > f(float t, const Matrix< float, 6, 1 > &, const Matrix< float, 3, 1 > &)
Definition: integration.cpp:8
uint8_t _cell_count
Definition: batt_smbus.h:270
#define BATT_SMBUS_MANUFACTURE_DATE
manufacture date register
Definition: batt_smbus.h:79
struct batt_smbus_bus_option smbus_bus_options[]
uint16_t get_serial_number()
Returns the SBS serial number of the battery device.
Definition: batt_smbus.cpp:440
uint16_t _serial_number
Definition: batt_smbus.h:282
#define BATT_SMBUS_AVERAGE_TIME_TO_EMPTY
predicted remaining battery capacity based on the present rate of discharge in min ...
Definition: batt_smbus.h:73
#define NUM_BUS_OPTIONS
uint8_t _cell_undervoltage_protection_status
Definition: batt_smbus.h:300
uint16_t serial_number
int orb_publish(const struct orb_metadata *meta, orb_advert_t handle, const void *data)
Definition: uORB.cpp:70
#define BATT_CELL_VOLTAGE_THRESHOLD_FAILED
Threshold in volts to Land if cells are imbalanced.
Definition: batt_smbus.h:60
int seal()
Seals the battery to disallow writing to restricted flash.
Definition: batt_smbus.cpp:538
constexpr _Tp min(_Tp a, _Tp b)
Definition: Limits.hpp:54
__EXPORT param_t param_find(const char *name)
Look up a parameter by name.
Definition: parameters.cpp:370
static int print_usage()
Definition: batt_smbus.cpp:660
BATT_SMBUS_BUS
Definition: batt_smbus.h:100
float _cell_voltages[4]
Definition: batt_smbus.h:257
#define BATT_SMBUS_SEAL
Definition: batt_smbus.h:93
#define BATT_SMBUS_AVERAGE_CURRENT
current register
Definition: batt_smbus.h:68
int get_startup_info()
Read info from battery on startup.
Definition: batt_smbus.cpp:379
Header for a battery monitor connected via SMBus (I2C).
float _lifetime_max_delta_cell_voltage
Definition: batt_smbus.h:297
constexpr _Tp max(_Tp a, _Tp b)
Definition: Limits.hpp:60
void Run() override
Definition: batt_smbus.cpp:149
int manufacturer_read(const uint16_t cmd_code, void *data, const unsigned length)
Performs a ManufacturerBlockAccess() read command.
Definition: batt_smbus.cpp:485
int print_status() override
Definition: batt_smbus.cpp:478
int orb_unadvertise(orb_advert_t handle)
Definition: uORB.cpp:65
#define BATT_SMBUS_MANUFACTURER_ACCESS
Definition: batt_smbus.h:82
Definition: bst.cpp:62
int get_cell_voltages()
Reads the cell voltages.
Definition: batt_smbus.cpp:266
#define BATT_SMBUS_LIFETIME_FLUSH
Definition: batt_smbus.h:90
uint16_t run_time_to_empty
#define BATT_VOLTAGE_UNDERVOLTAGE_THRESHOLD
Threshold in volts to re-enable undervoltage protection.
Definition: batt_smbus.h:63
float _crit_thr
Definition: batt_smbus.h:285
uint16_t cycle_count
#define BATT_SMBUS_ENABLED_PROTECTIONS_A_ADDRESS
Definition: batt_smbus.h:92
int dataflash_read(uint16_t &address, void *data)
Reads data from flash.
Definition: batt_smbus.cpp:342
int manufacture_date()
Gets the SBS manufacture date of the battery.
Definition: batt_smbus.cpp:451
int dataflash_write(uint16_t &address, void *data, const unsigned length)
Writes data to flash.
Definition: batt_smbus.cpp:363
uint16_t average_time_to_empty
uint16_t _batt_capacity
Definition: batt_smbus.h:273
#define BATT_SMBUS_RUN_TIME_TO_EMPTY
predicted remaining battery capacity based on the present rate of discharge in min ...
Definition: batt_smbus.h:72
#define BATT_SMBUS_MANUFACTURER_NAME
manufacturer name
Definition: batt_smbus.h:78
Definition: SMBus.hpp:47
float _emergency_thr
Definition: batt_smbus.h:288
#define BATT_SMBUS_FULL_CHARGE_CAPACITY
capacity when fully charged
Definition: batt_smbus.h:71
int lifetime_read_block_one()
Reads the lifetime data from block 1.
Definition: batt_smbus.cpp:553
SMBus * _interface
Definition: batt_smbus.h:253
__EXPORT hrt_abstime hrt_absolute_time(void)
Get absolute time in [us] (does not wrap).
orb_advert_t _batt_topic
Definition: batt_smbus.h:267
void suspend()
Definition: batt_smbus.cpp:256
int manufacturer_write(const uint16_t cmd_code, void *data, const unsigned length)
Performs a ManufacturerBlockAccess() write command.
Definition: batt_smbus.cpp:506