One way around the problem of getting a fast response from a microcontroller is to move the problem away from the processor. In the case of the Pi's processor there are some builtin devices that can use GPIO lines to implement protocols without the CPU being involved. In this chapter we take a close look at pulse width modulation PWM including, sound, driving LEDs and servos.
Now On Sale!
You can now buy a print or ebook edition of Raspberry Pi IoT in C from Amazon.
For Errata and Listings Visit: IO Press
This our ebook on using the Raspberry Pi to implement IoT devices using the C programming language. The full contents can be seen below. Notice this is a first draft and a work in progress.
Chapter List
-
Introducing Pi (paper book only)
-
Getting Started With NetBeans In this chapter we look at why C is a good language to work in when you are creating programs for the IoT and how to get started using NetBeans. Of course this is where Hello C World makes an appearance.
-
First Steps With The GPIO
The bcm2835C library is the easiest way to get in touch with the Pi's GPIO lines. In this chapter we take a look at the basic operations involved in using the GPIO lines with an emphasis on output. How fast can you change a GPIO line, how do you generate pulses of a given duration and how can you change multiple lines in sync with each other? -
GPIO The SYSFS Way
There is a Linux-based approach to working with GPIO lines and serial buses that is worth knowing about because it provides an alternative to using the bcm2835 library. Sometimes you need this because you are working in a language for which direct access to memory isn't available. It is also the only way to make interrupts available in a C program. -
Input and Interrupts
There is no doubt that input is more difficult than output. When you need to drive a line high or low you are in command of when it happens but input is in the hands of the outside world. If your program isn't ready to read the input or if it reads it at the wrong time then things just don't work. What is worse is that you have no idea what your program was doing relative to the event you are trying to capture - welcome to the world of input. -
Memory Mapped I/O
The bcm2835 library uses direct memory access to the GPIO and other peripherals. In this chapter we look at how this works. You don't need to know this but if you need to modify the library or access features that the library doesn't expose this is the way to go. -
Near Realtime Linux
You can write real time programs using standard Linux as long as you know how to control scheduling. In fact it turns out to be relatively easy and it enables the Raspberry Pi to do things you might not think it capable of. There are also some surprising differences between the one and quad core Pis that make you think again about real time Linux programming. -
PWM
One way around the problem of getting a fast response from a microcontroller is to move the problem away from the processor. In the case of the Pi's processor there are some builtin devices that can use GPIO lines to implement protocols without the CPU being involved. In this chapter we take a close look at pulse width modulation PWM including, sound, driving LEDs and servos. -
I2C Temperature Measurement
The I2C bus is one of the most useful ways of connecting moderately sophisticated sensors and peripherals to the any processor. The only problem is that it can seem like a nightmare confusion of hardware, low level interaction and high level software. There are few general introductions to the subject because at first sight every I2C device is different, but here we present one. -
A Custom Protocol - The DHT11/22
In this chapter we make use of all of the ideas introduced in earlier chapters to create a raw interface with the low cost DHT11/22 temperature and humidity sensor. It is an exercise in implementing a custom protocol directly in C. -
One Wire Bus Basics
The Raspberry Pi is fast enough to be used to directly interface to 1-Wire bus without the need for drivers. The advantages of programming our own 1-wire bus protocol is that it doesn't depend on the uncertainties of a Linux driver. -
iButtons
If you haven't discovered iButtons then you are going to find of lots of uses for them. At its simples an iButton is an electronic key providing a unique coce stored in its ROM which can be used to unlock or simply record the presence of a particular button. What is good news is that they are easy to interface to a Pi. -
The DS18B20
Using the software developed in previous chapters we show how to connect and use the very popular DS18B20 temperature sensor without the need for external drivers. -
The Multidrop 1-wire bus
Some times it it just easier from the point of view of hardware to connect a set of 1-wire devices to the same GPIO line but this makes the software more complex. Find out how to discover what devices are present on a multi-drop bus and how to select the one you want to work with. -
SPI Bus
The SPI bus can be something of a problem because it doesn't have a well defined standard that every device conforms to. Even so if you only want to work with one specific device it is usually easy to find a configuration that works - as long as you understand what the possibilities are. -
SPI MCP3008/4 AtoD (paper book only)
-
Serial (paper book only)
-
Getting On The Web - After All It Is The IoT (paper book only)
-
WiFi (paper book only)
The GPIO lines at their most basic output function can be set high or low by the processor. How fast they can be set high or low depends on the speed of the processor.
Using the GPIO line in its Pulse Width Modulation (PWM) mode you can generate pulse trains up to 4.8MHz, i.e. pulses as short as just a little more than 0.08 microseconds. You can even go faster if you are prepared to do some additional work.
The reason for the increase in speed is that the GPIO is connected to a pulse generator and once set to generate pulses of a specific type the pulse generator just gets on with it without needing any intervention from the GPIO line or the processor. In fact the pulse output can continue after your program has ended if you forget to reset it.
Of course, even though the PWM line can generate pulses as short as 0.1 microseconds, it can only change the pulses it produces each time that processor can modify it. For example, you can't use PWM to produce a single 0.1 microsecond pulse because you can't disable the PWM generator in just 0.1 microsecond.
Some Basic Pi PWM Facts
There are some facts worth getting clear right from the start, although some of the meanings will only become clear as we progress.
First what is PWM?
The simple answer is that a Pulse Width Modulated signal has pulses that repeat at a fixed rate - say one pulse every millisecond but the width of the pulse can be changed.
There are two basic things to specify about the pulse train that is generated - its repetition rate and the width of each pulse. Usually the repetition rate is set as a simple repeat period and the width of each pulse is specified as a percentage of the repeat period the duty cycle.
So for example a 1ms repeat and a 50% duty cycle specifies a 1ms period which is high for 50% of the time i.e. a pulse width of 0.5ms. The two extremes are 100% duty cycle i.e. the line is always high and 0% duty cycle i.e. the line is always low.
Notice it is the duty cycle that carries the information in PWM and not the frequency.
What this means is that generally you select a repeat rate and stick to it and what you change as the program runs is the duty cycle.
In many cases PWM is implemented using special PWM generator hardware that is built either into the processor chip or provided by an external chip. The processor simply sets the repeat rate by writing to a register and then changes the duty cycle by writing to another register. This generally provides the best sort of PWM with no load on the processor and generally glitch free operation. You can even buy addon boards that will provide additional channels of PWM without adding to the load on the processor.
The alternative to dedicated PWM hardware is to implement it in software. You can quite easily work out how to do this. All you need is to set a timing loop to set the line high at the repetition rate and then set it low again according to the duty cycle. You can implement this either using interrupts or a polling loop or even in more advanced ways such as using a DMA channel .
In the case of the Pi the PWM lines are implemented using special PWM hardware.
The big problem is that although there are two PWM implementations both are only available on the Pi2/3 and even in this case the second PWM is used for sound generation.
However as long as you don't want to use sound you can use both PWM channels and this is enough to run two servos or motor say.
The main PWM channel zero is brought out on the connector on pin12 via GPIO 18. The secondary channel which is also used by the system for sound generation is brought out on the connector on pin 35 via GPIO 13. As already mentioned you can only use GPIO 13 if you don't want sound generation.
Both PWM lines are driven by the same clock and this sometime causes people to conclude that the two lines must work at the same repeat rate. Although there are some restrictions both PWM lines can be set to their own repeat rate.
Two PWM lines is limiting and often forces users to either use hardware expansion or implement PWM in software.
As you can guess - there are no PWM inputs, just the one output. If for some reason you need to decode or respond to a PWM input then you need to program it using the GPIO input lines and the pulse measuring techniques introduced in the previous chapters.
The PWM Modes Mark/Space and Balanced
The PWM hardware is more sophisticated than you might have encountered before.
The first big difference is that it can work in two modes - mark/space or balanced. In fact there are even more options but these are the only two that have a common use.
In mark/space mode you simply have a repeat rate and a duty cycle. This is precisely what you need if you want to drive a traditional PWM device such as a servo motor. However for other applications where the PWM signal is being used as a simple D to A convertor then this is not the best way to send out a pulse train with a given duty cycle.
For example suppose you want 1KHz pulse train with a 50% duty cycle pulse train to say deliver 50% power or voltage to a device. The mark/space way of doing this switches the GPIO line on for 500 microseconds and off for 500 microseconds. The fluctuations in voltage are very slow and this causes problems for the driven device. A better way would be to divide the time into say 1 microsecond blocks and spread the on and off times throughout the block. In this case the device would be high for 1 microsecond and low for one microsecond and the filtering problems would be much easier to solve.
This idea of distributing the duty cycle over the full repeat period is what balanced mode implements. It is much more suitable to applications such as DtoA conversion and driving loads such as LEDs or motors.
The clock that is supplied to the PWM hardware doesn't set the repeat rate but the smallest unit of change on the PWM output line. In balanced mode it specifies the shortest high or low times for the pulse train.
The way that this works is that you specify a repeat rate in terms of a range parameter which is used to count down to zero at the clock rate. For example, if you set a clock rate of 1KHz and a range of 1024 then the repeat rate is 1/1024 KHz i.e. 0.99Hz - because the PWM cycle starts over after 1024 clock pulses.
In mark/space mode a 50% duty cycle would simply mean holding the line high for 512 clock pulses and then low for 512 clock pulses and so on.
In balanced mode a 50% duty cycle would mean pulses 500 microseconds high and 500 microseconds low. Note that the repeat rate would still be 0,99Hz but the signal would be much higher frequency even though it was a 50% duty cycle.
It is clear that the range sets the repeat rate. What sets the duty cycle? The answer is there is a data parameter which specifies how long the line should be held high. So for example if range is 1024 and data is 512 the duty cycle is 50%. In mark/space mode the line is held high for the first 512 counts and low for the remainder of the 1024 counts. In balanced mode the line is held high for 512 counts spread over the the total 1024 counts.
Obviously using this way of specifying repeat rate and duty cycle means that you can select more than one range and data value for any given duty cycle. For example a range of 4 and data of 2 is also a 50% duty cycle. So how do you choose a suitable pair of values.
The range gives you the possible number of duty cycle steps you can use. For example for a range of 2 you modify the duty cycle to 0, 50 or 100% by setting data to 0,1 or 2. A range of 512 gives you 512 steps and is usually called 8 bit PWM and a range of 1024 gives you 1024 duty cycle steps and is usually called 16 bit PWM.
So to summarize
- The PWM clock gives the smallest unit of change of the PWM line.
- The range gives the repeat rate of the pulse train
- repeat frequency = clock frequency/(2*range)
- The range gives the resolution of the duty cycle 1/range% or the number of duty cycle steps that are available.
- If you want to set duty cycle d% then data=range*d/100
You can now see why the clock frequency being supplied to both PWM units doesn't constrain them to the same repeat rate. They can work at different rates as long as they can tolerate different duty cycle resolutions and hence range values.
- Prev
- Next >>