Intro: Controlling Servos on FPGA
Currently I'm working on building a claw machine, much like those that plagued your childhood at movie theaters, arcades and grocery stores. I know for me many hours were spent yearning for the toy on the top of the pile, only to find out that the claw could not grasp it. I'd now like to exact my revenge on the universe by producing yet another of these such devices.
Since I am going to school for Electrical Engineering and have some experience with FPGAs, I've decided that it would be best to use an FPGA, specifically the Basys 3 to act as the brain.
To control the opening and closing action of the claw. I am going to use a servo.
The output pins of the Basys 3 can't supply enough current to directly power the servos in any useful fashion so I've decided to use the PmodCON3 as an external power source interface.
This Instructable with go through the basics of getting the FPGA to send the correct signals to the servo so that the user can control it by sending a degree value, rather than the PWM signal that it needs. For demonstration purposes this project assigns a degree value to each switch going from 0 to 360 degrees in 24 degree increments.
Step 1: Gather Your Materials
What you'll need:
This is the servo I used. If you use a different servo that is find but you may have to change your constants and equation to go from degree to constant.
Step 2: Servo Background Knowledge
Servos require a square wave of different pulse widths to operate. This is called Pulse Width Modulation.
In the image I have two PWM signals. A PWM wave has two important characteristics.
The first characteristic is the frequency. This is one over the period T. The period is the time from when the signal changes from high to low, to the next time the signal changes from high to low. You can see the period labeled on the image as T.
The second characteristic is the pulse width. This is how long the signal is high within one period. People usually talk about this as in duty cycle. Duty cycle is the percentage of T that the signal is high. So if T is 10ms and it is high 5ms you have 50% duty cycle. Standard non PWM square waves have 50% duty cycle.
For servo control T is the refresh rate, or how often the servo needs to see the high signal in order to stay holding a value. The duty cycle defines what angle the servo will be at.
The refresh rate that's required depends on the servo, I used 10ms which is usually a safe bet for most servos. The way the duty cycle corresponds to an angle depends on which specific servo you are using. I used two points, 0 and 180 degrees to create an equation of angle to duty cycle. I found those two first points via trial and error. If you do this though, be careful, not all servos have built in protection if you go above or below the allowable range. Luckily this one did. I discovered this when I tried to go above 180 degrees.
You can see the general idea of how the PWM signal relates to servo position above. If I have some duty cycle above the zero point I will get the servo to hold at some angle. If I have a larger duty cycle, the servo will go some angle farther. The exact details and relationship depend on the servo.
Step 3: How the Code Works
In my code I have my top module, represented in the image by the dotted square, which inputs switches, a button for clear, and the system clock.
Within the larger top module I have a counter, comparator, switch to angle decoder, and angle to constant value decoder.
The counter takes in the system clock and clear. Every clock cycle it increments a count value until it hits a certain constant value. This value is what is needed to get the appropriate frequency. You can find the equation for that commented in the code. Once it reaches that value it resets. So, it counts to the constant and then goes back to zero. This controls the frequency.
The switch to angle decoder takes in a switch value and maps it to an angle value.
The angle decoder takes in an angle value and maps it to a constant value that will get the appropriate duty cycle. That equation is also commented in the code.
The comparator then takes in the count value, and constant value from the angle decoder. If the count value is less than the constant than the output is 1, otherwise the output is zero. This creates the PWM signal.
You can see that illustrated in the second image.
If you want to use the angle as an input rather than the switches you can remove the switch to angle decoder. If you want to use more than one servo, you can instantiate multiple servo controller modules in a higher top module.
Step 4: Download the Code and Open the Project
Now that you know how servos and the code works you can use the code.
Download the zip file attached to this step and unzip it.
Open the project in Vivado.
Step 5: Generate the Bitstream and Program the Board
Plug in your Basys 3 board and turn it on.
Click Generate bitstream to sythesize, implement and generate the bit file for the design.
Open the hardware manager and program the board.
Step 6: Put All the Pieces Together
Plug the PmodCON3 into the top level of Pmod Connector C.
Plug the servo into the top row of connectors on the PmodCON3, paying close attention to which is ground, power, and the data signal.
Change the switches to change the angle that the servo is at.
The servo I used can only go from 0 to 180 degrees so some of the switches are not necessary. If you have a servo that goes 0 to 360 then you may be able to use those switches.
Again remember that if you have a different servo you may have to change the equation that maps angle to constant.
Now use the code in your own design!
If you'd like to hear more about my progress on creating the claw machine, keep following blog.digilentinc.com.