Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 2 additions & 2 deletions TUNING_GUIDE_ArduCopter.md
Original file line number Diff line number Diff line change
Expand Up @@ -268,7 +268,7 @@ The `ESC->FC Telemetry` type and protocol describe the return path:
| Connection Type | Protocol | Notes |
| --------------- | -------- | ----- |
| `None` | `None` | No ESC telemetry |
| same as FC->ESC | `BDShot` | BDShot only on Main Out and/or AIO, without serial port backup channel |
| same as FC->ESC | `BDShotOnly` | BDShot only on Main Out and/or AIO, without serial port backup channel |
| serial port | `ESC Telemetry` | DShot or BDShot serial telemetry backup channel |
| serial port | `FETtecOneWire` | Bidirectional FETtec protocol on the same wire |
| serial port | `Scripting` | For T-Motor/Hobbywing Datalink v2 serial telemetry |
Expand All @@ -278,7 +278,7 @@ The `ESC->FC Telemetry` type and protocol describe the return path:

When using BDShot only on `Main Out` (1-8) and/or `Aux I/O` (9-14) connection, without serial port backup channel:

![ESC telemetry BDshot only](images/blog/component_editor_esc_telem_main_out_aio.png)
![ESC telemetry BDShotOnly](images/blog/component_editor_esc_telem_main_out_aio.png)

