-
Notifications
You must be signed in to change notification settings - Fork 16.8k
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Add Smart_Battery_Info MAVLink message #16167
base: master
Are you sure you want to change the base?
Conversation
The message is marked as "work-in-progress". Is it a good idea to bring it in? I do like your changes though. |
f173c3c
to
40c1c25
Compare
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I love the addition to the simulated battery.
There might be some push-back on having the method returning a string for the serial number. We'll see.
@magicrub you might be interested in options to pass more CAN battery information back to the GCS with this message.
This looks pretty good, really.
libraries/GCS_MAVLink/GCS_Common.cpp
Outdated
for(uint8_t i = 0; i < battery.num_instances(); i++) { | ||
if (battery.get_type(i) != AP_BattMonitor::Type::NONE) { | ||
CHECK_PAYLOAD_SIZE(SMART_BATTERY_INFO); | ||
send_smart_battery_info(i); | ||
} |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
@WickedShell has grown to dislike this pattern, preferring to keep some state around indicating the last instance we successfully sent.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The pattern for the other battery message like you describe has to be modified with the comment below due to where I have the message being sent from. Suggestions?
for(uint8_t i = 0; i < battery.num_instances(); i++) {
const uint8_t battery_id = (last_smart_battery_info_idx + 1) % AP_BATT_MONITOR_MAX_INSTANCES;
if (battery.get_type(battery_id) != AP_BattMonitor::Type::NONE) {
CHECK_PAYLOAD_SIZE(SMART_BATTERY_INFO);
send_smart_battery_info(battery_id);
last_smart_battery_info_idx = battery_id;
//return true;
} else {
last_smart_battery_info_idx = battery_id;
}
}
return true;
7d68053
to
2cc10fa
Compare
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I'm going to mark this for discussion at the European DevCall. I want more people to chime in on the send-as-part-of-banner thing.
@hendjoshsr71 let me know if you'd like me to rebase this on the changes I've just made to the simulated-smbus stuff - it obviously conflicted. I think the commit in your list here can just be removed. |
I got it. Thanks for the update! Adding in capacity and other fields to the sim and will reupload once working. |
2cc10fa
to
697046d
Compare
Added design capacity and few more items to SITL_SMBus model |
697046d
to
27febdc
Compare
This needs a rebase |
efaab7e
to
d901a36
Compare
Rebase complete. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Once this is merged we should send a message to the gcs-maintainers mailing list letting them know that they can request the message...
@WickedShell you're going to want to be happy with this before merge, I think?
d901a36
to
43813be
Compare
Thanks @peterbarker for the all the reviews!! Moved the SMBUS stuff to the backends. |
43813be
to
6c5ce94
Compare
On Mon, 15 Mar 2021, Josh Henderson wrote:
Used, for the snprintf's in the serial number, product, device, and manufacturer name functions
In the header?
|
Ahh I think I see your point it should be in the `AP_BattMonitor_SMBus.cpp' instead? |
c45751c
to
fc3bc5d
Compare
Changed the capacity functions to int32_t as smbus spec of uint16 doesn't leave much room at 65,536 mAh |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
i think we need to use HAL_MINIMIZE_FEATURES for this feature, to prevent the flash and ram cost for small boards with 1M flash
added DelayMerge for delay after final rebase for 4.1.0 |
1875af3
to
ce802c4
Compare
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Fixed the GCS_send so that false only gets returned if there is no space on the link.
Tested with 2 analog battmons, 1 smbus_generic, 1 rotoye, and 1 maxell. That logging and mavlink send works with my mavproxy submodule
Tested with SMART_BATTERY_INFO disabled and checked logs such that all makes sense for given monitor type.
ce802c4
to
ec0a733
Compare
This requires 2440 bytes on Durandal (arducopter) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Some nitpicks. I didn't have time to fully tell but the initialization bit still looks worrisome to me, as I'm not seeing a path where we don't try and spend a ton of I2C bandwidth talking to batteries that aren't there....
logger->Write_Power(); | ||
|
||
#if HAL_SMART_BATTERY_INFO_ENABLED | ||
// Check if the log_count has changed as logging can open/close at anytime |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Can this be moved down into the other #if check below? It would help keep the ideas closer together and make the file more readable
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I moved it, but now it all gets called inside the loop more times than necessary on each read cycle.
#endif | ||
|
||
for (uint8_t i=0; i<_num_instances; i++) { | ||
if (drivers[i] == nullptr || get_type(i) == Type::NONE) { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Let's remove the check for type being none. Changing type already needs a restart, and it helps save some flash cost. (Unless there's a different/better reason I'm missing here?)
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Removed. What about L298 below? I think I've missed the point of checking Type::NONE
that was here before this PR.
for (uint8_t i=0; i<_num_instances; i++) {
if (drivers[i] != nullptr && get_type(i) != Type::NONE) {
drivers[i]->read();
drivers[i]->update_resistance_estimate();
}
}
const uint8_t read_size = bufflen + 1 + (_pec_supported ? 1 : 0); | ||
uint8_t buff[read_size]; | ||
// check cell count | ||
if (_state.healthy) { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Unless I've missed something healthy isn't actual true initially, and it's normally toggled by the polling loop. Why are we looking at it at all inside of the initialization block?
Especially since this is called repeatedly during polling until the initialized flag (which can only be set by entering here) doesn't this mean we might repeatedly poll for all the smart battery info for ever on a non healthy battery and massively bring down the I2C bus by accident?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
We would only continue to poll for smart battery info. that hasn't already been successfully read, but...
I think your right about pulling it down due to the possible delays in SMBus. The crux of the issue is the termination condition & its placement for reading these registers. I've added a separate timer for reading info register termination.
However, guidance on the appropriate termination condition for reading the info. registers would be appreciated.
- Use a timeout?
- for each called register only allow one attempt to read
- only call
initialize()
Z number of times
If I brought back all of the bool returns from the read_zz()
I could OR those and return before timeout as well? (But that costs flash.)
The // check cell count
section of code appears to be an initialization task to set _cell_count_fixed
. I was trying to pull out initialization tasks into here. For now I'm going to put this block back and leave getting that into here for another day.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I really wish there was way to run these initialization type tasks first on the bus before registering the timer()
ec0a733
to
626c7b2
Compare
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
@WickedShell Addressed most of your comments. But I have left a question or two about the termination condition for the initialization function.
logger->Write_Power(); | ||
|
||
#if HAL_SMART_BATTERY_INFO_ENABLED | ||
// Check if the log_count has changed as logging can open/close at anytime |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I moved it, but now it all gets called inside the loop more times than necessary on each read cycle.
#endif | ||
|
||
for (uint8_t i=0; i<_num_instances; i++) { | ||
if (drivers[i] == nullptr || get_type(i) == Type::NONE) { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Removed. What about L298 below? I think I've missed the point of checking Type::NONE
that was here before this PR.
for (uint8_t i=0; i<_num_instances; i++) {
if (drivers[i] != nullptr && get_type(i) != Type::NONE) {
drivers[i]->read();
drivers[i]->update_resistance_estimate();
}
}
const uint8_t read_size = bufflen + 1 + (_pec_supported ? 1 : 0); | ||
uint8_t buff[read_size]; | ||
// check cell count | ||
if (_state.healthy) { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
We would only continue to poll for smart battery info. that hasn't already been successfully read, but...
I think your right about pulling it down due to the possible delays in SMBus. The crux of the issue is the termination condition & its placement for reading these registers. I've added a separate timer for reading info register termination.
However, guidance on the appropriate termination condition for reading the info. registers would be appreciated.
- Use a timeout?
- for each called register only allow one attempt to read
- only call
initialize()
Z number of times
If I brought back all of the bool returns from the read_zz()
I could OR those and return before timeout as well? (But that costs flash.)
The // check cell count
section of code appears to be an initialization task to set _cell_count_fixed
. I was trying to pull out initialization tasks into here. For now I'm going to put this block back and leave getting that into here for another day.
const uint8_t read_size = bufflen + 1 + (_pec_supported ? 1 : 0); | ||
uint8_t buff[read_size]; | ||
// check cell count | ||
if (_state.healthy) { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I really wish there was way to run these initialization type tasks first on the bus before registering the timer()
626c7b2
to
834b614
Compare
0d0d04a
to
4bebd6c
Compare
4bebd6c
to
3743643
Compare
Rebased due to |
2f23d42
to
ed01ef5
Compare
ed01ef5
to
a69ddfa
Compare
This adds the MAVLink message 370 SMART_BATTERY_INFO to send serial number, cycles, capacity, product name, etc.
PR to add the message to ArduPilot/mavlink here: ArduPilot/mavlink#181
One small documentation change on the MAVLink side here: mavlink/mavlink#1551
serial_number: I wasn't sure the best way/place to deal with the conversion from int32_t to char[16].
AP_BattMonitor.h: get_serial_number()
that is used byAP_BattMonitor_UAVCAN.h
not sure how to combine this together and limit the extra functionsSIM_BattMonitor_SMBus.cpp
Issue: The method to fill the registers for manufacturer_name and device_name causes the data from device name to write over all but the first char of the manufacturer_name. (Fixed here #16228)