Configuration¶
Every setting the driver exposes, its default and where it lives: the transport configuration, the write policy, model descriptors, and the Kconfig options of the ESP32 examples.
Transport configuration¶
Bus::Open() takes a TransportConfig and hands it to your transport's open().
| Field | Default | Meaning |
|---|---|---|
baud_rate |
57600 (kDefaultBaud) |
Host rate in bit/s; must match the servos' Baud Rate register |
echo_policy |
EchoPolicy::None |
ExpectedLocalEcho when RX hears every TX byte (single-wire link) |
latency_ms |
2 |
Slack added to every reply timeout, twice, on top of 2 ms and the packet's byte time |
max_packet_bytes |
256 (kMaxPacketBytes) |
Largest packet the bus sends or asks a servo for; see below |
max_packet_bytes bounds every packet before byte stuffing. Protocol 2.0 (e-Manual section 2.4) makes an
instruction packet 10 bytes plus its parameters and a status packet 11 bytes plus its data, so with the default of
256 a ReadRegister() or SyncRead() returns at most 245 bytes per servo, a WriteRegister() writes at most
244, and a SyncWrite() carries at most 242 bytes of ID plus data. A request that would not fit returns
BufferTooSmall without sending. Open() refuses a value below 14 (kMinPacketBytes, a ping reply) with
InvalidParameter and caps a value above 1024 (kSdkMaxPacketBytes, the SDK's packet buffers).
For reads, writes and pings of one servo, the reply timeout for n expected bytes is n × byte time +
2 × latency_ms + 2 ms, measured with your transport's now_us(). Raise latency_ms when the transport adds
buffering of its own (a USB serial adapter, an RTOS queue); lower it, and the servos' Return Delay Time, for faster
polling.
A single-wire link at 1 Mbit/s:
dynamixel::TransportConfig single_wire_config() {
dynamixel::TransportConfig cfg{};
cfg.baud_rate = 1000000;
cfg.echo_policy = dynamixel::EchoPolicy::ExpectedLocalEcho; // RX hears every TX byte first
cfg.latency_ms = 1;
return cfg;
}
With ExpectedLocalEcho the driver reads back each transmitted packet and compares it before it waits for the
reply; a missing or different echo is EchoMismatch.
Write policy¶
Every WriteRegister() takes a WritePolicy, TxRx by default: TxOnly for fire-and-forget and broadcast,
ReadbackVerify for EEPROM values you must be sure of. The API guide
compares them. The typed Device setters always use TxRx.
A servo of your own¶
A ModelDescriptor holds a servo's register addresses, widths and capabilities. For an X-series servo the catalog
does not list, MakeXSeries() builds one from the shared table:
// An X-series servo the catalog does not list yet: same control table, its own model number.
inline constexpr dynamixel::ModelDescriptor kMyXm540 =
dynamixel::MakeXSeries(1120, "XM540-W270", /*supports_current=*/true,
/*effort_is_current=*/true);
void bind_my_servo(dynamixel::Device& servo) {
servo.BindModel(kMyXm540); // kept by Identify() when the ping reports model 1120
(void)servo.Identify();
}
MakeXSeries() argument |
Set it to |
|---|---|
number |
The model number from the e-Manual (Model Number, address 0) |
name |
Any label; Device::model()->name returns it |
supports_current |
true when the model has Goal Current (address 102) |
effort_is_current |
true when address 126 is Present Current rather than Present Load |
A servo with a different control table needs a ModelDescriptor written field by field; see
Model support.
Compile-time constants¶
| Constant | Value | Use |
|---|---|---|
kBroadcastId |
0xFE |
Broadcast, TxOnly writes |
kMaxDeviceId |
0xFC |
Highest ID, 252 |
kDefaultBaud |
57600 |
Factory rate |
kMaxPacketBytes |
256 |
Default max_packet_bytes |
kMinPacketBytes |
14 |
Smallest max_packet_bytes Open() accepts |
kSdkMaxPacketBytes |
1024 |
Cap on max_packet_bytes (SDK buffers) |
ESP32 example options¶
idf.py menuconfig, menu HF Dynamixel Example
(Kconfig.projbuild):
Every option is named CONFIG_HF_DYNAMIXEL_ followed by the name in the first column.
| Option | Default | Meaning |
|---|---|---|
UART_PORT |
1 | UART number |
UART_TX_GPIO |
4 (C6), 17 (S3) | MCU TX |
UART_RX_GPIO |
5 (C6), 18 (S3) | MCU RX |
UART_DIR_GPIO |
-1 | Buffer direction pin; -1: none |
DIR_ACTIVE_HIGH |
y | DIR high while transmitting |
BAUD |
57600 | Bus rate |
SERVO_ID |
1 | ID used when the scan finds nothing |
SCAN_LAST_ID |
20 | Scan IDs 1 to this |
EXPECT_LOCAL_ECHO |
n | EchoPolicy::ExpectedLocalEcho |
BIND_XSERIES_FALLBACK |
y | Fallback for an unlisted model |
The per-chip defaults are in sdkconfig.defaults.esp32c6 and sdkconfig.defaults.esp32s3.