diff --git a/CHANGELOG.md b/CHANGELOG.md index 68d2d159..bab57274 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -3,7 +3,13 @@ Please add a note of your changes below this heading if you make a Pull Request. ### Added * `dump_errors()` utility function in odrivetool to dump, decode and optionally clear errors. +* `f` command to ascii protocol to get encoder position and velocity feedback. * `q` command to ascii protocol. It is like the old `p` command, but velocity and current mean limits, not feed-forward. +* `ss`, `se`, `sr` commands to ascii protocol, for save config, erase config and reboot. +* `move_incremental` function for relative trajectory moves. +* `encoder.config.ignore_illegal_hall_state` option. +* `encoder.config.enable_phase_interpolation` option. Setting to false may reduce jerky pulsations at low speed when using hall sensor feedback. +* Analog input. Used the same way as the PWM input mappings. * Voltage limit soft clamping instead of ERROR_MODULATION_MAGNITUDE in gimbal motor closed loop. * Thermal current limit with linear derating. @@ -15,7 +21,7 @@ Please add a note of your changes below this heading if you make a Pull Request. ### Added * Overspeed fault * Current sense saturation fault. -* Supress startup transients by sampling encoder estimate into position setpoint when entering closed loop control. +* Suppress startup transients by sampling encoder estimate into position setpoint when entering closed loop control. * Make step dir gpio pins configurable. * Configuration variable `encoder.config.zero_count_on_find_idx`, true by default. Set to false to leave the initial encoder count to be where the axis was at boot. * Circular position setpoint mode: position setpoints wrapped [0, cpr). Useful for infinite incremental position control. diff --git a/Firmware/communication/ascii_protocol.cpp b/Firmware/communication/ascii_protocol.cpp index 3ac68499..8a0d3287 100644 --- a/Firmware/communication/ascii_protocol.cpp +++ b/Firmware/communication/ascii_protocol.cpp @@ -106,15 +106,17 @@ void ASCII_protocol_process_line(const uint8_t* buffer, size_t len, StreamSink& unsigned motor_number; float pos_setpoint, vel_limit, current_lim; int numscan = sscanf(cmd, "q %u %f %f %f", &motor_number, &pos_setpoint, &vel_limit, ¤t_lim); - if (numscan < 4) { + if (numscan < 2) { respond(response_channel, use_checksum, "invalid command format"); } else if (motor_number >= AXIS_COUNT) { respond(response_channel, use_checksum, "invalid motor %u", motor_number); } else { Axis* axis = axes[motor_number]; axis->controller_.pos_setpoint_ = pos_setpoint; - axis->controller_.config_.vel_limit = vel_limit; - axis->motor_.config_.current_lim = current_lim; + if (numscan >= 3) + axis->controller_.config_.vel_limit = vel_limit; + if (numscan >= 4) + axis->motor_.config_.current_lim = current_lim; } } else if (cmd[0] == 'v') { // velocity control @@ -172,6 +174,7 @@ void ASCII_protocol_process_line(const uint8_t* buffer, size_t len, StreamSink& respond(response_channel, use_checksum, "Please see documentation for more details"); respond(response_channel, use_checksum, ""); respond(response_channel, use_checksum, "Available commands syntax reference:"); + respond(response_channel, use_checksum, "Position: q axis pos vel-lim I-lim"); respond(response_channel, use_checksum, "Position: p axis pos vel-ff I-ff"); respond(response_channel, use_checksum, "Velocity: v axis vel I-ff"); respond(response_channel, use_checksum, "Current: c axis I"); @@ -179,6 +182,10 @@ void ASCII_protocol_process_line(const uint8_t* buffer, size_t len, StreamSink& respond(response_channel, use_checksum, "Properties start at odrive root, such as axis0.requested_state"); respond(response_channel, use_checksum, "Read: r property"); respond(response_channel, use_checksum, "Write: w property value"); + respond(response_channel, use_checksum, ""); + respond(response_channel, use_checksum, "Save config: ss"); + respond(response_channel, use_checksum, "Erase config: se"); + respond(response_channel, use_checksum, "Reboot: sr"); } else if (cmd[0] == 'i'){ // Dump device info // respond(response_channel, use_checksum, "Signature: %#x", STM_ID_GetSignature()); @@ -188,12 +195,14 @@ void ASCII_protocol_process_line(const uint8_t* buffer, size_t len, StreamSink& respond(response_channel, use_checksum, "Firmware version: %d.%d.%d", FW_VERSION_MAJOR, FW_VERSION_MINOR, FW_VERSION_REVISION); respond(response_channel, use_checksum, "Serial number: %s", serial_number_str); - } else if (cmd[0] == 's'){ // Save config - save_configuration(); - } else if (cmd[0] == 'e'){ // Erase config - erase_configuration(); - } else if (cmd[0] == 'b'){ // Reboot - NVIC_SystemReset(); + } else if (cmd[0] == 's'){ // System + if(cmd[1] == 's') { // Save config + save_configuration(); + } else if (cmd[1] == 'e'){ // Erase config + erase_configuration(); + } else if (cmd[1] == 'b'){ // Reboot + NVIC_SystemReset(); + } } else if (cmd[0] == 'r') { // read property char name[MAX_LINE_LENGTH]; diff --git a/docs/ascii-protocol.md b/docs/ascii-protocol.md index 51ff18ea..0c510fe6 100644 --- a/docs/ascii-protocol.md +++ b/docs/ascii-protocol.md @@ -37,6 +37,20 @@ Example: `t 0 -20000` For general moving around of the axis, this is the recommended command. #### Motor Position command +For basic use where you send one setpoint at at a time, use the `q` command. +If you have a realtime controller that is streaming setpoints and tracking a trajectory, use the `p` command. + +``` +q motor position velocity_lim current_lim +``` +* `q` for position +* `motor` is the motor number, `0` or `1`. +* `position` is the desired position, in encoder counts. +* `velocity_lim` is the velocity limit, in counts/s (optional). +* `current_lim` is the current limit, in A (optional). + +Example: `q 0 -20000 10000 10` + ``` p motor position velocity_ff current_ff ``` @@ -90,3 +104,8 @@ Not all parameters can be accessed via the ASCII protocol but at least all param * `property` name of the property, as seen in ODrive Tool * `value` text representation of the value to be written * Example: `w axis0.controller.pos_setpoint -123.456` + +#### System commands: +* `ss` - Save config +* `se` - Erase config +* `sr` - Reboot diff --git a/docs/getting-started.md b/docs/getting-started.md index 1a346bd8..982ec861 100644 --- a/docs/getting-started.md +++ b/docs/getting-started.md @@ -261,7 +261,7 @@ You can also directly control the current of the motor, which is proportional to ### Trajectory control -Set `axis.controller.config.control_mode = CTRL_MODE_TRAJECTORY_CONTROL`.
+While in position control mode, use the `move_to_pos` or `move_incremental` functions. See the **Usage** section for details
This mode lets you smoothly accelerate, coast, and decelerate the axis from one position to another. With raw position control, the controller simply tries to go to the setpoint as quickly as possible. Using a trajectory lets you tune the feedback gains more aggressively to reject disturbance, while keeping smooth motion. ![Taptraj](TrapTrajPosVel.PNG)
@@ -291,9 +291,18 @@ Keep in mind that you must still set your safety limits as before. I recommend #### Usage Use the `move_to_pos` function to move to an absolute position: ``` -..controller.move_to_pos() +..controller.move_to_pos(your_absolute_pos) ``` +Use the `move_incremental` function to move to a relative position. +To set the goal relative to the current actual position, use `from_goal_point = False` +To set the goal relative to the previous destination, use `from_goal_point = True` +``` +..controller.move_incremental(pos_increment, from_goal_point) +``` + +You can also execute a move with the [appropriate ascii command](ascii-protocol.md#motor-trajectory-command). + ### Circular position control To enable Circular position control, set `axis.controller.config.setpoints_in_cpr = True`