When using DShot or BDShot with a serial port backup channel:

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -1024,7 +1024,7 @@ def upload_selected_params_workflow( # pylint: disable=too-many-arguments, too-
# If reset happened, fc_parameters cache was cleared during disconnect/reconnect
# Re-download parameters now so _upload_parameters_to_fc has valid cache for comparison
if reset_happened:
self.download_flight_controller_parameters(lambda cb=progress_callback_for_download: cb)
self.download_flight_controller_parameters(lambda cb=progress_callback_for_download: cb) # type: ignore[misc]

# Upload remaining parameters (excluding those already uploaded in reset workflow)
remaining_params = {k: v for k, v in selected_params.items() if k not in already_uploaded_params}
Expand All @@ -1039,7 +1039,7 @@ def upload_selected_params_workflow( # pylint: disable=too-many-arguments, too-
if self._at_least_one_changed:
# Re-download all parameters to validate
# Note: Passing the callback directly, not the factory, since we already got it
self.download_flight_controller_parameters(lambda cb=progress_callback_for_download: cb)
self.download_flight_controller_parameters(lambda cb=progress_callback_for_download: cb) # type: ignore[misc]
param_upload_error = self._validate_uploaded_parameters(selected_params)

if param_upload_error:
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -26,15 +26,16 @@
from ardupilot_methodic_configurator.data_model_vehicle_components_validation import (
BATT_MONITOR_CONNECTION,
CAN_PORTS,
ESC_TELEMETRY_PROTOCOLS,
ESC_TELEMETRY_ONLY_PROTOCOLS,
GNSS_RECEIVER_CONNECTION,
I2C_PORTS,
PWM_OUT_PORTS,
RC_PROTOCOLS_DICT,
SERIAL_PORTS,
SERIAL_PROTOCOLS_DICT,
SERVO_FUNCTION_ESC_CONTROL,
ComponentDataModelValidation,
get_mot_pwm_type_sub_dict,
get_esc_connection_sub_dict,
)


Expand Down Expand Up @@ -179,7 +180,7 @@ def process_fc_parameters(
elif "GPS_TYPE" in doc:
self._verify_dict_is_uptodate(doc, GNSS_RECEIVER_CONNECTION, "GPS_TYPE", "values")
fw_type = str(self.get_component_value(("Flight Controller", "Firmware", "Type")) or "")
self._verify_dict_is_uptodate(doc, get_mot_pwm_type_sub_dict(fw_type), "MOT_PWM_TYPE", "values")
self._verify_dict_is_uptodate(doc, get_esc_connection_sub_dict(fw_type), "MOT_PWM_TYPE", "values")
self._verify_dict_is_uptodate(doc, RC_PROTOCOLS_DICT, "RC_PROTOCOLS", "Bitmask")

# Process parameters in sequence
Expand Down Expand Up @@ -330,7 +331,7 @@ def _process_serial_components(self, fc_parameters: dict) -> bool: # pylint: di
self.set_component_value(("GNSS Receiver", "FC Connection", "Type"), serial)
gnss += 1
elif component == "ESC":
if protocol in ESC_TELEMETRY_PROTOCOLS:
if protocol in ESC_TELEMETRY_ONLY_PROTOCOLS:
# Serial ESC->FC telemetry only (DShot with UART feedback, or Hobbywing Datalink v2).
# FC->ESC connection is still PWM/DShot; _set_esc_type_from_fc_parameters handles it.
# Do NOT increment esc so that function is still called.
Expand Down Expand Up @@ -372,13 +373,13 @@ def _set_esc_type_from_fc_parameters(self, fc_parameters: dict[str, float], doc:
protocol = doc["MOT_PWM_TYPE"]["values"].get(str(mot_pwm_type), "")
if protocol:
self.set_component_value(("ESC", "FC->ESC Connection", "Protocol"), protocol)
# Fallback to MOT_PWM_TYPE_DICT if doc is not available
# Fallback to ESC_CONNECTION_DICT if doc is not available
else:
mot_pwm_sub = get_mot_pwm_type_sub_dict(
esc_conn_sub = get_esc_connection_sub_dict(
str(self.get_component_value(("Flight Controller", "Firmware", "Type")) or "")
)
if str(mot_pwm_type) in mot_pwm_sub:
protocol = str(mot_pwm_sub[str(mot_pwm_type)]["protocol"])
if str(mot_pwm_type) in esc_conn_sub:
protocol = str(esc_conn_sub[str(mot_pwm_type)]["protocol"])
self.set_component_value(("ESC", "FC->ESC Connection", "Protocol"), protocol)

# Set ESC->FC Telemetry: DShot supports BDShot telemetry on the same PWM wire.
Expand All @@ -388,9 +389,9 @@ def _set_esc_type_from_fc_parameters(self, fc_parameters: dict[str, float], doc:
current_telemetry_type = self.get_component_value(("ESC", "ESC->FC Telemetry", "Type"))
if protocol and protocol.startswith("DShot"):
if current_telemetry_type not in SERIAL_PORTS and current_telemetry_type not in CAN_PORTS:
# No dedicated serial/CAN telemetry port detected; fall back to BDShot on the PWM wire
# No dedicated serial/CAN telemetry port detected; fall back to BDShotOnly on the PWM wire
self.set_component_value(("ESC", "ESC->FC Telemetry", "Type"), esc_conn_type)
self.set_component_value(("ESC", "ESC->FC Telemetry", "Protocol"), "BDShot")
self.set_component_value(("ESC", "ESC->FC Telemetry", "Protocol"), "BDShotOnly")
elif not current_telemetry_type or (
current_telemetry_type not in SERIAL_PORTS and current_telemetry_type not in CAN_PORTS
):
Expand Down Expand Up @@ -688,10 +689,19 @@ def _set_motor_poles_from_fc_parameters(self, fc_parameters: dict[str, float]) -
poles = 0.0
if "MOT_PWM_TYPE" in fc_parameters:
mot_pwm_type_str = str(int(fc_parameters["MOT_PWM_TYPE"]))
mot_pwm_sub = get_mot_pwm_type_sub_dict(
esc_conn_sub = get_esc_connection_sub_dict(
str(self.get_component_value(("Flight Controller", "Firmware", "Type")) or "")
)
if mot_pwm_type_str in mot_pwm_sub and mot_pwm_sub[mot_pwm_type_str].get("is_dshot", False):
entry = esc_conn_sub.get(mot_pwm_type_str)
esc_to_fc = entry.get("ESC_to_FC") if entry is not None else None
is_dshot = (
entry is not None
and isinstance(esc_to_fc, dict)
and ("same_as_FC_to_ESC",) in esc_to_fc
and isinstance(entry.get("type"), tuple)
and entry["type"] == PWM_OUT_PORTS
)
if is_dshot:
if fc_parameters.get("SERVO_BLH_POLES"): # DShot ESCs
poles = fc_parameters["SERVO_BLH_POLES"]
elif fc_parameters.get("SERVO_FTW_MASK") and fc_parameters.get("SERVO_FTW_POLES"):
Expand Down
Loading
Loading