By Adam Taylor

Many embedded systems are required to generate PWM (pulse-width modulated) signals, so I thought it would be a good idea to explain how you can do this using the Zynq SoC. I am going to show how to interface with a servomotor as a real-world example. Servomotors are used in applications such as robotics and advanced manufacturing. The way we interface with different servomotors varies depending on use, type, and cost. A servomotor interface can be either digital—in the form of a CAN or Modbus connection—or analog—like a PWM signal as mentioned above.

For this example, we are going to interface to a simple RC servo, which uses an analog PWM signal to drive the motor’s position. We can generate PWM signals directly from the Zynq SoC’s PS (processor system) using the Zynq SoC’s TTC (Triple Timer Counter).

Reviewing the TTC’s architecture, you will see that each of the three timers can generate a Wave-Out. For the first TTC, Wave-Out can be output either via the MIO or EMIO pins on the Zynq SoC, but the remaining two counters can only output this signal via EMIO.

For this example, we will be using the MicroZed board mounted on an I/O Carrier Card with the servos connected to one of the carrier card’s PMOD ports. Therefore, I will use the EMIO pins for all 6 TTC wave outputs. This means that we can drive up to 6 servos. In this example, I will use only two servos. Two servos allow me to demonstrate that I can use the software to ensure that the servos do not conflict with each other. Scaling up from two servos to six, or any number in between is then very straightforward.

As always, the first thing we need to do is create a hardware design within Vivado. After three years of the MicroZed Chronicles, you should be very familiar with this process. Create a new project in Vivado and add a block diagram with the Zynq Processing System contained within. With this added, we can quickly and easily set up the two available TTCs and enable the wave outs to be routed via the EMIO. It is then a simple case of directing these wave outputs to the Zynq PL’s I/O using a constraints file.

Enabling the TTC’s and directing them to EMIO

A very simple Zynq system for driving the Servo

With the bit file generated and exported for use in SDK, all we need to do now is understand how to drive the servo. We know it will use the PWM output for control, but we don’t know the specifics. The interface with the servo is very simple. There are three wires connected to most RC servos, two of these are power and ground while the third is the control wire uses to command the servo’s position. We use this wire to drive the motor to a position between -90 and +90 degrees, with 0 degrees being the neutral position. We command the servo to change its position by generating a PWM signal with a 20msec period between pulses. The pulse’s duty cycle is very low, varying from 2.5% to 12.5%. If we wish the servo to remain in the neutral position of 0 degrees, we must generate a 1.5msec pulse every 20msec. Moving to either extreme of +/-90 degrees is possible by either adding or subtracting 1msec to the pulse width used to achieve the neutral position.

In the next blog we will look at the software we need to generate this interface.

Code is available on Github as always.

If you want E book or hardback versions of previous MicroZed chronicle blogs, you can get them below.

First Year E Book here

First Year Hardback here

Second Year E Book here

Second Year Hardback here

All of Adam Taylor’s MicroZed Chronicles are cataloged here.