This repository contains a Zephyr RTOS based application for controlling servo motors via UART commands.
A companion app providing a web GUI is available under pkoscik/servo-ctrl-zephyr-gui-flask
.
Ensure that the Zephyr SDK and west
tool are installed. For setup instructions, refer to the Zephyr Getting Started Guide.
west init -m https://github.com/pkoscik/servo-ctrl-zephyr servo-ctrl-zephyr
cd servo-ctrl-zephyr
west update
Note
This payload expects the servo{1,2,3}
devicetree nodes to be configured. An example overlay file can be found in the nucleo_f767zi.overlay file. The following instructions will assume this board as a target.
west build -b nucleo_f767zi app
west flash --runner openocd
Warning
As part of the servo bootstrapping routine, the binary will set the servos to their mid-point upon reboot. Please be aware of the robot's dynamics and working envelope during reboots.
Send commands via UART to control the servos. The expected command format is:
S{id}:{position}\n
where:
id
is the servo ID (0, 1, or 2)position
is the desired position percentage (0-100)
For example, sending S0:50
will set servo 0 to 50% of its range.
The (optional) UART output can be used for diagnosing issues with the board during initialization and operation. Below is an example of the output from a properly functioning board:
*** Booting Zephyr OS build v4.0.0 ***
[INFO] set_servo_pulse_safe: Setting channel: 1 to width: 1440000
[INFO] set_servo_pulse_safe: Setting channel: 2 to width: 1600000
[INFO] set_servo_pulse_safe: Setting channel: 3 to width: 1600000
After inputting a position, a confirmation message will be displayed:
# S2:0
[INFO] set_servo_pulse_safe: Setting channel: 3 to width: 700000
Incorrect inputs that could cause hardware damage will result in an error message being displayed, followed by a kernel panic:
# S10:0
[ERROR] set_servo_pulse_safe: Servo ID out of range: 10 (max 3)
[00:00:04.173,000] <err> os: r0/a1: 0x00000004 r1/a2: 0x35bb5418 r2/a3: 0x00000000
[00:00:04.173,000] <err> os: r3/a4: 0x00000004 r12/ip: 0x00005460 r14/lr: 0x080007b9
[00:00:04.173,000] <err> os: xpsr: 0x01000000
[00:00:04.173,000] <err> os: Faulting instruction address (r15/pc): 0x080007c8
[00:00:04.173,000] <err> os: >>> ZEPHYR FATAL ERROR 4: Kernel panic on CPU 0
[00:00:04.173,000] <err> os: Current thread: 0x20020670 (unknown)
[00:00:04.224,000] <err> os: Halting system
# S1:150
[ERROR] set_servo_pulse_safe: Requested pulse out of reach: 3400000 (range: 700000 - 2500000)
[00:00:28.394,000] <err> os: r0/a1: 0x00000004 r1/a2: 0x6d904075 r2/a3: 0x00000001
[00:00:28.394,000] <err> os: r3/a4: 0x00000004 r12/ip: 0x00005460 r14/lr: 0x0800052f
[00:00:28.394,000] <err> os: xpsr: 0x01000000
[00:00:28.394,000] <err> os: Faulting instruction address (r15/pc): 0x0800053e
[00:00:28.394,000] <err> os: >>> ZEPHYR FATAL ERROR 4: Kernel panic on CPU 0
[00:00:28.394,000] <err> os: Current thread: 0x20020670 (unknown)
[00:00:28.447,000] <err> os: Halting system
The board will need to be reset following such an incident.
Parse errors (and, in the future, other non-critical errors) will return an error message:
# foo:bar
e001: Invalid input format.
In this case, the payload will continue to operate without the need for a reset.
This project has been tested with the Nucleo F767ZI board.
The servos use PWM channels 1-3 derived from the TIMER2
timer. The signals are pin-muxed to the following pins:
- Channel 1:
pa5
(CN7, top right) - Channel 2:
pb3
(CN7, top left) - Channel 3:
pb10
(CN10, bottom right)