Copyright © Astro Designs Ltd. Registered office, Marlborough, Wilts. England

Mail: info@astro-designs.com?subject=Astro Designs Website (astro-designs.com)

What you can do with the PiXi - No. 3

A few extra PWM Controllers for the Raspberry Pi


PWM, or Pulse-Width Modulation is a form of electronic signal that’s frequently used for motor speed control and positional control in servos, not to mention lots of other applications. It’s frequently used in robotics, and radio-control modelling. Adding PWM controllers to the Raspberry Pi is hardly a new concept but using an FPGA to create a custom PWM controller for the Raspberry Pi is far from being a common way of doing it but it’s a great little example of what you can achieve when you put an FPGA and the Raspberry Pi together. And there’s a interesting twist that we’ll come to later…


Firstly, how do we make a PWM controller?


In the analogue world, a basic PWM controller - the kind that’s used for motor speed control and servo control, is based around a saw-tooth oscillator and a comparator. The comparator compares the saw-tooth signal to a reference voltage and produces a square output signal where the duty-cycle of the comparator output varies with the fixed voltage applied to the comparator. So if we wanted to control a simple radio-control or ‘hobby’ servo then we just need to vary the reference voltage and this changes the duty-cycle of the pwm signal and this in turn controls the position of the servo.



In the digital world we do exactly the same. The saw-tooth oscillator is replaced with a digital counter and the analogue comparator is replaced with a digital comparator that compares the output value of the counter to a value that represents the reference or control signal. The output signal from the digital comparator is a square wave where the duty-cycle of the waveform varies with the reference or control signal applied to the input of the comparator.



For this example, to implement this within the FPGA we use a Hardware Definition Language (HDL) known as VHDL to define the counter and the comparator and connect them together. Here’s an example of a PWM controller written in VHDL:


pwm_ctrl : process(clock)

   – [comment] simple saw-tooth waveform (counter):

   if rising_edge(clock) then

      counter <= counter + 1 mod 1024;

   end if;


   – [comment] comparator:

   if reference >= counter then

      pwm <= ‘1’;

   else

      pwm <= ‘0’;

   end if;


end process;


– [comment] Connect the pwm signal to a GPIO output:

GPIO(0) <= pwm;


And there we have it, a simple PWM controller that can be implemented in an FPGA. No components, wires, or soldering, (although in a way that is removing half of the fun…) just a few lines of HDL code and we’ve created a 10-bit counter and a 10-bit comparator. All that’s needed is to connect the pwm signal to a GPIO pin on the FPGA use connect this pin on the circuit board to a connector that’ll provide a means of connecting our PWM signal to out load such as a small servo or a H-bridge motor driver and we have a functioning PWM controller that’s capable of controlling the position of a servo or the speed of a motor. Actually there’s one more thing we need to do, well two actually… The signal out of the FPGA is 3.3V so it would help to increase the signal swing from 3.3V to 5V or even 6V - or whatever the supply is to the servo or H-bridge. The easiest way to do this is with an NPN transistor:



Unfortunately the action of the NPN transistor effectively inverts the pwm waveform so ideally we could do with inverting this again to make it all right. All we need to do is invert the GPIO output within the FPGA like this:


GPIO(0) <= not pwm;


Or we could use


GPIO(0) <= ‘1’ when pwm = ‘0’ else ‘0’;


All together, that’s very little HDL code to have to write to create our very own PWM controller.


One thing to note is the clock frequency. Assuming we want a 50Hz pwm signal, this means the saw-tooth ‘counter’ will need to run at 50Hz x 2^10 (or 50Hz x 1024) which works out to 51.2kHz. Generating a clock frequency like this is something else that we can do with relative ease within the FPGA but we can look at how to do this in detail some other time.


Now here’s the twist we mentioned earlier. There are 56 potential outputs on the PiXi FPGA that go to external GPIO headers, why not create a PWM output for each pin? There’s easily enough resources within the FPGA to do this. We could do this by replicating this code 56 times, simply by copying the code and changing the GPIO number used for the output and giving each controller it’s own reference that allow us to control each PWM controller independently. Or we could use the VHDL ‘generate’ construct to do this for us. Here’s the same PWM controller wrapped inside a VHDL generate statement:


pwm_gen : for i in 0 to 55 generate

   signal pwm : std_logic;

begin

   Process(clock)

      – [comment] simple saw-tooth waveform (counter):

      if rising_edge(clock) then

         counter <= counter + 1 mod 1024;

      end if;


      – [comment] comparator:

      if reference(i) >= counter then

         pwm <= ‘1’;

      else

         pwm <= ‘0’;

      end if;


   End process;


   – [comment] connect the pwm signal to a GPIO output

   – and invert the signal to compensate for an external npn transistor:

   GPIO(i) <= not pwm;


end generate;


In this code we have 56 GPIO signals and 56 different references. “reference(i)” represents an array of independent reference numbers or signals. The important thing to note here is that the generate statement has created 56 completely separate pwm controllers in around 20 lines of HDL code. How many separate add-on boards would you need to do this or how many hours of work would have to go into wiring them up if you didn’t have the power of an FPGA at your disposal?


So there you have it, if you’ve not come across VHDL or Verilog Hardware Definition Languages (HDL) before, that’s a very quick intro into the kind of thing you can do. We’ll provide a better introduction into designing with FPGAs in another application note but for now we thought this snippet might be a good taster. The code needs to be “compiled” by the FPGA tools before being down-loaded into the FPGA but once there, you’ll have 56 working PWM controllers. Something else worth noting if you’re new to HDL, while the code above can look a little like software, this isn’t software and the FPGA isn’t running a program like a computer runs software. The code listed above gets translated into physical logic gates that exist within the FPGA. These logic gates have been interconnected using programmable ‘wires’ or ‘interconnects’ to create a physical electronic circuit. And what’s more, if you wish to add to the design or if make a mistake then you simply download a new configuration with any changes you’d like, over and over again!


The default configuration for the PiXi FPGA provides a optional PWM output on each output. All you need to do is to set the mode for each I/O pin to pwm mode and you have upto 56 pwm outputs at your disposal. We created this demonstration a little while back to demonstrate this: URL: https://www.youtube.com/watch?v=cVbOd15ufTI


The above examples simplify it a little bit. We’ve not shown it here but the clock frequency used to generate the saw-tooth (counter) waveform in the PiXi FPGA is user-adjustable. It defaults to 50Hz which is typically the frequency needed for radio-control servos but it can run slower if needed and it can also run faster at up to several kilo-Hertz. Also, it’s a relatively simple exercise to change it from a 10-bit PWM controller to 8-bit, 9-bit or anything up to 16-bit for better resolution.


That’s all we want to say about pwm outputs for now, thanks for reading :o)


So what else could you do with an FPGA and a Raspberry Pi? The next example will look at PWM capable inputs…