
Practical Electronic Recipes
with Arduino and Raspberry Pi
Copyright © 2017 Simon Monk. All rights reserved.
Printed in the United States of America.
Published by O’Reilly Media, Inc., 1005 Gravenstein Highway North, Sebastopol, CA 95472.
O’Reilly books may be purchased for educational, business, or sales promotional use. Online editions are also available for most titles (http://oreilly.com/safari). For more information, contact our corporate/institutional sales department: 800-998-9938 or corporate@oreilly.com.
See http://oreilly.com/catalog/errata.csp?isbn=9781491953402 for release details.
The O’Reilly logo is a registered trademark of O’Reilly Media, Inc. Electronics Cookbook, the cover image of an elephantnose fish, and related trade dress are trademarks of O’Reilly Media, Inc.
While the publisher and the author have used good faith efforts to ensure that the information and instructions contained in this work are accurate, the publisher and the author disclaim all responsibility for errors or omissions, including without limitation responsibility for damages resulting from the use of or reliance on this work. Use of the information and instructions contained in this work is at your own risk. If any code samples or other technology this work contains or describes is subject to open source licenses or the intellectual property rights of others, it is your responsibility to ensure that your use thereof complies with such licenses and/or rights.
978-1-491-95340-2
[LSI]
Traditional wisdom requires people using electronics to have at least an EE degree before they can do anything useful, but in this book the whole subject of electronics is given the highly respected O’Reilly Cookbook treatment and is broken down into recipes. These recipes make it possible for the reader to access the book at random, following the recipe that solves their problem and learning as much or as little about the theory as they are comfortable with.
While it is impossible to cover in one volume everything in a complex and wide-ranging subject like electronics, I have tried to select recipes that seem to come up most frequently when I talk to other makers, hobbyists, and inventors.
If you are into electronics or want to get into electronics, then this is the book that will help you get more from your hobby. The book is full of built-and-tested recipes that you can trust to do just what you need them to do, no matter what your level of expertise.
If you are new to electronics then this book will serve as a guide to get you started; if you are an experienced electronics maker, it will act as a useful reference.
This book has been gestating for a while. I believe that the original concept came from no less a person than Tim O’Reilly himself. The idea was to fill the gap in the market between books like the Arduino Cookbook and the Raspberry Pi Cookbook and heavyweight electronics textbooks.
In other words, to cover more of the fundamentals of electronics and topics peripheral to the use of microcontrollers that often get neglected, except in heavyweight electronic tomes. Topics such as how to construct various types of power supply, using the right transistor for switching, using analog and digital ICs, as well as how to construct projects and prototypes and use test equipment.
Boards like the Arduino and Raspberry Pi have lured whole new generations of makers, hobbyists, and inventors into the world of electronics. Components and tools are now low cost and within the reach of more people than at any time in history. Hackspaces and Fab Labs have electronic workstations where you can use tools to realize your projects.
The free availability of information including detailed designs means that you can learn from and adapt other people’s work for your own specific needs.
Many people who start with electronics as a hobby progress to formal education in electronic engineering, or just jump straight to product design as an inventor and entrepreneur. After all, if you have access to a computer and a few tools and components, you can build a working prototype of your great invention and then find someone to manufacture it for you, all financed with the help of crowdfunding. The barrier of entry to the electronics business is at an all-time low.
As a “cookbook” you can dive in and use any recipe, rather than read the book in order. Where you have a recipe that relies on some knowledge or skills from another recipe, there will be a link back to the prerequisite recipe.
The recipes are arranged in chapters, with Chapters 1 to 6 providing more fundamental recipes, some concerning theory but mostly about different types of component (your recipe ingredients). These chapters are:
The next section of chapters looks at how the components introduced in the first section can be used together in various recipes covering pretty much anything electronic that you might like to design.
The final section of the book contains recipes for construction and the use of tools.
The book also includes appendices that list all the parts used in the book along with useful suppliers and provide pinouts for devices including the Arduino and Raspberry Pi.
There are many wonderful resources available for the electronics enthusiast.
If you are looking for project ideas then sites like Hackaday and Instructables are a great source of inspiration.
When it comes to getting help with a project, you will often get great advice from the many experienced and knowledgable people that hang out on the following forums. Remember to search the forum before asking your question, in case it has come up before (usually it has) and always explain your question clearly, or “experts” can get impatient with you.
The following typographical conventions are used in this book:
Indicates new terms, URLs, email addresses, filenames, and file extensions.
Constant widthUsed for program listings, as well as within paragraphs to refer to program elements such as variable or function names, databases, data types, environment variables, statements, and keywords.
Constant width boldShows commands or other text that should be typed literally by the user.
Constant width italicShows text that should be replaced with user-supplied values or by values determined by context.
This element signifies a tip or suggestion.
This element indicates a warning or caution.
Supplemental material (code examples, exercises, etc.) is available for download at https://github.com/simonmonk/electronics_cookbook.
This book is here to help you get your job done. In general, if example code is offered with this book, you may use it in your programs and documentation. You do not need to contact us for permission unless you’re reproducing a significant portion of the code. For example, writing a program that uses several chunks of code from this book does not require permission. Selling or distributing a CD-ROM of examples from O’Reilly books does require permission. Answering a question by citing this book and quoting example code does not require permission. Incorporating a significant amount of example code from this book into your product’s documentation does require permission.
We appreciate, but do not require, attribution. An attribution usually includes the title, author, publisher, and ISBN. For example: “Electronics Cookbook by Simon Monk (O’Reilly). Copyright 2017 Simon Monk, 978-1-491-95340-2.”
If you feel your use of code examples falls outside fair use or the permission given above, feel free to contact us at permissions@oreilly.com.
Safari (formerly Safari Books Online) is a membership-based training and reference platform for enterprise, government, educators, and individuals.
Members have access to thousands of books, training videos, Learning Paths, interactive tutorials, and curated playlists from over 250 publishers, including O’Reilly Media, Harvard Business Review, Prentice Hall Professional, Addison-Wesley Professional, Microsoft Press, Sams, Que, Peachpit Press, Adobe, Focal Press, Cisco Press, John Wiley & Sons, Syngress, Morgan Kaufmann, IBM Redbooks, Packt, Adobe Press, FT Press, Apress, Manning, New Riders, McGraw-Hill, Jones & Bartlett, and Course Technology, among others.
For more information, please visit http://oreilly.com/safari.
Please address comments and questions concerning this book to the publisher:
We have a web page for this book, where we list errata, examples, and any additional information. You can access this page at http://bit.ly/electronics-cookbook.
To comment or ask technical questions about this book, send email to bookquestions@oreilly.com.
For more information about our books, courses, conferences, and news, see our website at http://www.oreilly.com.
Find us on Facebook: http://facebook.com/oreilly
Follow us on Twitter: http://twitter.com/oreillymedia
Watch us on YouTube: http://www.youtube.com/oreillymedia
Thanks to Duncan Amos, David Whale, and Mike Bassett for their technical reviews of the book and the many useful comments that they provided to help make this book as good as it could be.
I’d also like to thank Afroman for permission to use his great FM transmitter design and the guys at Digi-Key for their help in compiling parts codes.
As always, it’s been a pleasure working with the professionals at O’Reilly, in particular Jeff Bleiel, Heather Scherer, and of course, Brian Jepson.
Although this book is fundamentally about practice rather than theory, there are a few theoretical aspects of electronics that are almost impossible to avoid.
In particular, if you understand the relationship between voltage, current, and resistance many other things will make a lot more sense.
Similarly, the relationship between power, voltage, and current crops up time and time again.
As the word current suggests, the meaning of current in electronics is close to that of the current in a river. You could think of the strength of the current in a pipe as being the amount of water passing a point in the pipe every second. This might be measured in so many gallons per second.
In electronics, current is the amount of charge carried by electrons passing a point in a wire per second (Figure 1-1). The unit of current is the ampere, abbreviated as amp or as unit symbol A.
For a list of units and unit prefixes such as mA, see Appendix D.
To learn more about current in a circuit, see Recipe 1.4.
In Recipe 1.1 you read how current is the rate of flow of charge. That current will not flow without something influencing it. In a water pipe, that might be because one end of the pipe is higher than the other.
To understand voltage, it can be useful to think of it as being similar to height in a system of water pipes. Just like height, it is relative, so the height of a pipe above sea level does not determine how fast the water flows through a pipe, but rather how much higher one end of the pipe is than the other (Figure 1-2).
Voltage might refer to the voltage across a wire (from one end to the other) and in other situations, it might refer to the voltage from one terminal of a battery to another. The common feature is that for voltage to make any sense, it must refer to two points; the higher voltage is the positive voltage, marked with a +.
It is the difference in voltage that makes a current flow in a wire. If there is no difference in voltage between one end of a wire and another then no current will flow.
The unit of voltage is the volt. An AA battery has about 1.5V across its terminals. An Arduino operates at 5V, while a Raspberry Pi operates at 3.3V, although it requires a 5V supply that it reduces to 3.3V.
Sometimes it seems like voltage is used to refer to a single point in an electronic circuit rather than a difference between two points. In such cases the voltage then means the difference between the voltage at one point in the circuit and ground. Ground (usually abbreviated as GND) is a local reference voltage against which all other voltages in the circuit are measured. This is, if you like, 0V.
To learn more about voltages, see Recipe 1.5.
Use Ohm’s Law.
Ohm’s Law states that the current flowing through a wire or electronic component (I) will be the voltage across that wire or component (V) divided by the resistance of the component (R). In other words:
If it is the voltage that you want to calculate, then this formula can be rearranged as:
And, if you know the current flowing through a resistor and the voltage across the resistor, you can calculate the resistance using:
Resistance is the ability of a substance to resist the flow of current. A wire should have low resistance, because you do not usually want the electricity flowing through the wire to be unnecessarily impeded. The thicker the wire, the less its resistance for a given length. So a few feet of thin wire that you might find connecting a battery to a lightbulb (or more likely LED) in a flashlight might have a resistance of perhaps 0.1Ω to 1Ω, whereas the same length of thick AC outlet cable for a kettle may have a resistance of only a couple of milliohms (mΩ).
It is extremely common to want to limit the amount of current flowing through part of a circuit by adding some resistance in the form of a special component called a resistor.
Figure 1-3 shows a resistor (zig-zag line) and indicates the current flowing through it (I) and the voltage across it (V).
Let’s say that we were to connect a 1.5V battery to a 100Ω resistor as shown in Figure 1-4. The Greek letter Ω (omega) is used as shorthand for the unit of resistance (the “Ohm”).
Using Ohm’s Law, the current is the voltage across the resistor divided by the resistance of the resistor (we can assume that the wires have a resistance of zero).
So, I = 1.5 / 100 = 0.015 A or 15mA.
To understand what happens to current flowing through resistors and wires in a circuit, see Recipe 1.4.
To understand the relationship between current, voltage, and power, see Recipe 1.6.
Use Kirchhoff’s Current Law.
Stated simply, Kichhoff’s Current Law says that at any point on a circuit, the current flowing into that point must equal the current flowing out.
For example, in Figure 1-5 two resistors are in parallel and supplied with a voltage from a battery (note the schematic symbol for a battery on the left of Figure 1-5).
At point X, a current of I will be flowing into point X from the battery, but there are two branches out of X. If the resistors are of equal value then each branch will have half the current flowing through it.
At point Y, the two paths recombine and so the two currents of I/2 flowing into Y will be combined to produce a current of I flowing out of Y.
For Kirchhoff’s Voltage Law, see Recipe 1.5.
For further discussion on resistors in parallel, see Recipe 2.5.
Use Kirchhoff’s Voltage Law.
This law states that all the voltages between various points around a circuit will add up to zero.
Figure 1-6 shows two resistors in series with a battery. It is assumed that the two resistors are of equal value.
At first glance it is not clear how Kirchhoff’s Voltage Law applies until you look at the polarity of the voltage. On the left, the battery supplies V volts, which is equal in magnitude, but opposite in direction (and hence sign) to the two voltages V/2 across each resistor.
Another way to look at this is that V must be balanced by the two voltages V/2. In other words, V = V/2 + V/2 or V – (V/2 + V/2) = 0.
This arrangement of a pair of resistors is also used to scale voltages down (see Recipe 2.6).
For Kirchhoff’s Current Law, see Recipe 1.4.
In electronics, power is the rate of conversion of electrical energy to some other form of energy (usually heat). It is measured in Joules of energy per second, which is also known as a watt (W).
When you wire up a resistor as shown back in Figure 1-4 of Recipe 1.3 the resistor will generate heat and if it’s a significant amount of heat then the resistor will get hot. You can calculate the amount of power converted to heat using the formula:
P = I x V
In other words, the power in watts is the voltage across the resistor (in volts) multiplied by the current flowing through it in amps. In the example of Figure 1-4 where the voltage across the resistor is 1.5V and the current through it was calculated as 15mA, the heat power generated will be 1.5V x 15mA = 22.5mW.
If you know the voltage across the resistor and the resistance of the resistor, then you can combine Ohm’s Law and P=IV and use the formula:
With V=1.5V and R of 100Ω the power is 1.5V x 1.5V / 100Ω = 22.5mW.
For Ohm’s Law see Recipe 1.3.
In all the recipes up to this point, DC is assumed. The voltage is constant and generally what you would expect a battery to supply.
AC is what is supplied by wall outlets, and although it can be reduced to lower voltages (see Recipe 3.9) it is generally of a high (and dangerous) voltage. In the US, this means 110V and in most of the rest of the world 220V or 240V.
What puts the alternating in alternating current is the fact that the direction of current flow in AC reverses many times per second. Figure 1-7 shows how the voltage varies in a US AC wall outlet.
The first thing to notice is that the voltage follows the shape of a sine wave, gently increasing until it exceeds 150V then heading down past 0V to around –150V and then back up again, taking about 16.6 thousandths of a second (milliseconds, or ms) to complete one full cycle.
The relationship between the period of AC (time taken for one complete cycle) and the frequency of the AC (number of cycles per second) is:
The unit of frequency is the Hertz (abbreviated as Hz) so you can see that the AC shown in Figure 1-7 has a period of 16.6ms, which is 0.0166 seconds. So you can calculate the frequency as:
You may be wondering why AC from an outlet is described as 110V when it actually manages to swing over a range of over 300V from peak to peak. The answer is that the 110V figure is the equivalent DC voltage that would be capable of providing the same amount of power. This is called the RMS (root mean square) voltage and is the peak voltage divided by the square root of 2 (which is roughly 1.41). So, in the preceding example, the peak voltage of 155V when divided by 1.41 gives a result of roughly 110V RMS.
You will find more information on using AC in Chapter 7.
Resistors are used in almost every electronic circuit, come in a huge variety of shapes and sizes, and are available in a range of values that spans milliohms (thousandths of an ohm) to mega ohms (millions of ohms).
Ohm, the unit of resistance, is usually abbreviated as the Greek letter omega (Ω), although you will sometimes see the letter R used instead. For example, 100Ω and 100R both mean a resistor with a resistance of 100 ohms.
On a through-hole resistor (a resistor with leads) that has colored stripes on it, use the resistor color code.
If your resistor has stripes in the same positions as Figure 2-1 then the three stripes together on the left determine the resistor’s value and the single stripe on the right determines the accuracy of the value.
Each color has a value as listed in Table 2-1.
|
Black |
0 |
|
Brown |
1 |
|
Red |
2 |
|
Orange |
3 |
|
Yellow |
4 |
|
Green |
5 |
|
Blue |
6 |
|
Violet |
7 |
|
Gray |
8 |
|
White |
9 |
|
Gold |
1/10 |
|
Silver |
1/100 |
For a three-stripe resistor such as this, the first two stripes determine the basic value (say 27 in Figure 2-1) and the third stripe determines the number of zeros to add to the end. In the example of Figure 2-1, the value of a resistor with stripes red, purple, and brown is 270Ω. I said before that this stripe indicates the number of zeros, but actually, to be more accurate, it is a multiplier. If it has a value of gold, then this means ⅒ of the value indicated by the first two stripes. So brown, black, and gold would indicate a 1Ω resistor.
The stripe on its own specifies the tolerance of the resistor. Silver (rare these days) indicates ±10%, gold ±5%, and brown ±1%.
If your resistor has stripes as shown in Figure 2-2 then the value of the resistor is specified with an extra digit of precision. In this case, the first three stripes determine the basic value (in the case of Figure 2-2, 270) and the final digit the number of zeros to add (in this case, 0). This resistor is also 270Ω.
For low-value resistors, gold is used as a multiplier of 0.1 and silver of 0.01. A 1Ω four-stripe resistor would have value stripes of brown, black, black, and silver (100 x 0.01).
Through-hole capacitors also have value labels similar to SMT resistors (see Recipe 3.3).
The ±1% E96 series includes all the base values of the E24 series, but has four times as many values. However, it is very rare to need such precise values of resistor.
If your resistor is to limit current to some other component that might be damaged, perhaps limiting the power to an LED (Recipe 4.4) or into the base of a bipolar transistor (Recipe 5.1), then pick the next largest value of resistor from the E24 series.
For example, if your calculations tell you that the resistor should be a 239Ω resistor, then pick a 240Ω resistor from the E24 series.
In reality, you may decide to limit yourself even further to avoid having to gradually collect every conceivable value of resistor, especially as they are often sold in packs of 100. I generally keep the following resistor values in stock: 10Ω, 100Ω, 270Ω, 470Ω, 1k, 3.3k, 4.7k, 10k, 100k, and 1M.
For full details on all of the resistor series available, see http://www.logwell.com/tech/components/resistor_values.html.
A variable resistor, a.k.a. a pot or potentiometer, is made from a resistive track and a slider that varies its position along the track. By varying the position of the slider you can vary the resistance between the slider and either of the terminals at the ends of the track. The most common pots are rotary like the one shown in Figure 2-3.
Pots come in a large variety of shapes and sizes. Figure 2-4 shows a selection of pots.
The two pots on the left of Figure 2-4 are called trimmers or trimpots. These devices are designed to be turned using a screwdriver or by twiddling the tiny knob between the thumb and forefinger.
The next pot is a pretty standard device with a threaded barrel that allows the pot to be fixed into a hole. The shaft can be cut to the length required before fixing a knob to it.
There is a dual-gang pot in the middle of Figure 2-4. This is actually two pots with a common shaft and is often employed in stereo volume controls. After that is a similar looking device that combines a pot with an on/off switch. Finally, on the right is a sliding type of pot, the kind that you might find on a mixing desk.
Pots are available with two types of tracks. Linear tracks have a close to linear resistance across the whole range of the pot. So, at the half-way point the resistance will be half of the full range.
Pots with a logarithmic track increase in resistance as a function of the log of the slider position rather than in proportion to the position. This makes them more suitable to volume controls as human perception of loudness is logarithmic. Unless you are making a volume control for an audio amplifier, you probably want a linear pot.
To connect a pot to an Arduino or Raspberry Pi, see Recipe 12.9.
A potentiometer lends itself to being a variable voltage divider (see Recipe 2.6).
The overall resistance of a number of resistors in series is just the sum of the separate resistances.
Figure 2-5 shows two resistors in series. The current flows through one resistor and then the second. As a pair, the resistors will be equivalent to a single resistor of 200Ω.
The heating power of each resistor will be
.
If you used a single resistor of 200Ω then the power would be:
So, by using two resistors, you can double the power.
You may be wondering why you would ever want to use two resistors in series when you could just use one. Power dissipation may be one reason, if you cannot find resistors of sufficient power.
But there are other situations, such as the one shown in Figure 2-6, where you use a variable resistor (pot) with a fixed resistor to make sure that the combination’s resistance does not fall below the value of the fixed resistor.
Resistors in series are often used to form a voltage divider (see Recipe 2.6).
The combined resistance of a number of resistors in parallel is the inverse of the sum of the inverses of the resistors. That is, if there are two resistors R1 and R2 in parallel, then the overall resistance is given by:
In the example shown in Figure 2-7 with two 100Ω resistors in parallel, the arrangement is equivalent to a single resistor of:
Intuitively, this makes perfect sense, because there are now two equally resistive paths through the resistors instead of one as would be the case with a single resistor.
In Figure 2-7 a single 50Ω resistor is equivalent to the two 100Ω resistors in parallel, but what implications does this have for the power ratings of the two resistors?
Intuitively, you would expect the total power dissipation of two 100Ω resistors to be the same as the two 50Ω resistors, but just to be sure let’s do the math.
For each 100Ω resistor, the power will be:
So the total for the two resistors will be 45mW, allowing you to use lower power and more common resistors.
Just as you’d expect, performing the calculation for the single 50Ω resistor you get:
See Recipe 2.4 for resistors in series.
Use two resistors in series as a voltage divider (also called potential divider). The word “potential” indicates the voltage has the potential to do work and make current flow.
Figure 2-8 shows a pair of resistors being used as a voltage divider.
The output voltage (Vout) will be a fraction of the input voltage (Vin) according to the formula:
For example, if R1 is 470Ω, R2 is 270Ω, and Vin is 5V:
Note that if R1 and R2 are equal then the voltage is divided by 2.
A pot naturally forms a potential divider as you can think of it as two resistors in series whose overall resistance adds up to the same value, but the proportion of the resistance of R1 to R2 varies as you turn the knob. This is just how a pot is used in a volume control.
It may be tempting to think of a voltage divider as useful for reducing voltages in power supplies. However, this is not the case, because as soon as you try to use the output of the voltage divider to power something (a load), it is as if another resistor is being put in parallel with R2. This effectively reduces the resistance of the bottom half of the voltage divider and therefore also reduces the output voltage. This will only work if R1 and R2 are much lower than the resistance of the load. This makes them great for reducing signal levels, but of no use for high-power circuits.
See Chapter 7 for various techniques for reducing voltages in power supplies.
For level shifting with a voltage divider, see Recipe 10.17.
Calculate the power (Recipe 1.6) your resistor will be converting into heat and pick a resistor with a power rating comfortably greater than this value.
For example, if you have a 10Ω resistor connected directly to the terminals of a 1.5V battery, then the power that the resistor converts to heat can be calculated as:
This means that a standard ¼W resistor will be OK, but you may wish to take the next step up to ½W.
The most common power rating of resistor used by hobbyists is the ¼W (250mW) resistor. These resistors are not so tiny that they are hard to handle or the leads too thin to make good contact in breadboard (Recipe 20.1) yet they are capable of handling enough power for most uses, such as limiting current to LEDs (Recipe 14.1) or used as voltage dividers for low current (Recipe 2.6).
Other common power ratings for through-hole resistors with leads are ½W, 1W, 2W, 5W, 10W, and even higher power resistors.
Figure 2-9 shows a selection of resistors of different power ratings.
When it comes to the tiny surface-mount “chip resistors” that are surface mounted onto circuit boards, power ratings start much lower.
To understand power, see Recipe 1.6.
Use a photoresistor.
A photoresistor (Figure 2-10) is a resistor in a clear plastic package whose resistance varies depending on the amount of light falling on it. The more brightly the photoresistor is illuminated, the lower the resistance.
A typical photoresistor might have a resistance in direct sunlight of 1kΩ increasing to several MΩ in total darkness.
Photoresistors are often used in a voltage-divider arrangement (Recipe 2.6) with a fixed-value resistor to convert the resistance of the photoresistor into a voltage that can then be used with a microcontroller (Recipe 12.6) or comparator (Recipe 17.10).
You will find more details on using a photoresistor in Recipe 12.6.
One method is to use a thermistor. Other ways can be found in Recipe 12.10 and Recipe 12.11.
All resistors are slightly sensitive to changes in temperature. However, thermistors (Figure 2-11) are resistors whose resistance is very sensitive to changes in temperature. As with photoresistors (Recipe 2.8), they are often used in a voltage divider (Recipe 2.6) to convert the resistance to a voltage reading that is more convenient.
There are two types of thermistors. NTC (negative temperature coefficient) thermistors are the more common type and their resistance decreases as the temperature increases. PTC (positive temperature coefficient) thermistors have a resistance that increases as the temperature increases.
In addition to being used to measure temperature (see Recipe 12.7) PTC thermistors are also used to limit current. As the current through the thermistor increases, the resistor heats up and thus its resistance increases, reducing the current.
For practical circuits that use a thermistor to measure temperature, see Recipe 12.7 and Recipe 12.8.
Wires all have resistance. A thick copper wire will have a much lower resistance than the same length of a much thinner wire. As someone once said, “the great thing about standards are that there are always lots to choose from.” Nowhere is this more true than for wire thicknesses or gauges. One of the most common standards is AWG (American Wire Gauge) mostly used in the US, and the SWG (Standard Wire Gauge) mostly used in the UK and most logically just the diameter of the wire in mm.
Nearly all wiring used in electronics is made of copper. If you strip the insulation off a wire and it looks silver-colored, then it’s probably still copper, but copper that has been “tinned” to stop it from oxidizing and make it easier to solder.
Table 2-2 shows some commonly used wire gauges along with their resistances in Ω per foot and meter for copper wiring.
| AWG | Diameter (mm) | mΩ/m | mΩ/foot | Max. Current (A) | Notes |
|---|---|---|---|---|---|
| 30 | 0.255 | 339 | 103 | 0.14 | |
| 28 | 0.376 | 213 | 64.9 | 0.27 | |
| 24 | 0.559 | 84.2 | 25.7 | 0.58 | Solid-core hookup wire |
| 19 | 0.95 | 26.4 | 8.05 | 1.8 | General-purpose multicore wire |
| 15 | 1.8 | 10.4 | 3.18 | 4.7 | Thick multicore wire |
The larger the AWG number the thicker the wire. Wires thinner than 24AWG are most likely to be thin enameled wire designed for winding transformers and indictors, like the wire shown in Figure 2-12.
Solid-core wire is made of a single strand of copper insulated in plastic (Figure 2-13). It is useful with solderless breadboards (Recipe 20.1) but should not be used in situations where it is likely to be flexed as it will break through metal fatigue if bent back and forth. I always have this wire in at least three colors so that I can use black for negative, red for positive, and other colors for nonpower connections.
For general-purpose wire where some movement is likely, use multicore wire made up of a number of strands of wire twisted about each other and encased in plastic insulation. Again, it’s useful to have a selection of colors.
The currents listed in Table 2-2 are only suggestions. The actual current that each gauge of wire can carry without getting too hot depends on many factors, including how well ventilated the project’s case is and whether the wires are all grouped together with a whole load of other wires all getting warm. So treat Table 2-2 as a guide.
When you buy wire, the maximum temperature of the insulation will usually be specified. This is not just because of internal heating of the wire but also for situations where the insulation is to be used in hot environments such as ovens or furnaces.
If you are looking for wires to carry high voltages then you will need a good insulation layer. Again, wires will normally have a breakdown voltage specified for the insulation.
For a table comparing wire gauges, see http://bit.ly/2lOyPIh.
For the current-handling capabilities of wire by gauge, see http://bit.ly/2mbgZS8.
When it comes to digital electronics, capacitors are almost a matter of insurance, providing short-term stores of charge that improve the reliability of circuits. As such their use is often simply a matter of following the recommendations in the IC’s datasheet without the need to do any math.
However, when it comes to analog electronics the use of capacitors becomes much more varied. Their ability to store small amounts of charge for a short period of time can be used to set the frequency of oscillators (see Recipe 16.5). They can be used to smooth the ripples for a power supply (see Recipe 7.2) or to couple two audio circuits without transferring the DC part of the signal (see Recipe 17.9).
In fact, capacitors will be used throughout this book in all sorts of ways, so it’s important to understand how they work, how to select the right capacitor, and how to use it.
Inductors are not as common as capacitors, but they are widely used in certain roles, particularly in power supplies (see Chapter 7).
Use a capacitor.
In construction, capacitors are just two conductive surfaces separated by an insulating layer (Figure 3-1).
In fact, the insulating layer between the conductive surfaces of the capacitor can just be air, although a capacitor using an air gap will be of very low value. In fact, the value of the capacitor depends on the area of the conducting plates, how close they are together, and how good an insulator separates them. So the greater the area of the plates and the smaller the distance between them the greater the capacitance (the more charge it can store).
Individual electrons do not flow through a capacitor, but those on one side of the capacitor influence those on the other. If you apply a voltage source like a battery to a capacitor, then the plate of the capacitor connected to the positive supply of the battery will accumulate positive charge and the electric field this generates will create a negative charge of equal magnitude on the opposite plate.
In water terms, you can think of a capacitor as an elastic membrane in a pipe (Figure 3-2) that does not allow water to pass all the way through the pipe, but will stretch, allowing the capacitor to be charged. If the capacitor is stretched too far then the elastic membrane will rupture. This is why exceeding the maximum voltage of a capacitor is likely to destroy it.
When you apply a voltage across a capacitor it will almost instantly charge to that voltage. But if you charge it through a resistor then it will take time to become full of charge. Figure 3-3 shows how a capacitor can be charged or discharged through the use of the switches S1 and S2.
When you close switch S1, C1 will charge through R1 until C1 reaches the battery voltage. Open S1 again and the now charged capacitor will retain its charge. Eventually the capacitor will lose its charge through self-discharge.
If you now close S2, C1 will now discharge through R2 and LED1, which will light brightly at first and then more dimly as C1 is discharged.
If you want to experiment with the schematic diagram of Figure 3-3, then build up the breadboard diagram shown in Figure 3-4. For an introduction to breadboard, see Recipe 20.1. Use 1kΩ resistors and a 100µF capacitor.
Press the button labeled CHARGE for a second or two to charge the capacitor then release the button and press the DISCHARGE button. The LED should glow brightly for a second or so and then dim until it extinguishes after a second or so.
If you were to monitor the voltage across the capacitor while it was first being charged and then discharged, you would see something similar to Figure 3-5.
In Figure 3-5 the square-shaped waveform is the voltage applied to the capacitor through a 1kΩ resistor. For the first 400ms this is 9V. But as you can see the voltage across the capacitor does not increase linearly, but rather increases faster at first and then gradually tails off as the voltage across the capacitor gets closer to the battery voltage.
Similarly, when the capacitor discharges, the voltage decreases sharply at first and then starts to tail off.
So, if a capacitor stores electrical energy, you may be wondering how this differs from a rechargeable battery. Well, in fact a special type of very high capacitance capacitor called a supercapacitor is sometimes used in place of a rechargeable battery for applications that require a very rapid storage and release of energy. The differences between a capacitor and a battery include:
For information on using a solderless breadboard, see Recipe 20.1.
The voltage curves of Figure 3-5 were created using a circuit simulator (Recipe 21.11). You can experiment with this simulation online using PartSim at http://bit.ly/2mrtrhs.
Unless your application needs capacitors with special features, the following rule of thumb applies.
In most cases, for capacitors between 1pF and 1nF use a disc capacitor (Figure 3-6a). For capacitors between 1nF and 1µF use a multilayer ceramic capacitor (MLC; Figure 3-6b) and for capacitors above 1µF use an aluminum electrolytic capacitor (Figure 3-6c). The rightmost capacitor is a tantulum electrolytic capacitor.
Although disc ceramic, MLC, and aluminum electrolytic capacitors are the most commonly used types of capacitor, there are other types:
Capacitors are less reliable than resistors. Exceed the voltage rating and you are likely to damage the insulating layer. Electrolytic capacitors use an electrolyte contained in an aluminum can that creates a very thin layer of oxide as the insulator. These are especially prone to failure due to overvoltage, or overtemperature, or just age. If vintage HiFi equipment fails, it is usually the large electrolytic capacitors in the power supplies that are the cause of the failure. In addition, if an electrolytic capacitor does fail then it can spray out the electrolyte in a somewhat messy manner.
In addition to the actual capacitance of a capacitor, there are a number of other factors to consider when selecting a device. Of critical importance is the voltage rating. Unless you are creating something that uses high voltages, this is not usually a problem with smaller value capacitors, as they are generally rated at least 50V. However, as soon as you get into the range of electrolytics then you will be in a trade-off between capacitor size and voltage. Electrolytic capacitors are commonly available in voltage ratings of 6.3V, 10V, 25V, 30V, 40V, 50V, 63V, 100V, 160V, 200V, 250V, 400V, and 450V. It is unusual to find electrolytic capacitors with a higher voltage rating than 500V.
The temperature rating becomes important when the capacitors are being rapidly charged and discharged, as a capacitor will always have an internal resistance called its equivalent series resistance (ESR) that causes heating during charging and discharging.
Small-value MLC capacitors generally have a very low ESR of little more than the resistance caused by their leads. This allows them to charge and discharge extremely quickly. A high-value electrolytic capacitor might have an ESR of a few hundred mΩ. This both limits the speed at which the capacitors can charge and discharge and causes a heating effect.
For the use of electrolytic capacitors to smooth out voltage ripple from power supplies, see Recipe 7.4.
Small, low-value SMD capacitors are generally unmarked, and so you should label them as soon as you buy them.
Electrolytic capacitors usually have their capacitance value and voltage rating printed on the package. Polarized through-hole electrolytic capacitors are also usually supplied with the positive lead longer than the negative lead and the negative lead marked with a minus sign or a diamond symbol.
Most other capacitors use a numbering system similar to that of SMD resistors. The value is usually three digits and a letter. The first two digits are the base value and the third digit is the number of zeros to follow. The base value being the value in pF (pico Farad; see Appendix D).
For example, a 100pF capacitor would have the three digits 101 (a 1, a 0, followed by one further 0). A 100nF capacitor would be marked 104 (a 1, a 0, followed by four further 0s); that is, 100,000 pF or 100nF.
The letter after the digits indicates the tolerance (J, K, or M for ±5%, ±10%, and ±20%, respectively).
To read resistor color codes, see Recipe 2.1.
Looking at Figure 3-7, you can see two capacitors in parallel double up on the surface area of the conductive plates and therefore may correctly assume that the overall capacitance is the sum of the two capacitances.
It is actually quite common to place a number of capacitors in parallel to increase the overall capacitance. It is especially common when smoothing a high-power transformer-based power supply for, say, an audio amplifier where it is important to remove as much ripple from the power supply as possible (see Recipe 7.2).
In such systems it is common to use a number of different capacitors of different types and values in parallel to minimize the effects of ESR (see Recipe 3.2).
For capacitors in series, see Recipe 3.5.
It is unusual to connect capacitors in series. Occasionally, this will be done as part of a more complex circuit such as in Recipe 7.12.
For capacitors in parallel, see Recipe 3.4.
Supercapacitors are low-voltage capacitors that have extremely high capacitances. They are primarily used as energy-storage devices in situations that would otherwise use rechargeable batteries.
They can have values up into the hundreds of F (Farads). Note that the top of the capacitance range for an aluminum electrolytic is around 0.22F.
Low (comparatively) value supercapacitors of perhaps a few F are sometimes used as alternatives to rechargeable batteries or long-life lithium batteries to power ICs in standby mode to retain memory in static RAM that would otherwise be lost, or to power real-time clock (RTC) chips so a device using an RTC IC will keep the time if it’s powered off for a while.
Extremely high-value supercapacitors are available that offer an alternative to rechargeable batteries for larger capacity energy storage.
Supercapacitors with values of 500F or more can be bought for just a few dollars. The maximum voltage for a supercapacitor is 2.7V so, for higher voltage use, the capacitors can be placed in series with special protection circuitry to ensure the 2.7V limit is not exceeded as the bank of capacitors are charged.
Supercapacitors generally look like standard aluminum electrolytic capacitors. At present, their energy storage is still quite a long way from that of rechargeable batteries and because they are capacitors, the voltage decreases much more quickly than when discharging a battery.
See Recipe 3.7 to calculate the energy stored in super capacitors and normal capacitors.
The energy stored in a capacitor in J is calculated as:
Taking a medium-sized electrolytic of 470µF at 35V the energy stored would be:
which is not very much energy. Since the energy storage is proportional to the square of the voltage, the results for a capacitor of the same value but at 200V are much more impressive:
For a 500F 2.7V supercapacitor, the results are even more impressive:
By way of comparison, a single 1.5V AA battery of 2000mAH stores around:
For information on rechargeable batteries, see Recipe 8.3.
An inductor is, at its simplest, just a coil of wire. At DC, it behaves just like any length of wire and will have some resistance, but when AC flows through it, it starts to do something interesting.
A change in current in one direction in an inductor causes a change in voltage in the opposite direction. This effect is more marked the higher the frequency of the AC flowing through the inductor. The net result of this is that the higher the frequency of the AC, the more the inductor resists the flow of current. So as not to confuse this effect with ordinary resistance, it is called reactance but it still has units of Ω.
The reactance X of an inductor can be calculated by the formula:
Where f is the frequency of the AC (cycles per second) and L is the inductance of the inductor whose units are the Henry (H). This resistive effect does not generate heat like a resistor, but rather returns the energy to the circuit.
The inductance of an inductor will depend on the number of turns of wire as well as what the wire is wrapped around. So, very low-value inductors may be just a couple of turns of wire without any core (called air-core inductors). Higher value inductors will generally use an iron or more likely ferrite core. Ferrite is a magnetic ceramic material.
The current-carrying capability of an inductor generally depends on the thickness of the wire used in the coil.
Inductors are used in switched mode power supplies (SMPS) where they are pulsed at a high frequency (see Recipe 7.8 and Recipe 7.9). They are also used extensively in radio-frequency electronics, where they are often combined with a capacitor to form a tuned circuit (see Chapter 19).
A type of inductor called a choke is designed to let DC pass while blocking the AC part of a signal. This prevents unwanted radio-frequency noise from infiltrating a circuit. You will often find a USB lead has a lump in it near one end. This is a ferrite choke, which is just a cylinder of ferrite material that encloses the cables and increases the inductance of the wire to a level where it can suppress high-frequency noise.
For more information on the use of inductors in SMPSs, see Recipe 7.8 and Recipe 7.9.
See Recipe 3.9 for more information on transformers.
A transformer is essentially two or more inductor coils wrapped onto a single core. Figure 3-8 shows the schematic diagram for a transformer that also gives a clue as to how it works.
A transformer has primary coils and secondary coils. Figure 3-8 shows one of each. The primary coil is driven by AC, say the 110V from an AC outlet, and the secondary is connected to the load.
The voltage at the secondary is determined by the ratio of the number of turns on the primary to the number of turns on the secondary. Thus if the primary has 1000 turns and the secondary just 100, then the AC voltage will be reduced by a factor of 10.
Figure 3-9 shows a selection of transformers. As you can see they come in a wide range of sizes.
In Figure 3-9 there is a small high-frequency transformer on the left that was taken from a disposable flash camera where it was used to step up pulsed DC (almost AC) from a 1.5V battery to the 400V needed by a Xenon flash tube.
The type of transformer shown in the center is commonly used to step-down 110V AC to a low voltage, say 6V or 9V.
The transformer on the right is also designed to step-down AC outlet voltages to lower voltages. It is called a torroidal transformer and the primary and secondary coils are wrapped around a single torroidal former (donut shaped arrangement of iron layers), on top of each other. These transformers are often used in HiFi equipment where the noise found in most SMPSs is considered too high for high-end HiFi amplifiers.
It used to be that if you wanted to power a low-voltage DC appliance such as a radio receiver from an AC outlet, then you would first use a transformer to drop the 100V AC at 60Hz to, say, 9V. You would then rectify and smooth the low-voltage AC into DC.
These days, an SMPS (see Recipe 7.8) is normally used as transformers are expensive and heavy items with iron and long lengths of copper-winding wire. However, transformers are still used in SMPS but operate at a very much higher frequency than 60Hz. Operating at a high frequency (often 100s of kHz) allows the transformers to be much smaller and lighter than low-frequency transformers while retaining good efficiency.
This video shows a torroidal transformer winding machine in action: https://youtu.be/82PpCzM2CUg.
Recipe 7.1 describes how to use a transformer to convert one AC voltage to another.
The first diodes to be used in electronics were cat’s whisker detectors used in crystal radios. These comprised a crystal of a semiconductor material (often lead sulphide or silicon). The cat’s whisker is simply a bare wire that is held in an adjustable bracket that touches the semiconductor crystal. By carefully moving the whisker around, at certain points of contact the arrangement would act as a diode, only allowing current to flow in one direction. This property is needed in a simple radio receiver to detect the radio signal so that it can be heard (see Chapter 19).
Today diodes are much easier to use and come in all sorts of shapes and sizes.
A diode is a component that only allows current to flow through it in one direction. It’s a kind of one-way valve if you want to think of it in terms of water running through pipes, which of course is a simplification. In reality the diode offers very low resistance in one direction and very high resistance in the other. In other words, the one-way valve restricts the flow a tiny bit when open and also leaks slightly when closed. But most of the time, thinking of a diode as a one-way valve for electrical current works just fine.
There are lots of specialized types of diodes, but let’s start with the most common and basic diode, the rectifier diode. Figure 4-1 shows such a diode in a circuit with a battery and resistor.
In this case, the diode allows flow of current and is considered forward-biased. The two leads of the diode are called the anode (abbreviated as “a”) and cathode (abbreviated rather confusingly as “k”). For a diode to be forward-biased, the anode needs to be at a higher voltage than the cathode, as shown in Figure 4-1.
One interesting property of a forward-biased diode is that unlike a resistor, the voltage across it does not vary in proportion to the current flowing through it. Instead, the voltage remains almost constant, no matter how much current flows through it. This varies depending on the type of diode, but is generally about 0.5V.
In the case of Figure 4-1, we can calculate that the current flowing through the resistor will be:
This is only 0.5mA less than if the diode were to be replaced with wire.
In Figure 4-2 the diode is facing the other direction. It is reverse-biased and consequently almost no current will flow through the resistor.
The diode’s one-way effect can be used to convert AC (Recipe 1.7) into DC. Figure 4-3 shows the effect of a diode on an AC voltage source.
This effect is called rectification (see Recipe 7.2). The negative part of the cycle is unused. This still isn’t true DC because even though the voltage never becomes negative it still swings from 0V up to a maximum and back down rather than remain constant. The next stage would be to add a capacitor in parallel with the load resistor that would smooth out the signal to a flat and almost constant DC voltage.
For information on using diodes in power supplies, see Recipe 7.2 and Recipe 7.3.
Figure 4-4 shows different types of diodes. Generally, the bigger the diode package, the greater its power-handling capability. Most diodes are a black plastic cylinder with a line at one end that points to the cathode (the end that should be more negative for forward-biased operation).
The diode on the left of Figure 4-4 is an SMD. The through-hole diodes to the right get larger, the higher the current rating.
There are many different types of diodes. Unlike resistors that are bought as a particular value resistor (say, 1kΩ) diodes are identified by the manufacturer’s part number.
Some of the most commonly used rectifier diodes are listed in Table 4-1.
| Part Number | Typical Forward Voltage | Maximum Current | DC Blocking Voltage | Recovery Time |
|---|---|---|---|---|
| 1N4001 | 0.6V | 1A | 50V | 30µs |
| 1N4004 | 0.6V | 1A | 400V | 30µs |
| 1N4148 | 0.6V | 200mA | 100V | 4ns |
| 1N5819 | 0.3V | 1A | 40V | 10ns |
The forward voltage, often abbreviated as Vf, is the voltage across the diode when forward-biased. The DC-blocking voltage is the reverse-biased voltage that if exceeded may destroy the diode.
The recovery time of a diode refers to how quickly the diode can switch from forward-biased conducting to reverse-biased blocking. This is not instantaneous in any diode and in some applications fast switching is needed.
The 1N5819 diode is called a Schottky diode. These types of diodes have much lower forward voltage and generate less heat.
You can find the datasheet for the 1N4000 family of diodes here: http://bit.ly/2lOtD71.
When forward-biased, Zener diodes behave just like regular diodes and conduct. At low voltages, when reverse-biased they have high resistance just like normal diodes. However, when the reverse-biased voltage exceeds a certain level (called the breakdown voltage), the diodes suddenly conduct as if they were forward-biased.
In fact, regular diodes do the same thing as Zener diodes but at a high voltage and not a voltage that is carefully controlled. The difference with a Zener diode is that the diode is deliberately designed for this breakdown to occur at a certain voltage (say, 5V) and for the Zener diode to be undamaged by such a “breakdown.”
Zener diodes are useful for providing a reference voltage (see the schematic in Figure 4-5). Note the slightly different component symbol for a Zener diode with the little arms on the cathode.
The resistor R limits the current flowing through the Zener diode. This current is always assumed to be much greater than the current flowing into a load across the diode.
This circuit is only well suited to providing a voltage reference. A voltage reference provides a stable voltage but with hardly any load current; for example, when the circuit is used with a transistor as in Recipe 7.4. So a resistor value of, say, 1kΩ would, if Vin was 12V, allow a current of:
The output voltage will remain roughly 5V whatever Vin is as long as it’s greater than 5V. To understand how this happens, imagine that the voltage across the Zener diode is less than its 5V breakdown voltage. The Zener’s resistance will therefore be high and so the voltage across it due to the voltage divider effect of R and the Zener will be higher than the breakdown voltage. But wait, since the breakdown voltage is exceeded it will conduct, bringing the Vout down to 5V. If it falls below that, the diode will turn off and the Vout will increase again.
Zener diodes are also used to protect sensitive electronics from high-voltage spikes due to static discharge or incorrectly connected equipment. Figure 4-6 shows how an input to an amplifier not expected to exceed ±10V can be protected from both high positive and negative voltages. When the input voltage is within the allowed range the Zener will be high resistance and not interfere with the input signal, but as soon as the voltage is exceeded in either direction the Zener will conduct the excess voltage to ground.
Although you would generally use a voltage-regulator IC (see Recipe 7.4), you can use a Zener diode combined with a transistor to act as a voltage regulator.
LEDs are like regular diodes in that when reverse-biased they block the flow of current, but when forward-biased they emit light.
The forward voltage of an LED is more than the usual 0.5V of a rectifier and depends on the color of the LED. Generally a standard red LED will have a forward voltage of about 1.6V.
Figure 4-7 shows an LED in series with a resistor. The resistor is necessary to prevent too much current from flowing through the LED and damaging it.
An LED used as an illuminator will generally emit some light at 1mA but usually needs about 20mA for optimum brightness. The LED’s datasheet will tell you its optimal and maximum forward currents.
As an example, if in Figure 6-5 the voltage source is a 9V battery and the LED has a forward voltage of 1.6V, you can calculate the resistor value needed using Ohm’s Law:
370Ω is not a common resistor value (see Recipe 2.2) so you could pick a 360Ω resistor, in which case the current would be:
which would be just fine.
Finding suitable resistor values for LEDs to limit the current is such a common task that there is really no need to go through these calculations all the time. In Recipe 14.1 you will find a practical recipe for rule-of-thumb selection of current-limiting resistors.
For information on driving different types of LED, see Chapter 14.
Use a photodiode. You can also use a photoresistor (Recipe 2.8) or a phototransistor (Recipe 5.7).
A photodiode is a diode that is sensitive to light. A photodiode usually has a transparent window, but photodiodes designed for infrared use have a black plastic case. The black plastic case is transparent to IR and usefully stops the photodiode from being sensitive to visible light.
Photodiodes can be treated as little tiny photovoltaic solar cells. When illuminated they generate a small current. Figure 4-8 shows how you can use a photodiode with a resistor to produce a small voltage that you could then use in your circuits.
In this circuit, the voltage when illuminated brightly might only be 100mV.
The resistor is necessary so that the small current from the photodiode is converted into a voltage (V=IR). Otherwise, any voltage that you measure will be depend on the resistance (called impedance when not from a resistor) of whatever is measuring the voltage. So, for example, a multimeter with an input impedance of 10MΩ would provide a completely different (and lower) reading than a multimeter with a 100MΩ input impedance.
R1 makes the voltage consistent. The impedance of whatever is connected to the output needs to be much higher in value than R1. If this is an op-amp (see Chapter 17) then the input impedance is likely to be hundreds of MΩ and so will not alter the output voltage appreciably. The smaller you make R1, the lower the output voltage will be, so it’s a matter of striking a balance.
Better sensitivity can be achieved by using the photodiode in a photoconductive mode with a voltage source (Figure 4-9).
Photoresistors (Recipe 12.6) and phototransistors (Recipe 5.7) tend to be used more than photodiodes as they are more sensitive.
Transistors are used to control the flow of a current. In digital electronics this control takes the form of an on/off action, with the transistor acting as an electronic switch.
Transistors are also used in analog electronics where they can be used to amplify signals in a linear manner. However, these days, a better (cheaper and more reliable) way to do this is to use an integrated circuit (chip) that combines lots of transistors and other components into a single convenient package.
This chapter does not cover all types of transistors or semiconductor devices, but instead focuses on the most common ones, which are generally low in cost and easy to use. There are other exotic devices like the unijunction transistors and SCRs (silicon-controlled rectifiers) that used to be popular, but are now seldom used.
The other thing deliberately left out of this cookbook is the usual theory of how semiconductors like diodes and transistors work. If you are interested in the physics of electronics, there are many books and useful resources on semiconductor theory, but just to make use of transistors, you do not really need to know about holes, electrons, and doping N and P regions.
This chapter will concentrate on the use of transistors in their digital role. You will find information on using transistors for analog circuits in Chapter 16.
In this chapter, you will encounter a wide variety of transistors. Appendix A includes pinouts for the transistors used in this chapter and throughout the book.
Use a low-cost bipolar junction transistor (BJT).
BJTs like the 2N3904 cost just a few cents and are often used with a microcontroller output pin from an Arduino or Raspberry Pi to increase the current the pin can control.
Figure 5-1 shows the schematic symbol for a BJT alongside one of the most popular models of this kind of transistor, the 2N3904. The 2N3904 is in a black plastic package called a TO-92 and you will find that many different low-power transistor models come supplied in the TO-92 package.
The transistor is usually shown with a circle around it, but sometimes just the symbol inside the circle is used.
The three connections to the transistor in Figure 5-1 are from top to bottom:
The main current flowing into the collector and out of the emitter is controlled by a much smaller current flowing into the base and out of the emitter. The ratio of the base current to the collector current is called the current gain of the transistor and is typically somewhere between 100 and 400. So for a transistor with a gain of 100, a 1mA current flowing from base to emitter will allow a current of up to 100mA to flow from collector to emitter.
To get a feel for how such a transistor could be used as a switch, build the circuit shown in Figure 5-2 using the breadboard layout shown in Figure 5-3. For help getting started with breadboard tutorial, see Recipe 20.1.
The push switch will turn the LED on when its pressed. Although this could be achieved much more easily by just putting the switch in series with the LED and R2, the important point is that the switch is supplying current to the transistor through R1. A quick calculation shows that the maximum current that could possibly flow through R1 and the base is:
In reality the current is less than this, because we are ignoring the 0.6V between the base and emitter of the transistor. If you want to be more precise, then the current is actually:
This tiny current flowing through the base is controlling a much bigger current of roughly (assuming Vf of LED 1.8V):
Just like a diode, when the BJT is in use there will be an almost constant voltage drop of around 0.5V to 1V between the base and emitter connections of the transistor.
A resistor limiting the current that can flow into the base of the transistor (R1 in Figure 5-2) is essential, because if too much current flows through the base then the transistor will overheat and eventually die in a puff of smoke.
Because the base of a transistor only requries a small current to control a much bigger current, it is tempting to think of the base as having a built-in resistance to a large current flowing. This is not the case, since it will draw a self-destructively large current as soon as its base voltage exceeds 0.6V or so. So, always use a base resistor like R1.
The BJT transistor described earlier is the most common and is an NPN type of transistor (negative positive negative). This is not a case of the transistor being indecisive, but relates to the fact that the transistor is made up like a sandwich with N-type (negative) semiconductor as the bread and P-type (positive) semiconductor as the filling. If you want to know what this means and understand the physics of semiconductors, then take a look at https://en.wikipedia.org/wiki/Bipolar_junction_transistor.
There is another less commonly used type of BJT called a PNP (positive negative positive) transistor. The filling in this semiconductor sandwich is negatively doped. This means that everything is flipped around. In Figure 5-2 the load (LED and resistor) is connected to the positive end of the power supply and switched on the negative side to ground. If you were to use a PNP transistor the circuit would look like Figure 5-4. You can find out more about using PNP transistors in Recipe 11.2.
If the gain of your transistor is not enough, you may need to consider a Darlington transistor (Recipe 5.2) or MOSFET (Recipe 5.3).
If, on the other hand, you need to switch a high-power load then you should consider a power MOSFET (Recipe 5.3) or IGBT (Recipe 5.4).
You can find the datasheet for the popular low-power BJT, the 2N3904, here: http://www.farnell.com/datasheets/1686115.pdf.
Use a Darlington transistor.
A regular BJT will typically only have a gain (ratio of base current to collector current) of perhaps 100. A lot of the time, this will be sufficient, but sometimes more gain is required. A convenient way of achieving this is to use a Darlington transistor, which will typically have a gain of 10,000 or more.
A Darlington transistor is actually made up of two regular BJTs in one package as shown in Figure 5-5. Two common Darlington transistors are shown next to the schematic symbol. The smaller one is the MPSA14 and the larger the TIP120. See Recipe 5.5 for more information on these transistors.
The overall current gain of the pair of transistors in this arrangement is the gain of the first transistor multiplied by the gain of the second. It’s easy to see why this is the case, as the base of the second transistor is supplied with current from the collector of the first.
Although you can use a Darlington transistor in designs just as if it were a single BJT, one effect of arranging the transistors like this is that there are now two voltage drops between the base and emitter. The Darlington transistor behaves like a regular NPN BJT with an exceptionally high gain but a base-emitter voltage drop of twice that of a normal BJT.
A popular and useful Darlington transistor is the TIP120. This is a high-power device that can handle a collector current of up to 5A.
You can find the datasheet for the TIP120 here: http://bit.ly/2mHBQy6 and the MPSA14 here: http://bit.ly/2mI1vXF.
MOSFETs (metal-oxide semiconductor field effect transistors) do not have an emitter, base, and collector, but rather a source, gate, and drain. Like BJTs, MOSFETs come in two flavors: N-channel and P-channel. It is the N-channel that is most used and will be described in this recipe. Figure 5-6 shows the schematic symbol for an N-channel MOSFET with a couple of common MOSFETs next to it. The larger transistor (in a package called TO-220) is an FQP30N06 transistor capable of switching 30A at 60V. The hole in the TO-220 package is used to bolt it to a heatsink, something that is only necessary when switching high currents. The small transistor on the right is the 2N7000, which is good for 500mA at 60V.
Rather than multiply a current in the way that a BJT does, there is no electrical connection between the gate and other connections of the MOSFET. The gate is separated from the other connections by an insulating layer. If the gate-drain voltage exceeds the threshold voltage of the MOSFET, then the MOSFET conducts and a large current can flow between the drain and source connections of the MOSFET. The threshold voltage varies between 2V and 10V. MOSFETs designed to work with digital outputs from a microcontroller such as an Arduino or Raspberry Pi are called logic-level MOSFETs and have a gate-threshold voltage guaranteed to be below 3V.
If you look at the datasheet for a MOSFET you will see that it specifies on and off resistances for the transistor. An on resistance might be as low as a few mΩ and the off resistance many MΩ. This means that MOSFETs can switch much higher currents than BJTs before they start to get hot.
You can calculate the heat power generated by the MOSFET using the current flowing through it and its on resistance using the following formula. For more information on power, see Recipe 1.6.
The schematic and breadboard layout used in Recipe 5.1 needs a little modification to be used to experiment with a MOSFET. The variable resistor is now used to set the gate voltage from 0V to the battery voltage. The revised schematic and breadboard layouts are shown in Figures 5-7 and 5-8, respectively.
With the trimpot’s knob at the 0V end of its track, the LED will not be lit. As the gate voltage increases to about 2V the LED will start to light and when the gate voltage gets to about 2.5V the LED should be fully on.
Try disconnecting the end of the lead going to the slider of the pot and touch it to the positive supply from the battery. This should turn the LED on, and it should stay on even after you take the lead from the gate away from the positive supply. This is because there is sufficient charge sitting on the gate of the MOSFET to keep its gate voltage above the threshold. As soon as you touch the gate to ground, the charge will be conducted away to ground and the LED will extinguish.
Since MOSFETs are voltage- rather than current-controlled devices you might be surprised to find that under some circumstances you do have to consider the current flowing into the gate. That is because the gate acts like one terminal of a capacitor. This capacitor has to charge and discharge and so when pulsed at high frequency the gate current can become significant. Using a current-limiting resistor to the gate will prevent too much current from flowing.
Another difference between using a MOSFET and a BJT is that if the gate connection is left floating, then the MOSFET can turn on when you aren’t expecting it. This can be prevented by connecting a resistor between the gate and source of the MOSFET.
To use MOSFETs with a microcontroller output, see Recipe 11.3.
To use a MOSFET for polarity protection, see Recipe 7.17.
For level shifting using a MOSFET, see Recipe 10.17.
For the use of heatsinks, see Recipe 20.7.
An IGBT (insulated gate bipolar transistor) is an exotic type of transistor found in high-power, high-voltage switching applications. They are fast switching, and generally are particularly well specified when it come to operating voltage. Switching voltages of 1000V are not uncommon.
A BJT has base, emitter, and collector; a MOSFET has a gate, source, and drain; and an IGBT combines the two, having a gate, emitter, and collector. Figure 5-9 shows the schematic symbol for an IGBT alongside two IGBTs. The smaller of the two (STGF3NC120HD) is capable of switching 7A at 1.2kV and the even bigger one (IRG4PC30UPBF) 23A at 600V.
IGBTs are voltage-controlled devices just like a MOSFET, but the switching side of the transistor behaves just like a BJT. The gate of an IGBT will have a threshold voltage just like a MOSFET.
IGBTs are sometimes used in the same role as high-power MOSFETs but have the advantage over MOSFETs of being able to switch higher voltages at equally large currents.
For information on BJTs see Recipe 5.1 and for MOSFETS see Recipe 5.3.
You can find the datasheet for the STGF3NC120HD here: http://bit.ly/2msNM6v.
The IRG4PC30UPBF datasheet is here: http://bit.ly/2msXTb9.
Stick to a basic set of go-to transistors for most applications until you have more unusual requirements and then find something that fits the bill.
A good set of go-to transistors is shown in Table 5-1.
| Transistor | Type | Package | Max. Current | Max. Volts |
|---|---|---|---|---|
| 2N3904 | Bipolar | TO-92 | 200mA | 40V |
| 2N7000 | MOSFET | TO-92 | 200mA | 60V |
| MPSA14 | Darlington | TO-92 | 500mA | 30V |
| TIP120 | Darlington | TO-220 | 5A | 60V |
| FQP30N06L | MOSFET | TO-220 | 30A | 60V |
When shopping for an FQP30N06L, make sure the MOSFET is the “L” (for logic) version, with “L” on the end of the part name; otherwise, the gate-threshold voltage requirement may be too high to connect the gate of the transistor to a microcontroller output especially if it is operating at 3.3V.
The MPSA14 is actually a pretty universally useful device for currents up to 1A, although at that current there is a voltage drop of nearly 3V and the device gets up to a temperature of 120°C! At 500mA, the voltage drop is a more reasonable 1.8V and the temperature 60°C.
To summarize, if you only need to switch around 100mA then a 2N3904 will work just fine. If you need up to 500mA, use an MPSA14. Above that, the FQP30N06L is probably the best choice, unless price is a consideration, because the TIP120 is considerably cheaper.
Reasons for straying from the transistors listed in Table 5-1 include:
For information on BJTs see Recipe 5.1, for MOSFETs Recipe 5.3, and for IGBTs Recipe 5.4.
To decide on a transistor for switching with an Arduino or Raspberry Pi, see Recipe 11.5.
Once you start to push transistors beyond a light load, you will find that they start to get hot. If they get too hot they will burn out and be permanently destroyed. To avoid this, either use a transistor with greater current-handling capability or fix a heatsink to it (Recipe 20.7).
TRIAC (TRIode for alternating current) is a semiconductor-switching device designed specifically to switch AC.
BJT and MOSFETs are not useful for switching AC. They can only do that if you split the positive and negative halves of the cycle and switch each with a separate transistor. It is far better to use a TRIAC that can be thought of as a switchable pair of back-to-back diodes.
Figure 5-10 shows how a TRIAC might be used to switch a high AC load using a small current switch. A circuit like this is often used so that a small low-power mechanical switch can be used to switch a large AC current.
The 110V or 220V AC that you find in your home kills thousands of people every year. It can burn you and it can stop your heart, so please do not attempt to build the circuits described here unless you are absolutely sure that you can do so safely.
Also, see Recipe 21.12.
When the switch is pressed a small current (tens of milliamps) flows into the gate of the TRIAC. The TRIAC conducts and will continue conducting until the AC crosses zero volts again. This has the benefit that the power is switched off at low power when the voltage is close to zero, reducing the power surges and electrical noise that would otherwise occur if switching inductive loads like motors.
However, the load could still be switched on at any point in the circuit, generating considerable noise. Zero-crossing circuits (see Recipe 5.9) are used to wait until the next zero crossing of the AC before turning the load on, reducing electrical noise further.
See Recipe 1.7 on AC.
For information on solid-state relays using TRIACs, see Recipe 11.10.
TRIACs are usually supplied in TO-220 packages. For pinouts, see Appendix A.
A phototransistor is essentially a regular BJT with a translucent top surface that allows light to reach the actual silicon of the transistor. Figure 5-11 shows how you can use a phototransistor to produce an output voltage that varies as the level of light falling on the transistor changes.
When the photoresistor is brightly illuminated, it will turn on and conduct, pulling the output voltage toward 0V. In complete darkness, the transistor will be completely off and the output voltage will rise to the supply voltage of 5V.
Some phototransistors look like regular transistors with three pins and a clear top and others (like the TEPT5600 used in Figure 5-11) come in LED-like packages with pins for the emitter and collector, but no pin for the base. For phototransistors that look like LEDs, the longer pin is usually the emitter. Phototransistors are nearly always NPN devices.
As a light-sensing element, the phototransistor is more sensitive than a photodiode and responds more quickly than a photoresistor. Phototransistors have the advantage over photoresistors that they are manufactured using cadmium sulphide and some countries have trade restrictions on devices containing this material.
The output of the circuit of Figure 5-11 can be directly connected to an Arduino’s analog input (Recipe 10.12) to take light readings as an alternative to using a photoresistor (Recipe 12.3 and Recipe 12.6).
For the TEPT5600 datasheet, see http://bit.ly/2m8vhS0.
Use an opto-coupler, which consists of an LED and phototransistor sealed in a single lightproof package.
Figure 5-12 shows how an opto-coupler can be used. When a voltage is applied across the + and – terminals, a current flows through the LED and it lights, illuminating the phototransistor and turning on the transistor. This brings the output down to close to 0V. When the LED is not powered, the transistor is off and R1 pulls the output up to 5V.
The important point is that the lefthand side of the circuit has no electrical connection to the righthand side. The link is purely optical.
When the sensing transistor is a TRIAC (see Recipe 5.6) the device is known as an opto-isolator rather than opto-coupler and the low-power TRIAC inside the opto-isolator can be used to switch AC using a more powerful TRIAC as shown in Figure 5-13. This circuit is often called an SSR (solid-state relay) as it performs much the same role as a relay would in AC switching, but without the need for any moving parts.
You should not work with high voltages unless you are completely sure that you can do so safely and understand the risks. See Recipe 21.12 for more information on working with high voltages.
R1 is used to limit the current flowing into the gate of the opto-isolator and R2 keeps the TRIAC MT1 turned off until the TRIAC in the opto-isolator is turned on by light falling on it because of the LED being energized. R3 and C1 form a filter to reduce the RF noise that would otherwise be generated by the switching. Note that R3 and C1 must both be rated to cope with the peak AC voltage (use 400V devices).
The MOC3032 package also contains a zero-crossing switch that stops the TRIAC from turning on until the AC crosses 0V. This greatly reduces the interference generated by the switching circuit.
For SSRs use opto-isolators, see Recipe 11.10.
For the MOS3032 datasheet, see http://www.farnell.com/datasheets/2151740.pdf.
For relays that also isolate the control side from the power side, see Recipe 6.4.
ICs will be involved in almost every project you are likely to work on. Be it a microcontroller or special-purpose chip for motor control or a radio receiver or audio amplifier, there is probably a chip for it. There is little point in building a circuit out of transistors and other components if there is a single IC that will do the job. You will find many different sorts of IC scattered throughout this book.
ICs come in many different shapes and sizes. Figure 5-14 shows a selection of them.
ICs can have as few as three pins or hundreds of pins. You will often find that the same basic IC is available in different packages, both SMD and through-hole packages. This can be very useful if you plan to prototype your design using a solderless breadboard before manufacturing using SMD components.
Another way of using SMDs on a solderless breadboard is to use a “breakout board” that allows you to solder the SMD onto a board and then plug that board into the breadboard. There is an example of this shown in Figure 18-5.
ICs are identified by their part number, which is often difficult to read, so it’s a good idea to label the bag the IC comes in.
ICs with more than three pins will have a little dot next to pin 1. If there is no dot, then there will be a notch that indicates the top of the IC. The pin numbering then moves down the IC to the bottom continuing with the bottom pin of the righthand side. For some example IC pinouts, see Appendix A.
You can find a list of the ICs used in this book in “Integrated Circuits”.
Mechanical switches allow the flow of current to be turned on and off by flipping a toggle from one position to another or by pressing a button. They are so simple that they require little in the way of explanation other than to describe the various types of switches available and to highlight their limitations.
Relays long predate transistors as a means of using a small current to switch to a much bigger one. However, their flexibility and separation of the control side from the switching side mean that they are still in use today.
Switches generally work by mechanically bringing together two metal contacts. Figure 6-1 shows how this might work.
When the push button is pressed, it presses the sprung metal contact at the top to the fixed contact in the base of the switch.
There are several things that can make switching less straightforward than you might expect:
For these reasons switches have a maximum voltage and current, and there are often separate maximums for switching AC and DC.
For a discussion of the various types of switch, see Recipe 6.2.
Figure 6-2 shows a selection of switches.
The switches from left to right are:
If you are designing a project, then you are probably most likely to be using a microcontroller of some sort, in which case a simple push switch is all that is required. Even if you have a situation where you might want to use a switch to select between two options, chances are you would use a pair of push switches and some feedback as to which is selected in a display.
Slide and toggle switches have mostly been relegated to the role of switching power on and off to the project, although you will occasionally find them on circuit boards as “selector” switches.
Toggles (and other switches) are available in many different switching configurations. Some of those described include DPDT, SPDT, SPST, and SPST. These letters stand for:
A DPDT switch is double pole, double throw. The word pole refers to the number of separate switch elements that are controlled from the one mechanical lever. So, a double-pole switch can switch two things on and off together. A single-throw switch can only open or close a contact (or two contacts if it is a double pole). However, a double-throw switch can make the common contact be connected to one of two other contacts. Figure 6-3 shows some of these configurations.
As seen in Figure 6-3 when drawing a schematic with a double-pole switch, it is common to draw the switch as two switches (S1a and S1b) and connect them with a dotted line to show that they are linked mechanically.
The matter is further complicated because you can have three poles or more on a switch, and double-throw switches are sometimes sprung, and do not stay in one or both of these positions. They may also have a center-off position where the common contact is not connected to any other contact.
Another kind of switch that you may encounter is the rotary switch. This has a knob that can be set to a number of positions. If you have a multimeter, then this is the kind of switch that you will use to select the range. Such switches are not often used. Rotary encoders coupled with a microcontroller (Recipe 12.2) are the more modern way of making a selection using a control knob that you turn.
To use switches with an Arduino or Raspberry Pi, see Recipe 12.1.
A reed switch is made up of a pair of contacts running parallel to each other that are close but not touching. The contacts are enclosed in a glass capsule and when a magnet is brought close to the contacts they are drawn together, closing the switch.
Figure 6-4 shows a reed switch with and without a magnet next to it.
Reed switches are often found in intruder alarms on doors and windows. A fixed magnet is attached to the door and the reed switch to the door frame. When the door is opened, the magnet moves away from the reed switch, triggering the alarm.
Reed switches are also found in reed relays but are rarely used these days.
An electromechanical relay has two parts, a coil that acts as an electromagnet and switch contacts that close when the coil is energized. Figure 6-5 shows a relay, along with the pinout of the relay and a photo of an actual relay.
Although somewhat old-fashioned, relays are still in use today. They are equally happy switching AC or DC and are easily interfaced to a microcontroller.
If you take a relay apart, you will probably see something like Figure 6-6.
Here you can clearly see the coil that forms the electromagnet that when energized will move the contacts seen at the top.
The electromagnet of a relay is a big coil of wire and when released will produce a voltage spike that should be snubbed using a diode (see Recipe 11.9).
See Recipe 11.9 for information on using a relay with an Arduino or Raspberry Pi.
Today SSRs are often used in place of electromechanical relays (see Recipe 11.10).
Anything electronic needs a source of power. This may be as simple as a battery, but often will involve reducing high-voltage AC to the normal 1–12V DC that most electronics use.
Sometimes you need to generate higher voltages from a low-voltage battery. This may be stepping up the supply from a single 1.5V AA battery to a 6 or 9V, or it may be to generate much higher voltages for applications such as the 400V to 1.5kV supply needed by Geiger-Müller tubes.
The ultimate high-voltage power supply is a solid-state Tesla coil (see Recipe 7.15).
This is the first chapter where you will encounter a fair selection of ICs. When using an IC that you are not familiar with, your first port of call should be its datasheet. It will not only tell you how to avoid destroying it (by making sure you do not exceed its maximum ratings) but will also tell you how it behaves and if you are lucky will often include “reference designs” that are complete circuits that use the chip in a practical situation. These designs are developed by the chip manufacturer to show you how to use the IC, and many of the recipes in this chapter start from such reference designs.
If the datasheet for the IC does not include such useful designs, then the next thing to search for is “application notes” for the IC. This will often expand the rather terse and scientific-looking datasheet into practical circuits using the IC.
Use a transformer (see Recipe 3.9).
When buying a transformer designed for 60Hz AC, you will often find the windings in an arrangement something like the one shown in Figure 7-1.
This has two identical primary coils and two identical secondary coils, all wound on the same former (laminated iron frame). This allows some flexibility in how the transformer is used. For example, US electricity is 110V whereas much of the world uses 220V AC. If you are designing a product and need the same low-voltage AC output whether the input is 100V or 220V, then two primary coils allow you to do this if you power the primaries in parallel for 110V and series for 220V.
The dual secondaries provide similar flexibility to wire in series for double the output voltage.
Transformers are only rated to handle a certain amount of power. The resistance of the windings causes them to heat as current flows through them, and if things get too hot the insulation on the wire will break down and the transformer will fail.
A transformer will normally be rated as so many VA (volt amps). For most loads connected to a transformer 1VA is the same as 1Watt, but if large inductive loads like motors are being driven, then the current and voltage become out of phase and the apparent power will be lower than the VA rating.
For an introduction to transformers, see Recipe 3.9.
Reducing the AC voltage is often the first step in making an unregulated power supply, which is the topic of Recipe 7.2.
Use an AC step-down transformer (see Recipe 7.1) and then rectify and smooth the output.
Figure 7-2 shows one schematic for the simplest method of achieving this.
The output voltage in Figure 7-2 is shown as 9V. This will be 1.42 (square root of 2) of the stated output voltage of the transformer.
The diode D rectifies the low-voltage AC from the transformer (see Recipe 4.1). The capacitor C then smooths this out to a constant DC that theoretically will be the peak voltage from the cathode of the diode. The diode will prevent the capacitor from discharging back through the transformer and so once it is at the peak voltage it will stay there.
The schematic of Figure 7-2 is missing any kind of load. The capacitor is being charged to the peak voltage, but nothing is using that charge. When you add a load to the output as shown in Figure 7-3 the capacitor will still be receiving its kicks of voltage from the diode and transformer, but now it will be discharging through the load at the same time.
When using power supplies you will hear the use of the word “load,” which is the thing that is being powered by the power supply. When thinking about how the power supply will operate, you can just think of this load as a resistance. In Figure 7-3 the load is represented by R.
The characteristic voltage drop during each cycle due to the load discharging C is called the ripple voltage.
The size of this ripple voltage can be calculated from the load current and also from the size of the capacitor according to this formula:
where I is the current in amps, f is the AC frequency (60Hz), and C is the capacitance in Farads.
As an example, if the load current is 100mA, a 1000µF capacitor would reduce the ripple voltage to:
Notice that the ripple voltage is proportional to the load current, so in the preceding example, a current of 1A would result in a ripple voltage of 8.3V!
This state of affairs can be improved by using a full-wave rectifier as described in Recipe 7.3, which effectively doubles the frequency f in the preceding formula, halving the ripple voltage.
For full-wave rectification, see Recipe 7.3.
The half-wave rectification of Recipe 7.2 is not very efficient. You want to reduce the ripple voltage by using full-wave rectification.
There are two solutions to this:
Figure 7-4 shows how you can make use of both the positive and negative halves of the AC cycle.
The secondary windings are in serial, with the central connection between the windings becoming the ground of the DC output. When the end of the winding connected to D1 is at its maximum, the end of the winding connected to D2 will be at its minimum (greatest negative value). D1 and D2 will take it in turn to provide positive voltage to the capacitor and the whole AC cycle can contribute to charging the capacitor. Figure 7-5 shows the full-wave rectified output before it is smoothed by the capacitor. It is as if the negative cycles are being reversed.
If you only have a single secondary winding, then you can still achieve full-wave rectification by using an arrangement of four diodes called a bridge rectifier. Figure 7-6 shows an unregulated DC power supply using a bridge rectifier.
To understand how this works, imagine that point A is positive and B is negative. This will allow current to flow from A through D2 to charge the capacitor. If there is a load on the power supply, then the current from the negative side of the DC output will be able to flow back through D4 to B.
When the AC cycle flips polarity and it is B that is positive and A negative, then the positive DC output is supplied through D3 and returns to A through D1.
In Recipe 7.2 you saw how the ripple voltage halves if you use full-wave rectification rather than half-wave. The ripple voltage can be reduced by using very large capacitors, but in most circumstances it is better to use a regulated power supply as described in Recipe 7.4 or a switched mode power supply (SMPS), as discussed in Recipe 7.8.
You can buy a bridge rectifier as a single component that contains the four diodes wired up in a bridge configuration. This simplifies the wiring of your power supply as the bridge rectifier will have four terminals: two marked with a ~ to indicate AC input as well as + and – terminals for the rectified output.
To learn about half-wave rectification, see Recipe 4.1 and Recipe 7.2.
Use a linear voltage regulator IC after your unregulated DC power supply.
Figure 7-7 shows such a circuit. As you can see, the first stage of the project is just an unregulated power supply.
A linear voltage regulator IC such as the very common 7805 regulator has three pins:
In the case of the 7805, the output voltage is fixed at 5V, so as long as the input voltage is above about 7V the output will not have any significant ripple voltage (because the regulator chip needs about 2V more than its output voltage of 5V to successfully regulate the voltage).
At first sight, since C1 and C2 are in parallel, it is not immediately obvious why you would need both. However, the reason is that C1 will be a large electrolytic capacitor (470µF or more) and C2 will be a smaller MLC (typically 330nF) with a low ESR that should be positioned as close as possible to the voltage regulator. C2 along with C3, which is typically 100nF, are required by the voltage regulator IC to ensure that the regulation remains stable.
In selecting values for C2 and C3, it is best to consult the datasheet for the voltage-regulator IC that you are using. This will normally specify values for the capacitors as well as tell you other important properties of the voltage regulator such as:
Some linear voltage regulators are described as low-dropout (LDO). These have a much smaller dropout voltage than the 2V of the 7805. Some only need as little as 150mV more at the input than the output. If the input voltage of the regulator does fall below the dropout voltage, the output voltage will gradually decrease as the input voltage decreases. These regulators such as the LM2937, which has a dropout of 0.5V, are great if your input voltage is unavoidably close to the desired output. Perhaps you have a 6V battery and require a 5V output. Keeping the input voltage close to the output voltage also helps to reduce the heat generated by the regulator.
Voltage regulators are available in various packages from tiny surface-mount devices to larger packages such as the TO-220 package of the 7805, which are designed to be bolted to a heatsink for higher current use.
Most voltage regulators including the 7805 have protection circuitry that monitors the device’s temperature and if it gets too hot, it drops the output voltage and therefore limits the output current so that the device is not destroyed by the heat. Voltage regulators also have a mounting hole designed to be attached to a heatsink. This is not needed for low currents, but as the current gets higher a heatsink (see Recipe 20.7) will become necessary.
The 05 part of the 7805 refers to the output voltage and, as you might expect, you can also find 7806, 7809, 7812, and other voltages up to 24V. There is also a parallel 79XX range of negative voltage regulators should you need to provide regulated positive and negative power supplies as you do for some analog applications.
The 78LXX range of regulators are a lower-power (and smaller package) version of the 78XX regulators.
You can find the datasheet for the 7805 here: https://www.fairchildsemi.com/datasheets/LM/LM7805.pdf.
These days, most regulated AC-to-DC power supplies use SMPS design (Recipe 7.8).
Use an adjustable voltage regulator like the LM317.
Figure 7-8 shows a typical schematic for a variable output voltage regulator using the LM317.
The output voltage of the LM317 varies according to the formula:
This only holds true as long as R2 is relatively low resistance (less than 10kΩ).
So, if R1 is 270Ω and R2 is a 2kΩ pot, then at one end of the pot’s travel, the output voltage will be:
When the pot’s knob is rotated fully the other way, the output voltage will be:
As R2 increases, the output voltage also increases, but as with a fixed-output regulator, the regulator requires some spare voltage to do the regulating with. In the case of the LM317, this is about 1.5V less than the input voltage.
Adjustable voltage regulators like the LM317 are available in a number of different-sized packages and able to handle different amounts of current before their temperature-protection circuitry kicks in to prevent damage to the IC.
You can find the datasheet for the LM317 here: http://www.ti.com/lit/ds/symlink/lm317.pdf.
To use an LM317 as a current regulator, see Recipe 7.7.
Use a fixed linear voltage regulator as shown in Figure 7-9.
New batteries have a voltage that often starts a little higher than the rated voltage (perhaps 9.5V for a 9V battery). This voltage drops as the battery is used. A 9V battery will quickly fall to 8V and will probably only provide useful power until it falls to perhaps 7.5V as it’s almost completely empty.
A voltage regulator can be used to provide constant output voltage during the lifetime of the battery and also to reduce voltage to a specific voltage needed for a microcontroller (usually 3.3V or 5V).
Unlike the transformer-based DC supply of Recipe 7.4 a battery does not suffer from ripple voltage, so the capacitor at the input to the voltage regulator can be omitted. However, the capacitor at the output is still needed in most applications as the load is likely to vary a lot and could cause instability in the regulator.
For more information on batteries, see Chapter 8.
Use an LM317 voltage regulator configured in constant-current mode as shown in Figure 7-10.
For the LM317 chip, the output current is set by the value of R1 using the formula:
So, to limit the current to a maximum of 100mA the resistor value would be chosen using:
This circuit will automatically raise and lower the output voltage to keep the current at the desired level.
To see this circuit limit the power to a high-power LED, see Recipe 14.2.
Use a switching voltage-regulator IC like the one in the schematic shown in Figure 7-11.
The LM2596 can provide a regulated power supply at 3A without needing a heatsink.
The FB (feedback) pin allows the regulator to monitor the output voltage and adjust the width of the pulses to keep the voltage constant. The EN (enable) pin can be used to turn the IC on and off.
Linear regulators as described in Recipe 7.4, Recipe 7.5, and Recipe 7.6 suffer from the disadvantage that they simply burn off the excess voltage as heat, which means they get hot and also waste energy.
Switching regulator designs such as the buck regulator shown in Figure 7-11 operate at 85% efficiency almost independently of the input voltage. By comparison, a linear regulator with a high input voltage and a low output voltage may only have an efficiency of perhaps 20 to 60%.
In a similar manner to PWM (see Recipe 10.8) a buck converter uses a transistor to switch power to an inductor that stores the energy of each pulse at a high frequency (150kHz for the LM2596). The longer the pulse the higher the output voltage. A feed-back mechanism changes the pulse length in response to the output voltage, ensuring a constant output.
It makes little sense to design a switching power supply from discrete components when there are ICs like the LM2596 that will do the whole thing so well.
There are many switching voltage-regulator ICs available and generally their datasheet will include a well-designed application circuit and sometimes even a circuit board layout.
If you are making a one-off project, then it is worth considering buying a ready-made switching-regulator module, either from eBay or suppliers like Adadruit and Sparkfun that specialize in modules.
You can find the datasheet for the LM2596 here: http://bit.ly/2lOLtHc.
Use a boost-converter IC as the basis for a design like the one shown in Figure 7-12.
This design will produce an output voltage of 5V from an input voltage of between 0.9V and 5V at 90% efficiency.
The SW (switch) output of the IC is used to send pulses of current through the inductor L1 generating high-voltage spikes that charge C1. The output VOUT is monitored through the FB (feedback) pin via the voltage divider formed by R1 and R2 that sets the output voltage.
The potential divider formed by R1 and R2 sets the output voltage. The value of R2 should be fixed at 180kΩ and the value of R1 calculated using the formula:
There are many similar boost-converter ICs available. In all cases, read the datasheet carefully as it will include a reference design and guides for finding the correct values for external components.
The datasheet for the TPS61070 can be found here: http://www.ti.com/lit/ds/symlink/tps61070.pdf.
Use an inverter. These devices use an oscillator to drive a transformer and generate high-voltage AC from low-voltage DC.
An inverter generates high-voltage AC, high enough voltage and current to stop your heart. So, do not attempt to make an inverter unless you are absolutely certain you have the knowledge and skills to do so safely.
Generating 110V from a low-voltage source (say a 12V car battery) is in theory very simple, but unless you really want to make such a thing yourself, it is generally cheaper and safer to buy a ready-made inverter product.
For more information on working with high voltages, see Recipe 21.12.
If you really do wish to make yourself an inverter, Figure 7-13 shows a typical schematic.
This design uses the CD4047 timer IC as an oscillator. This IC provides a similar function to the much more famous 555 timer (see Recipe 7.13, Recipe 7.14, and several recipes in Chapter 16) but has the advantage that it has both normal and inverted outputs. These two ouputs each drive an NPN Darlington power transistor to energize one half of the primary coil in turn.
The transformer used here is the kind used in recipes such as Recipe 7.1 to step down an AC voltage, but in this case, it will be used to step the voltage up. The windings that would normally be used as the secondary side of the transformer will be driven by the transistors and the output from the transformer will be taken from the coil that would normally have been connected to AC.
To drive the circuit from 12V DC at 60Hz to produce a 110V AC output you need a transformer with a 12-0-12V secondary and a 110V primary.
The power to the CD4047 is supplied through a 100Ω resistor (R5) and a 100µF decoupling capacitor (C3; see Recipe 15.1) across the IC’s power supply. These reduce noise on the power supply to the CD4047.
Figure 7-14 shows the inverter built on a breadboard. This arrangement is fine as a first prototype, but in practice the design would be better built onto a circuit board and the power transistors attached to sizeable heatsinks (Recipe 20.7). It would also be wise to include a fuse in the 12V supply line to limit the current to a value that the transistors can handle, otherwise the transistors could overheat and die.
The transformer used is a toroidal type that I had available, but any type of transformer can be used.
For information on using a 4047 IC see its datasheet.
To learn about fuses, see Recipe 7.16.
To build circuits using a solderless breadboard, see Recipe 20.1.
See Recipe 3.9 for more information on transformers.
You want to power your project from 110V or 220V AC supply efficiently, without using a large transformer like the one used in Recipe 7.2.
Designing SMPSs intended for high-voltage use is a specialized and potentially dangerous activity. Aside from the always present danger of electric shock, a poorly designed SMPS can easily overheat and become a fire hazard.
For these reasons, I strongly suggest that when you need to power a project from AC, use a ready-made commercial SMPS “wall wart” power adapter and fit a DC barrel jack socket to your project. These sealed adapters are readily available and made in such quantities that they will almost certainly be cheaper to buy than to make.
It is interesting to see how these power supplies work. Figure 7-15 shows how such a power supply can achieve the same power output of a transformer-based design (Recipe 7.2) with perhaps ⅒th of the weight.
The high-voltage AC input is rectified and smoothed to produce high-voltage DC in the same way as Recipe 7.2 but without using a transformer first. This DC is then “chopped” or switched at high frequency (often around 60kHz) into a series of short pulses that then feed an output transformer that steps down the high-frequency AC. The resulting low-voltage AC is then rectified and filtered into low-voltage DC. Because the transformer operates at such a high frequency, it can be made much smaller and lighter than a 60Hz transformer.
Voltage regulation is achieved by feedback from the DC output to the controller that alters the width of the pulses being chopped that in turn alters the DC output voltage.
To keep the DC output isolated from the high-voltage AC, the feedback path to the controller uses an opto-isolator (Recipe 5.8).
This might seem like a lot of extra complexity, but the size, weight, and cost advantages of reducing the transformer size is enough to make SMPSs worthwhile.
Although there are ICs that do a lot of the work of an SMPS, they still require quite a few external components such as an opto-isolator and a high-frequency transformer.
Another advantage of SMPSs over transformer-based power supplies is that they can generally accept input voltages from 80–240V, and if the input voltage is higher, you just end up with shorter pulses to generate the same output voltage.
For the old-fashioned transformer-based approach to AC to low-voltage DC conversion, see Recipe 7.2.
For more information on transformers see Recipe 3.9 and for opto-isolators see Recipe 5.8.
This is a job for the very elegant voltage-multiplier circuit, which uses a ladder of diodes and capacitors to increase the voltage without the use of inductors. It can be built in multiple stages to increase the voltage by different multiples. The schematic of Figure 7-16 shows a four-stage voltage multiplier that will multiply the AC voltage by 4.
To understand how this circuit works, consider what happens at the peak positive and negative value of the AC inputs. When the input is at its negative maximum, C1 will be charged through D1. On the next positive maximum, C1 will still be charged to the peak, but now, the input will be effectively added to C1. If we stopped there this would be a voltage doubler, but now C2 will charge from the next negative peak and so on until the output is at four times the peak input voltage.
The diodes should all be specified with a maximum voltage greater than the RMS AC input voltage times 1.4 (peak voltage). When selecting the capacitors (which should all be of the same value), you have a similar problem to that of selecting a smoothing capacitor in Recipe 7.2. If there is no load on the output then you can use very low value capacitors, but as soon as you add a load, they will discharge through it creating a ripple. Given that you will want the capacitors to be nonpolarized (no electrolytics here) and high-voltage, then you are likely to use something like 10nF capacitors rated for the same maximum voltage as the diodes for a low-current load such as a Geiger–Müller tube.
This kind of circuit is often used in high-voltage applications to multiply an initially high voltage up to even higher voltages.
For an example of using this kind of voltage multiplier in a power supply for a Geiger–Müller tube, see Recipe 7.14.
For background information on diodes and capacitors, see Recipe 4.1 and Recipe 3.1, respectively, and for background on AC see Recipe 1.7.
This circuit can generate voltages approaching 1000V. Although this is at low current, it will still give you a nasty jolt and could have disastrous consequences if you have a pacemaker or heart problems, so please be careful if you decide to make this recipe.
This is especially true if you reuse the transformer from the flash unit of a disposable camera, as these units have a large capacitor charged to 400V or more that can really hurt. So discharge the capacitor first (Recipe 21.7).
Use a version of the inverter circuit of Recipe 7.10 to drive a small high-frequency transformer. Figure 7-17 shows the schematic for the power supply. Note that D1 and C4 should both be rated at 1000V.
The 555 timer is designed to provide a frequency of between 7kHz and 48kHz controlled using the variable resistor R3. The Darlington transistor provides pulsed current to the transformer, the output of which is rectified and smoothed.
Altering the frequency will alter the output voltage. With a high-voltage multimeter (1000V DC) adjust the variable resistor until the maximum voltage is found. For my transformer this took place at a frequency of 35kHz.
Figure 7-18 shows the project built on two pieces of breadboard. The left breadboard has the 555 oscillator and the righthand board the transistor and high-voltage part of the design.
As you can see, the high-frequency transformer is tiny. The device I used is marked DT5A and is scavenged from the flash unit of an old disposable camera.
To check the output voltage, you will need a voltmeter with a 1000V DC range. Modern digital multimeters generally have an input impedance of around 10MΩ. At 1000V that means that a load current of 1kV / 10MΩ = 100nA. This does not sound like much, but for a low-current circuit like Figure 7-17, this loading may well reduce the voltage being measured. Increasing the value of C4, perhaps by putting a couple of capacitors of the same value in parallel with the original C4, should tell you if the multimeter is having an effect.
To measure high voltages reliably, you can use a specialist high-voltage meter with a very high input impedance, but these are expensive.
See Recipe 7.14 for a version of this design that adds a three-stage voltage multiplier to increase the output voltage.
For information on using the 555 timer, see Recipe 16.6.
For information on measuring high voltages, see Recipe 21.8.
To build circuits using a solderless breadboard, see Recipe 20.1.
The 450V output of Recipe 7.13 is not enough—you need 1.2–1.6kV for a Geiger–Müller tube that detects alpha radiation.
Add a three-stage voltage multiplier to the schematic of Recipe 7.13. The result of this is shown in Figure 7-19.
The diodes, C4, C5, and C6, can all still be rated at 1kV since the voltage across each should still be under 1kV.
As with the design of Recipe 7.13 the output of this design is likely to contain a few volts of unwanted noise.
For a version of this design without the voltage multiplier, see Recipe 7.13.
One common and safe design for a Tesla coil uses a homemade transformer. Figure 7-20 shows the completed Tesla coil illuminating an LED from a distance of half an inch and Figure 7-21 shows the power supply built on the breadboard.
Figure 7-22 shows the schematic for the project that uses a self-oscillating design based around a transformer and transistor.
The transformer for this design is made from a length of 2-inch plastic pipe onto which around 300 turns of 34 SWG (30 AWG) enameled copper wire are wound next to each other. The primary is made up of just three turns of plastic insulated multicore wire.
This circuit is called a solid-state flyback converter (sometimes called a slayer exciter). The top end of the transformer secondary is not directly connected to anything, but with the top end of the coil connected to something with a large area (such as the copper ball I used) there is a small stray capacitance to ground. The top surface of the large area could be a metal plate or various other arrangements, as long as it’s made from a large conducting area without too many sharp points to encourage discharge.
When power is first applied to the circuit, the transistor will turn on through R1, resulting in a large current flowing through the three turns of the transformer primary. This induces current to flow through the secondary, creating a potential difference due to the stray capacitance. Although small, this capacitance is sufficient to reduce the voltage on the bottom end of the secondary (and base of the transistor) to such an extent that the transistor turns off. The LED ensures that the base never falls more than 1.8V (the forward voltage of the LED) below ground. Because the transistor turns off, the magnetic field collapses and R1 reasserts its influence over the transistor’s base to turn the transistor back on and so the cycle continues.
If you get the connections of the primary the wrong way around, or even just the geometry of the secondary wrong, there is a chance the transformer will turn on but oscillation fail to start, which will rapidly destroy the transistor. If all is well, LED1 will light. A lab power supply with current limiting is very useful in this situation (see Recipe 21.1).
Holding a second LED close to the high-voltage end of the secondary will cause it to light. By holding one lead of the LED, you will be providing a weak path to ground.
A quick way to increase the power of the circuit is to place several transistors in parallel (all three pins). By using four 2N3904s I was able to generate enough voltage to cause the gas in a compact florescent lamp to ionize, lighting the lamp from a range of almost a foot.
For information on prototyping with a solderless breadboard, see Recipe 20.1.
You can see this Tesla coil in action at https://youtu.be/-DEpQH7KMj4.
For other types of high-voltage power supply, see Recipe 7.13 and Recipe 7.14. The “joule thief” circuit (Recipe 8.7) operates in a similar way to this design.
To see a miniature Tesla coil design in action using a ferrite core rather than an open tube, visit https://www.youtube.com/watch?v=iMoDAspGPPc. The design here uses the same schematic as in Figure 7-22.
If you search the internet for Tesla coil, you will find some incredible builds.
Use a fuse. Figure 7-23 shows a selection of fuses.
Fuses can be broadly classified as one-shot traditional fuses or polyfuses. As the name suggests, one-shot fuses can only be used once. When their current or temperature limits have been exceeded and they have blown, that’s it, they must be discarded. For this reason they are generally attached to electronics using a fuse holder, so they can be replaced easily.
Polyfuses (a.k.a. resettable fuses) do not blow, but when the current through them increases above their limit value, their resistance increases, only resetting when the current returns to zero and they have cooled down. This means they can be permanently attached to a circuit. You will often find them used in places like USB ports, where you need to protect computer ports against overcurrent by misbehaving peripherals. Polyfuses use the same technology as PTC thermistors (see Recipe 2.9).
In modern circuit design, and especially for low-voltage and relatively low-current use, polyfuses are the best approach. However, for AC applications and other high-current situations, where overcurrent will only happen if something is seriously wrong, then traditional single-use fuses are the safest option because they require manual intervention before the power can be reapplied to the downstream circuit.
If a single-use fuse blows, then work out why it blew before replacing it. The most likely cause of overcurrent is a short circuit, either from wires touching that should not be touching, or a component failing that causes some part of the circuit to draw more current than it should.
There are a number of different single-use fuses:
To test a fuse, see Recipe 21.5.
For a circuit to produce a constant current, see Recipe 7.7.
To protect a circuit against accidental polarity reversal, see Recipe 7.17.
Many ICs and circuits designed with discrete transistors will be destroyed by overcurrent and hence heating if the power is applied with the wrong polarity.
If you don’t care about a small voltage drop of 0.5V to 1V, then use a single diode from the positive battery terminal to the positive supply of your circuit (see Figure 7-24).
Remember to select a diode that can handle the current that you expect the circuit to draw.
If you can’t afford to lose a volt through the diode but are losing 0.2–0.3V, then use a Schottky diode in place of the regular diode.
If even 0.3V is too much to lose, then use an P-channel MOSFET as shown in the circuit in Figure 7-25.
With the correct polarity, the P-channel MOSFET’s gate-drain voltage will be high enough to keep the MOSFET on. Since MOSFETs with extremely low on-resistances are available, there will be very little voltage drop across the MOSFET to the load. The circuit only works for battery-supply voltages over the gate-threshold voltage, or the MOSFET will not turn on.
When the polarity is reversed, the MOSFET will be firmly off, preventing any significant current from flowing into the load circuit.
Remember that the link between the gate and other connections of the MOSFET is capacitative and so no current can leak through the gate to the negative terminal of the battery.
Although almost by tradition people tend to prefer to switch and use polarity protection on the positive supply, you can also do the same trick with an N-channel MOSFET on the negative battery supply as shown in Figure 7-26.
It’s a good idea to include polarity protection in any battery-powered project, even with a 9V battery that has a clip that only goes one way around, because it is all too easy to touch the wrong contacts together.
Using a MOSFET is probably the cheapest way to protect a design, as it can cope with several amps and will generally be smaller and cheaper than a diode with the same properties, especially in surface-mount technology.
To use fuses to protect a circuit against overcurrent, see Recipe 7.16.
For background on diodes, see Chapter 4.
For more information on MOSFETs, see Recipe 5.3.
In Chapter 7 you learned about various ways of supplying low-voltage DC to your electronics designs from AC. In this chapter you will learn how to use various types of batteries and photovoltaic solar cells.
The capacity of a battery is specified in Ah (ampere hours) or mAh (milliampere hours). To calculate how many hours your battery will last, you need to divide this number by the current consumption of your project in A or mA.
For example, a 9V PP3 rechargeable battery typically has a capacity of about 200mAh. If you were to connect an LED with a suitable series resistor that limited the current to 20mA, the battery should be good for about:
The estimate of time you get using the preceding calculation is very much an estimate and all sorts of factors such as the age of the battery, the temperature, and the current will affect the actual battery life.
If you are using a number of batteries in serial (e.g., in a battery holder that contains 4xAA batteries), then you do not get to multiply the battery life by 4, because the same current will be flowing out of each battery (Figure 8-1).
From Kirchhoff’s Current Law (Recipe 1.4) we know the current flowing past any point in the circuit will be the same. Assuming an LED with a forward voltage of 1.8V the current will be around 9mA. Even though there is more than one battery cell, each cell will have 9mA flowing through it. A typical AA battery has a capacity of around 2000mAh and so we could expect this circuit to run for:
It is best to avoid putting batteries in parallel because none of the cells in the battery will be at exactly the same voltage and when you connect them together, the first thing that will happen is their voltages will equalize with the higher voltage batteries discharging into the lower voltage batteries. If the batteries are rechargeable, you may be okay if the voltage difference is very small, but for nonrechargeable batteries, this charging process can heat the batteries and be dangerous.
Batteries all have an internal resistance, very similar to the ESR of a capacitor (Recipe 3.2). This will cause heating as the battery discharges, which is why you cannot use a small 200mAh battery to supply 10A for 72 seconds. The internal resistance of the battery will both limit the current and cause the battery to heat up. Small batteries tend to have higher internal resistance than big batteries.
Most nonrechargeable batteries bought from a component supplier will specify the maximum continuous discharge current.
For information on choosing between different types of rechargeable batteries see Recipe 8.3 and for nonrechargeable batteries see Recipe 8.2.
To measure the current used by your project using a multimeter, see Recipe 21.4.
Decide what your minimum battery life for the product should be and calculate the capacity of the battery you need in mAh, then use Table 8-1 to select a battery.
If you need more volts than a single battery cell provides, then place several of the cells in series in a battery holder.
| Battery Type | Approx. Capacity (mAh) | Voltage (V) |
|---|---|---|
| Lithium Button Cell (e.g., CR2032) | 200 | 3 |
| Alkaline PP3 Battery | 500 | 9 |
| Lithium PP3 | 1,200 | 9 |
| AAA Alkaline | 800 | 1.5 |
| AA Alkaline | 2,000 | 1.5 |
| C Alkaline | 6,000 | 1.5 |
| D Alkaline | 15,000 | 1.5 |
Higher capacity nonrechargeable batteries are expensive and so C and D cells are found less and less often in favor of rechargeable LiPo battery packs (see Recipe 8.3).
You should also be wary of using exotic or unusual batteries. It’s generally a good idea to stick to universally available batteries like AA cells unless you need something smaller in which case AAA batteries will do.
Battery holders such as the 4 x AA battery holder shown in Figure 8-2 are readily available to hold 1, 2, 3, 4, 6, and 8 AA cells to make a battery pack capable of supplying 1.5, 3, 4.5, 6, 9, and 12V, respectively.
Perfect batteries would allow you to draw as large a current as you want. However, in reality batteries have a small resistance that will cause heating as the battery discharges. The higher the current the greater the heat produced. Smaller capacity batteries have a lower maximum discharge rate than larger batteries.
For information on rechargeable batteries, see Recipe 8.2.
Decide how long you would like your project to operate between charges and use Table 8-2 to choose a battery.
| Battery Type | Approx. Capacity (mAh) | Voltage (V) |
|---|---|---|
| NiMh button cell pack | 80 | 2.4-3.6 |
| NiMh AAA cell | 750 | 1.25 |
| NiMh AA cell | 2,000 | 1.25 |
| LC18650 LiPo cell | 2,000 to 8,000 | 3.7 |
| LiPo Flat cell | 50 to 8,000 | 3.7 |
| Sealed lead acid (SLA) | 600, 8,000 | 6 or 12 |
LiPo (lithium polymer) and the closely related lithium ion cells are the lightest and also now as cheap per mAh as older technologies such as MiMh, but they require care when charging and discharging or they can catch fire (see Recipe 8.6).
You will still find NiMh batteries in products like electric toothbrushes. They are heavier than LiPos of the same capacity but are easy to charge (see Recipe 8.4).
SLA batteries (sealed lead acid) are even heavier than NiMh cells but cope well with trickle charging and last for years. However, their use is on the decline in favor of lighter-weight LiPo batteries.
Many rechargeable batteries will specify safe charge and discharge rates in units of C. This refers to a ration of the battery’s nominal capacity. So, a 1Ah battery that says it can be discharged at 5C is capable of supplying 5A (5 x 1A). If the maximum charge current is specified as 2C the battery can be charged at 2A.
For a similar recipe but for nonrechargeable batteries, see Recipe 8.2.
You want to charge a NiMh or SLA battery while it’s connected to your circuit and you don’t need to charge it quickly.
Note that LiPo batteries should not be trickle charged in this way. Instead, see Recipe 8.6 on charging LiPo batteries.
Trickle charge the battery from a power supply using a resistor to limit the current. If you don’t know how the power supply works, then also include a diode in the circuit to prevent damage to the power supply when the power is turned off. Figure 8-3 shows the schematic for charging a 6V battery from a 12V supply.
A battery’s datasheet will specify the charging current to use for fast charging and in this case slow trickle charging in terms of C, where in this case, C is not capacitance but rather the capacity of the battery in mAh. So the datasheet for an AA rechargeable battery might say that it should be trickle charged at C/10 mA, meaning that if the battery is a 2000mAh AA cell, it can be trickle charged at 2000/10 = 200mA indefinitely without damaging the battery. Charging below 200mA will still result in the battery being charged, and in situations like battery backup (Recipe 8.5) charging at C/50 (40mA) is probably a good compromise between charging speed and power consumption of the circuit.
To charge at 40mA we just need to set the value of R. The voltage across R will be 12V – 6V – 0.5V = 5.5V. We know that the current is 40mA, so we can calculate R using Ohm’s Law as:
Using the standard resistor value of 120Ω will result in a slightly higher current of:
We also need to make sure the resistor has a sufficient power rating, which we can calculate as:
So, a ¼W resistor is probably OK, but ½W would not get as hot.
An alternative to using a resistor to limit the current is to use Recipe 7.7 to provide a constant charging current. This design is more complex and expensive, but will cope better with variations in the input voltage and the battery’s voltage changing as it charges.
Charging from a photovoltaic solar cell is very similar to trickle charging (see Recipe 9.1).
Use a battery of slightly lower voltage than the power adapter–supplied voltage and a pair of diodes in the arrangement shown in Figure 8-4.
The diodes ensure that the output is supplied from either the battery or the power supply, whichever has the higher voltage. Since you want the power supply to be providing the voltage most of the time, arrange for it to be a volt or more higher than the battery voltage (remember the battery voltage will drop as it discharges). In Figure 8-4, when the power supply is producing 10V, D1 will be forward-biased (conducting) and D2 reverse-biased. This reverse-biasing of D2 prevents any accidental charging of the battery (which may not be rechargeable). If the power supply were to turn off, D2 becomes forward-biased, providing the output voltage and D1 would become reverse-biased preventing any possible flow of current into the power supply that could damage it, especially if it is an SMPS design (Recipe 7.8).
When selecting a diode type for D1 and D2, you need to make sure it can handle the current that the output needs to provide. Although in most cases regular diodes like the 1N4xxx series are just fine, they will result in a forward-voltage drop of at least 0.5V. You can reduce this voltage drop by using Schottky diodes (Recipe 4.2).
The circuit of Figure 8-4 will work just fine for rechargeable or nonrechargeable batteries, but it will not charge the batteries. If using rechargeable batteries, you can modify the circuit slightly so that the power supply trickle charges the battery and supplies the output. Figure 8-5 shows the schematic for this. See Recipe 8.4 for the calculation for the charging resistor.
Now when the power supply is in charge some of the current from D1 will flow through R1 and charge the battery (D2 is reverse-biased and can effectively be ignored). When the power supply is off (0V) D2 becomes forward-biased and supplies power to the output. At this time, R1 becomes irrelevant as D2 will be conducting.
See Recipe 4.2 for help selecting the right diode.
For the basics of what diodes do, see Recipe 4.1.
Use a LiPo-charging IC designed specifically for the purpose of charging LiPo batteries. The schematic of Figure 8-6 is an example design using the MCP73831 IC.
Many consumer electronics use LiPo batteries (often charged from a USB connection) with chips like the MCP73831 and many are low cost (less than $1) and include all sorts of advanced features that make sure the LiPo cell is charged safely.
The MCP73831 only needs two capacitors and a resistor to make a complete LiPo-charging circuit. The LED and R2 provide a status indicator that shows that the battery is charging and can be omitted if you don’t need it.
The chip will automatically control the charge current, turning it to a safe trickle charge when the cell is fully charged. However, you can set the maximum charge current in amps (consult the datasheet for the LiPo cell that you plan to use) by means of R1, using the formula:
So, to charge at 500mA (the maximum allowed by the chip anyway) set R1 to 2kΩ.
As an alternative to using a design of your own to charge a LiPo cell, you can also buy ready-made LiPo charge modules such as the Adafruit 1905 and Sparkfun PRT-10217 (both use the MCP73831).
LiPo batteries have made the news in recent years because they will catch fire if abused. Using a charger chip like the MCP73831 in your circuits will help ensure your design is safe and reliable. For extra safety, you can add a thermal fuse (Recipe 7.16) to the supply to the charging circuit.
If you are looking for a lower-tech solution then consider using a NiMh or SLA battery instead.
Unlike NiMh or SLA batteries, LiPo batteries are not suited for charging in parallel. Each cell effectively has to be charged independently using special hardware. If your project cannot operate directly from the 3.7V of a LiPo cell and needs a bit more voltage, then it is generally easier to use a boost converter (Recipe 7.9) to generate the voltage you need.
You can find the datasheet for the MCP73831 here: http://bit.ly/2n2XUPP.
The novelty circuit known as a joule thief allows you to power an LED from an alkaline AA cell even when its voltage drops to around 0.6V.
A joule thief is actually a small self-oscillating boost converter (see Recipe 7.9) that requires just a transistor, resistor, and homemade transformer to drive an LED from a single 1.5V battery, even when the battery voltage drops as low as 0.6V. The circuit is shown in Figure 8-7.
The circuit is very similar in operation to the self-oscillating boost converter used in Recipe 7.15 except that the secondary winding has the same number of turns as the primary and is connected back to the base via a resistor rather than using parasitic (from the winding) capacitance.
Figure 8-8 shows a joule thief. This circuit is interesting because it is fun to make one and see just how long an AA battery can power an LED.
I made my transformer by winding 12 turns of 30 AWG (34 SWG) enameled copper wire, for each winding, around a tiny toroidal ferrite core. In reality, more or less of any ferrite core and even plastic insulated wire will work just fine.
The supply generates pulsed DC at a frequency of about 50kHz (depending on the transformer).
For more practical boost converters, see Recipe 7.9.
Recipe 7.15 uses a very similar circuit to this recipe.
For information on wire gauges, see Recipe 2.10.
Use a photovoltaic solar panel (Figure 9-1) to generate electricity to trickle charge a battery that then supplies your project. The leftmost panel in Figure 9-1 is reclaimed from a low-power solar LED on a stick that cost about $1.50.
Figure 9-2 shows the schematic for solar charging a battery.
Solar panels are made up of a number of solar cells wired together in series to increase the output voltage. You will need a solar panel with an output voltage that is greater than the battery voltage.
The diode D1 is essential to prevent current from flowing back through the solar panel and damaging it when the solar panel is not illuminated enough for its output voltage to exceed the battery voltage.
R1 sets the charging current in just the same way as trickle charging (Recipe 8.4). As with trickle charging, you can also use a current regulator such as the one described in Recipe 7.7.
The performance of the solar panel varies enormously with the amount of sunlight falling on it. A solar panel will produce useful amounts of power when in direct sunlight, but in shadow or on a cloudy day it is unlikely to produce any more than 1/20 of its direct sunlight performance.
If you are thinking of using a solar panel to power a project indoors, unless you plan to keep the project on a sunny window sill or your project uses microamps, then forget it. The size of panel that you will need will make the project huge.
Two key parameters specified for a solar panel are its nominal output voltage and its power output. Both these values require some explanation.
The power output of the panel in mW for a small panel and W for a larger panel, as stated in the specification for the panel, is the power output under ideal conditions. That is, pointing directly at the sun without clouds, haziness, or any other impairments. In Table 9-1 you see the results of practical tests on the solar panels shown in Figure 9-1. These tests were carried out in the early afternoon at my home (53° latitude). The “no direct sunlight” readings were made with the panel pointing at clear sky but away from direct sunlight. For details on how to take such measurements yourself, see Recipe 9.3.
| Nominal Power |
Dimensions (inches) |
Actual Output (direct sunlight) |
Actual Output (no direct sunlight) |
Guide Price (2016) |
|---|---|---|---|---|
| Unknown | 1x1 | 40mW | 1.4mW | $1 |
| 1W | 6x4 | 210mW | 8.4mW | $5 |
| 20W | 22x12 | 6.9W | 86mW | $40 |
Two things emerge from these measurements. First, the actual power output, even for the highest quality panel (the 20W panel), was actually almost ⅓ of its rated value. Secondly, when out of direct sunlight, the power output fell to almost 1/100 of the full-sunlight reading in the worst case. Now, while I’m sure the panels would do better at noon near the equator, that’s not where most of us live.
Similarly, the output voltage at suboptimal lighting levels is also not the same as the specified output voltage. Table 9-2 shows the no-load output voltage for the same solar panels.
| Nominal Output Voltage |
Actual Output (direct sunlight) |
Actual Output (no direct sunlight) |
|---|---|---|
| 2V | 2.2V | 1.9V |
| 6V | 10.6V | 9.7V |
| 12V | 21.3V | 18V |
The output voltage is higher than the nominal voltage so it can be used to charge a battery of nominal voltage.
To work out the power output of the solar panel that you need, see Recipe 9.3.
For the basics of trickle charging, see Recipe 8.4.
This solution will not give you an exact solar-panel power requirement and accompanying battery capacity, but it will at least give you a rough estimate to get you started with field testing.
Start by calculating the energy use of your project in Ws (joules) for a 24-hour period because a 24-hour day will include both the daylight and nighttime parts of the daily cycle. Calculating this current consumption is easy if the device is on all the time and the current consumption is constant. Let’s say we have a garden temperature sensor that uses WiFi and consumes a constant 70mA from its 5V power supply. The power consumption is therefore 70mA x 5V = 350mW. The energy consumption is 350mW times the number of seconds in 24 hours. That is, 350mW x 24 x 60 x 60 = 30,240J.
This means that we need a solar panel that can during a 24-hour period provide 30,240J of energy. You can calculate the required solar-panel power using the formula:
where E is the energy needed (30,240 in this example) and H is the average number of hours that the solar panel will be in direct sunlight. Let’s assume that you live in the tropics, have more or less no seasonal variation in day length, and 10 hours of sunlight a day. In that case you can calculate the power of the panel you need as:
So, in theory a 1W solar panel is fine for this particular situation.
If you think you might need the thermostat to keep working for three days without any solar charging (perhaps during a tropical storm) you will need a battery that can deliver 3 x 30,240 = 90,720J of energy.
The storage capacity in mAh (C) can be calculated using this formula:
This equation has made a number of optimistic assumptions. First, the tropical daylight pattern is likely to be markedly different from a wet maritime climate at high altitude. In that case, you may only be able to assume a much lower average. For example, according to US Climate Data, December in Seattle only averages 62 hours of sunshine in the entire month (2 hours a day). This would require a solar panel of five times the power of the tropical equivalent.
The equation also assumes that any voltage conversion that is needed between the output of the solar panel down to the battery voltage is 100% efficient. If you are using a switching regulator like Recipe 7.8 then you might get 80%, but a linear regulator will not be as good, maybe only 50% or lower.
Also, the battery you are charging or the circuit charging it may limit the maximum power that you are using from the solar panel to prevent damage to the battery by charging it with too high a current. This all needs to be taken into account. Using a higher power solar panel than your battery can keep up with will have the advantage that under lower light conditions you will still get some charging.
All in all, using the worst-case sunshine hours scenario for your location, you should probably use double the calculated solar-panel output power requirement as your starting point, before ordering any solar panels to start experimenting with.
In addition to assumptions about the generation side of things, the load side is also often a lot more complicated than a constant load current. It may be that a device has a constant standby current most of the time, but then is turned on by a user or as a result of a timed operation and uses considerably more current for a while, before going back to standby mode. In addition to manually logging the current consumption and making estimates of the energy usage over 24 hours, you can also use a logging multimeter that will make and store periodic readings of current consumption. The resulting data can be downloaded into a spreadsheet for further analysis.
A logging multimeter can also be a great way of assessing the real performance of a solar panel (see Recipe 9.3).
If you are making a solar-powered project, then it is always worth working out how to keep the power consumption to a minimum. For an Arduino or other microcontroller project this may mean making the microcontroller go into a low-power sleep most of the time, just waking periodically to check if anything needs to happen.
Of course, some projects (maybe a solar-powered water pump) don’t need a battery backup because they only need to operate when it’s sunny.
For information on measuring the actual power output of a solar panel, see Recipe 9.3.
For examples of this approach for powering an Arduino see Recipe 9.4 and for a Raspberry Pi see Recipe 9.5.
Using a load resistor attached to the solar panel, measure the voltage across the resistor and from this calculate the power output. Figure 9-3 shows this arrangement.
The output power of the solar panel P is calculated as:
So, if you use a 100Ω load resistance and the voltage is 5V, the output power of the solar panel is:
The value of the load resistor needs to be low enough that the maximum output power of the solar panel is not exceeded, otherwise the solar panel will not generate as much as it could. In other words, if the solar panel is a 12V panel, you will probably find that the no-load output voltage is up to 18V in bright sunlight. So, you really want a load resistor value that gives an output of about 12V. You can calculate the maximum value of resistor to use using:
So, if your solar panel claims to be 20W at 12V, an ideal resistor value would be:
Remember that the resistor will have to have a power rating sufficient to handle the full power output of the panel—in this case 20W.
In addition to simply taking readings under different circumstances (full sunlight, shade, etc.) you can also use a logging multimeter such as the one shown in Figure 9-4 to record the voltage across the load resistor at regular intervals.
This way, you can create a picture of what your panel is likely to generate in a day.
In Recipe 9.2 this measurement technique was used to assess the performance of some of my solar panels.
For information on using a voltmeter, see Recipe 21.2.
Use a 5V solar cellphone charger, like the one shown in Figure 9-5.
Unless you are designing a product, using a ready-made charger circuit is by far the easiest way of solar powering your Arduino.
An Arduino Uno uses around 50mA, so a 4Ah charger/battery like the one shown in Figure 9-5 will power the Arduino for around:
The Arduino Uno is not the most efficient of boards, when it comes to trying to minimize current consumption. It is more efficient to use an Arduino Pro Mini that has an external USB interface that you only need to connect when programming the Arduino. This can reduce your current consumption to 16mA. Using software to put the Arduino to sleep periodically can also greatly reduce current consumption.
For an introduction to Arduino, see Recipe 10.1.
To power your Raspberry Pi from solar, you will need a bigger solar panel than provided with ready-made phone boosters, as the Raspberry Pi is considerably more power hungry (see Recipe 9.5).
Use a 12V solar cell, charge controller, and SLA battery with a 12V to 5V power adapter.
This may sound excessive, but a Raspberry Pi with a WiFi adapter (WiFi is power hungry) can easily consume 600mA. If you add in a small 12V HDMI monitor, then you are likely to be drawing well over 1A.
Figure 9-6 shows a typical setup.
A ready-made charge controller generally has three pairs of screw terminals. One is attached to the solar panel, one to the battery, and one pair for the load, which in this case is a 12V to USB (5V) adapter commonly used as a phone car charger. Be sure to use one that can supply at least 1A.
To run the Raspberry Pi continuously, you will need a 20W or greater solar panel. The choice of battery size depends on how long you want your Pi to keep running after it goes dark, or is dull for a few days. See Recipe 9.2 for information on how to make that choice.
If you are planning to use your Raspberry Pi as a controller, you may want to consider whether it would be better to use an Arduino, which uses only ⅒ of the power, or if you need network connectivity, a Particle Photon or an ESP8266 module (see Recipe 10.6), both of which use less than 100mA.
To power an Arduino using solar energy, see Recipe 9.4.
There is a good chance that any electronics project that you embark on will involve the use of a microcontroller (in the form of an Arduino) or a single-board computer (SBC) like the Raspberry Pi. Our gadgets are becoming more intelligent, requiring a little computer brain to control them; they are also becoming more connected, often needing an interface to the internet.
A typical Maker’s electronics project these days will involve the use of a microcontroller or SBC with some electronics to switch things or sense value, or both. These extra electronics are attached to the microcontroller or SBC using its GPIO (general-purpose input/output) pins.
In this chapter the recipes mostly focus on the electronic side of interfacing with a microcontroller or SBC in general, but will also use the Arduino and Raspberry Pi as examples.
You want to understand just what an “Arduino” is and why it finds its way into so many electronics projects.
Figure 10-1 shows the most popular flavor of Arduino, the Arduino Uno R3.
An Arduino is not a microcontroller but instead a microcontroller interface board. It has a microcontroller chip on the board, but it also has a whole load of other components that provide:
An Arduino does not do anything until it has been programmed. That is, you have to use your computer to write some instructions in the programming language C that can control and read the GPIO pins. Special software, called the Arduino IDE, is provided to both write the programs and then upload them onto the Arduino using a USB cable. Figure 10-2 shows the Arduino IDE with the “Blink” program loaded and ready to transfer to your Arduino. As its name suggests, the Blink program simply makes the Arduino’s built-in LED blink on and off and is the starting point for most people’s Arduino adventures.
You can download the Arduino IDE from http://arduino.cc.
In this book, it will be assumed that you have experimented with Arduino and at least got as far as uploading a program onto it to make an LED blink. If you are new to programming or need a slower-paced introduction to Arduino, then see some of the book suggestions at the end of this recipe.
In addition to the GPIO pins that you will learn more about in Recipe 10.7 the Arduino also has peripheral interfaces for I2C (Recipe 14.9 and Recipe 14.10) and SPI devices (Recipe 19.4).
The Arduino is an extremely useful and reliable component to use in your designs, even if it is just while you are prototyping the project and will later build your own design with a microcontroller.
In addition to the Arduino Uno shown in Figure 10-1, there are many other types of Arduinos that are all programmed the same way. This means you can select an Arduino based on its price, size, and number of GPIO connections.
There are many excellent books written about Arduino that will help you fill in the background. Two I particularly recommend are:
The following is a list of some of the Arduino-related recipes in this book, outside of this chapter:
All the Arduino sketches and Python programs for Raspberry Pi for this book are downloadable from GitHub.
To use the Arduino sketches, download them from GitHub by cloning the directory if you are a git user, or use the Download Zip option behind the Clone or Download button on the GitHub page. You do not need to have a GitHub login to download the files.
Once extracted, the directory contains a directory called arduino with each of the Arduino sketches inside its own directory. Double-clicking on it will open the sketch in the Arduino IDE.
An alternative way to access the sketches is to copy the contents of the arduino directory that you downloaded from GitHub into your Arduino IDE’s sketches directory, which is found in your operating system’s Documents or My Documents (Windows) folder in a directory called Arduino. Then you will be able to open any of the sketches from the File→Sketchbook menu of the Arduino IDE.
To download the Python files for Raspberry Pi, see Recipe 10.4.
If you are looking for a primer to teach you Arduino C, then my book Programming Arduino: Getting Started with Sketches (TAB DIY, 2016) should help you out.
You want to understand just what a “Raspberry Pi” is and why it finds its way into so many electronics projects.
A Raspberry Pi (Figure 10-3) is an SBC running a version of Debian Linux (called Raspbian) as an operating system. You can plug in a keyboard, mouse, and monitor and use it to browse the internet just like a “normal” computer.
The Raspberry Pi is available in a number of different sizes, from the very low-cost Pi Zero up to the Model 3, which includes built-in WiFi.
The reason the Raspberry Pi has become popular for electronics projects is that, like the Arduino, it also has GPIO pins that you can connect to external electronics. What’s more, because the Raspberry Pi can be easily connected to the internet, you can also use it for all sorts of Internet of Things (IoT) projects.
When it comes to programming the Raspberry Pi, there are lots of options. In fact, all major programming languages are available to run on the Raspberry Pi, but the most popular language for electronics projects is probably Python, which is used in conjunction with the RPi.GPIO library.
While you need a computer to program an Arduino, to write programs for Raspberry Pi, you will use the Raspberry Pi itself.
To use a Raspberry Pi unattended, you will want to be able to make your program automatically run when the Raspberry Pi Boots up (Recipe 10.3).
My book The Raspberry Pi Cookbook by O’Reilly (2016) is a cookbook like this, but dedicated entirely to the Raspberry Pi.
If you are new to programming and need a gentle introduction to Python programming on the Raspberry Pi, you might want to consider my book Programming the Raspberry Pi: Getting Started with Python (TAB DIY, 2015).
Here is a list of some of the Raspberry Pi-related recipes in this book outside of this chapter:
All the Python programs for Raspberry Pi for this book can be found here: https://github.com/simonmonk/electronics_cookbook.
To use the programs, you can fetch them from GitHub directly onto your Raspberry Pi using the command:
$ git clone https://github.com/simonmonk/electronics_cookbook
This will also fetch all the Arduino sketches, but these can be ignored. You will find the Python programs in a directory called pi.
To run a program (e.g., blink.py) use the following command:
$ sudo python blink.py
Note that the sudo command is not required on the latest version of the Raspberry Pi’s operating system (Raspbian) so you may be able to just type:
$ python blink.py
Although I suggested ignoring the Arduino sketches earlier in this recipe, in reality you can download and install the Arduino IDE onto a Raspberry Pi and then use the Raspberry Pi to program the Arduino (see http://spellfoundry.com/sleepy-pi/setting-arduino-ide-raspbian/).
To access the Arduino code, see Recipe 10.2.
To set a Raspberry Pi Python program to automatically run on startup, see Recipe 10.5.
If you are looking for a primer to teach you Python with Raspberry Pi, my book Programming Raspberry Pi: Getting Started with Python (TAB DIY, 2015) should help you out.
Modify your rc.local file to run the program you want.
Edit the file /etc/rc.local by using the command:
$ sudo nano /etc/rc.local
Add the following line after the first block of comment lines that begin with #:
/usr/bin/python /home/pi/my_program.py &
It is important to include the & on the end of the command line so that it runs in the background; otherwise, your Raspberry Pi will not boot.
Be careful when you edit rc.local, or you may stop your Raspberry Pi from booting.
For general background on Raspberry Pi, see Recipe 10.3.
Table 10-1 lists some other popular boards (MC, microcontroller; SBC, single-board computer).
| Board | Type | Notes |
Arduino IDE Compatible |
Website |
|---|---|---|---|---|
| Digispark | MC | A tiny Arduino compatible with just a few GPIO pins that plugs straight into your computer’s USB port for programming. | Y | digistump.com |
| Adafruit Feather | MC | A small Arduino compatible with built-in LiPo battery charger and a range of wireless options. | Y | adafruit.com |
| NodeMCU | MC | A small, very low-cost board that can be easily converted to use the Arduino IDE. It has built-in WiFi. | Y | eBay |
| Particle Photon | MC | A small, low-cost Arduino compatible with built-in WiFi and IoT software built-in. | N | particle.io |
| Teensy3 | MC | A small, low-cost Arduino compatible. | Y | pjrc.com |
| BeagleBone Black | SBC | A Raspberry Pi alternative with more GPIO pins and analog inputs. | N/A | beagleboard.org |
| ODROID-XU4 | SBC | An 8-core 2GHZ South Korean monster SBC. | N/A | hardkernel.com |
Some of these boards are shown in Figure 10-4.
The Arduino IDE is a very flexible piece of software that can be easily extended to operate with unofficial Arduino-type boards. This means that you can stick to the Arduino IDE and the Arduino C programming language to program Arduino-like boards that may use a different processor or include useful addons such as WiFi, Bluetooth, or battery-charging hardware.
The Particle Photon deserves special mention, since although it uses a language that is based on Arduino C, you do not program it with the Arduino IDE, but rather with a web-based IDE. Deployment is then over the internet, allowing remote updating of applications. It also includes a very easy-to-use software framework for building IoT projects.
Other good boards to use where WiFi is required are any of the boards based on the ESP8266 modules, such as the NodeMCU and smaller modules like the ESP01. These can be programmed from the Arduino IDE. The ESP8266 boards are not as simple to use as the Photon but are extremely cheap.
For information on the Arduino see Recipe 10.1 and for the Raspberry Pi, see Recipe 10.3.
Microcontrollers and SBCs have GPIO pins that allow you to connect external electronics to them. Figure 10-5 shows the schematic for a typical GPIO pin within a microcontroller chip or SoC of a Raspberry Pi. The pin can function as either a digital input or digital output, under software control.
Referring to Figure 10-5, if the output enable control of the GPIO is set using software to be enabled, the pin functions as a digital output and the push-pull driver (Recipe 11.8) allows the GPIO pin to source or sink a few tens of milliamps.
If the push-pull driver is disabled, then the pin can function as a digital input. If the pull-up resistor enable control is set, then the transistor Q1 is enabled to allow the resistor to pull up the input to a default high. This is commonly used when connecting a switch to a digital input to prevent a floating input from oscillating between high and low (see Recipe 10.7).
The GPIO schematic of Figure 10-5 is typical of most Arduino pins. Some of the Arduino pins (marked A0 to A5) can be used as analog inputs and for those pins, the GPIO is also connected to ADC hardware inside the microcontroller chip.
Some GPIO pins have pull-down resistors as well as pull-up resistors, which can be turned on and off in the same way as pull-down resistors.
Table 10-1 compares the GPIO features of an Arduino and Raspberry Pi 3.
| Feature | Arduino Uno R3 | Raspberry Pi 3 |
|---|---|---|
| Operating voltage | 5V | 3.3V |
| Maximum individual output current | 40mA | 18mA |
| Maximum total current for all pins used as outputs | 400mA | Not specified |
| Internal pull-up resistors | Y | Y |
| Internal pull-down resistors | N | Y |
| Number of GPIOs | 18 | 26 |
| Analog inputs | 6 | None |
Figures 10-6 and 10-7 describe each of the accessible GPIO and power pins available on an Arduino and Raspberry Pi 3, respectively.
Some of the pins require a little more explanation:
Unlike an Arduino, the GPIO pins on a Raspberry Pi are not labeled. If you are going to be connecting things to the GPIO pins, it’s a good idea to get a hold of a GPIO template, such as the Raspberry Leaf (Adafruit 2196), that fits over the GPIO pins allowing you to identify them easily.
Most of the pins on a Raspberry Pi can be used as GPIO, but some have second functions:
If you have an older Raspberry Pi (before the model B+) it will only have 26 pins on the GPIO connector. These are the same as the top 26 pins (above the dashed line) of the 40-pin layout of newer Raspberry Pis shown in Figure 10-7.
For an introduction to Arduino see Recipe 10.1 and for Raspberry Pi see Recipe 10.3.
Many of the recipes in Chapters 11, 12, 13, and 14 use GPIO pins.
Use the pinMode function to set the pin to be an output and then use digitalWrite to turn the pin on and off. The following example program will make digital pin 13 (attached to the Arduino’s built-in LED) blink on and off:
constintledPin=13;voidsetup(){pinMode(ledPin,OUTPUT);}voidloop(){digitalWrite(ledPin,HIGH);// turn the LED ondelay(1000);// wait for a seconddigitalWrite(ledPin,LOW);// turn the LED offdelay(1000);// wait for a second}
The code for this sketch is available as part of the book downloads (Recipe 10.2). The sketch is called blink.
The program (or “sketch” as they are known in the Arduino world) starts by defining a constant for the pin connected to the LED called ledPin, which is given the value 13. If you change your mind and decide to make another pin blink, you only need to change 13 to that pin number in one place in the code.
The setup function is run just once after the Arduino is reset. The pinMode function then specifies that ledPin is to be an OUTPUT. It is perfectly possible to change a pin’s mode while the sketch is running. You can find a good example of this with Charlieplexing (see Recipe 14.6).
The loop function will be run repeatedly over and over again, and each time it is run, it will first set ledPin (pin 13) high, wait a second (1000 milliseconds) then set it low, then wait another second, and so on.
For digital outputs on a Raspberry Pi, see Recipe 10.9 and for digital inputs on an Arduino see Recipe 10.10.
For the current-handling capabilities of an Arduino digital output, see Recipe 10.7.
Use the RPi.GPIO library (included in Raspbian) with Python. The following example program will make GPIO pin 18 turn on and off once a second:
importRPi.GPIOasGPIOimporttimeGPIO.setmode(GPIO.BCM)led_pin=18GPIO.setup(led_pin,GPIO.OUT)try:whileTrue:GPIO.output(led_pin,True)# LED ontime.sleep(1)# delay 1 secondGPIO.output(led_pin,False)# LED offtime.sleep(1)# delay 1 secondfinally:("Cleaning up")GPIO.cleanup()
The code for this program is available as part of the book downloads (see Recipe 10.4). The file is called blink.py.
Unlike the Arduino, the Raspberry Pi does not have any user-controllable LEDs built in so to see this program in action see Recipe 14.1.
The code starts by importing the GPIO and time libraries. It then sets the GPIO pin identification mode to be BCM (Broadcom). This is a hangover from the early days of Raspberry Pi when two ways of identifying the pins were almost equally used. However, for historical reasons, you still need to include this line at the top of all your Python programs. Some internet and book resources still exist that use the pin positions on the connector rather than the pins’ name. If you find such a resource, it will tell you to use a pin mode of BOARD instead of BCM.
The variable led_pin refers to the GPIO pin to be blinked and the pin set to be an output.
The main program loop is contained inside a try/finally block. This is not strictly speaking essential and the program will run just fine without it, but by calling GPIO.cleanup() whenever the program exits, all the GPIO pins are put back into a safe input state so that accidental shorts of the pins will not cause any damage.
Inside the while loop, the pin is first turned on, then there is a delay of a second, then it is turned off, etc. The sleep function takes a time in seconds as a parameter that can also be less than a second using a decimal notation. For example, to delay for half a second you would use time.sleep(0.5).
The Arduino equivalent to this program can be found in Recipe 10.8.
For digital inputs on a Raspberry Pi, see Recipe 10.11.
Use the Arduino C digitalRead function. To see the result of the read, use the Arduino Serial Monitor. The following sketch illustrates this:
constintinputPin=7;voidsetup(){pinMode(inputPin,INPUT);Serial.begin(9600);}voidloop(){intreading=digitalRead(inputPin);Serial.println(reading);delay(500);}
You can find this sketch in the downloads for the book (see Recipe 10.2). It is called ch_10_digital_input.
The constant inputPin is defined as pin 7 and initialized to be an INPUT in the setup function.
The loop function first assigns the value resulting from carrying out a digitalRead on inputPin to the variable reading and then sends this value over the Arduino’s USB interface to the Serial Monitor. Finally, a delay of 500 milliseconds is added to slow things down to a manageable rate.
To open the Serial Monitor (Figure 10-8), click the rightmost icon on the Arduino IDE’s toolbar. This looks like a magnifying glass.
You should see a steady stream of numbers appear as shown in Figure 10-8. These should be predominantly 0s, but there may be occasional 1s. Try attaching a male-to-male jumper wire or short length of solid core wire to pin 7 of the Arduino (Figure 10-9). You should find that you get a selection of 1s and 0s. This is because you are acting as an antenna and the digital input is picking up electromagnetic noise (most likely “hum”). The digital input is “floating” and since it has a very high input impedance, it is very sensitive to noise.
Next, try attaching the floating end of the lead to one of the GND connections on the Arduino as shown in Figure 10-10. You should see that the output in the Serial Monitor is all 0s.
Finally, move the end of the wire that goes to GND to 5V and the Serial Monitor output should now be all 1s.
The Arduino Serial Monitor is one of the few ways to see what is going on inside your Arduino and is often used to see what’s going wrong in a sketch.
For digital inputs on a Raspberry Pi, see Recipe 10.11.
Use the RPi.GPIO library. The following example program reads GPIO23 every half second and prints out the result:
importRPi.GPIOasGPIOimporttimeGPIO.setmode(GPIO.BCM)input_pin=23GPIO.setup(input_pin,GPIO.IN)try:whileTrue:reading=GPIO.input(input_pin)(reading)time.sleep(0.5)finally:("Cleaning up")GPIO.cleanup()
The code for this program is available as part of the book downloads (see Recipe 10.4). The file is called ch_10_digital_input.py.
When you run the preceding program, you will see mostly 0s in the terminal:
$ sudo python ch_10_digital_input.py 0 0 0 0 0 0 0
With both this program and Recipe 10.10 you can connect a switch to the digital input (Recipe 12.1) or use a female-to-female jumper wire to connect GPIO23 to either GND or 3.3V.
For digital inputs on the Arduino, see Recipe 10.10.
Use the Arduino analogRead function and one of the Arduino pins A0 to A5 that can be used as analog inputs. The following example sketch writes the analog reading as a voltage to the Serial Monitor every half a second:
voidsetup(){pinMode(inputPin,INPUT);Serial.begin(9600);}constintinputPinA0;voidloop(){intreading=analogRead(inputPin);floatvolts=reading/204.6;Serial.println(volts);delay(500);}
You can find this sketch, which is called ch_10_analog_input, with the downloads (Recipe 10.2).
The sketch defines the inputPin as A0. When referring to one of the A0 to A5 pins on an Arduino, you have to use the letter and the number (A and 0), whereas for the other pins you just use the number.
The analogRead function returns a number between 0 and 1023, where 0 means 0V and 1023 means 5V. This number is converted to a voltage by dividing it by 204.6 (1023 / 5). Note that the analog range can be changed by connecting the Arduino AREF (analog reference) pin to a different voltage.
When you open the Serial Monitor you will see a series of values displayed. As with the digital inputs of Recipe 10.10 the analog input is floating and so the numbers (voltage on A0) will probably fluctuate something like this:
2.42 2.36 2.27 2.13 1.99 1.86 1.74 1.62 1.40 0.70
Try the experiments in Recipe 10.11 and put a wire into A0. Touching the end of the wire with your fingers so that you act as a radio antenna should make the analog readings even more wild. Connecting A0 to the 5V connector of the Arduino should display a voltage reading of 5.00 on the Serial Monitor and GND will give you 0.00; connecting A0 to the 3.3V socket on the Arduino should give you a reading of around 3.30.
If the maximum voltage you want to measure is below 5V, then you can use the Arduino AREF pin to keep the 0–1023 range of readings but for a smaller voltage range and thus achieve higher precision.
For example, if you tie the AREF pin to the 3.3V pin on the Arduino you will get a full range of readings over the 3.3V range. The voltage at AREF needs to be stable and regulated or your readings will be inaccurate.
The Raspberry Pi does not have analog inputs, but you can use an ADC IC (Recipe 12.4).
Use the analogWrite function of the Arduino on one of the PWM-capable pins.
The following example sketch will set the brightness of an LED wired to pin 11. The brightness is set by sending a number between 0 and 255 from the Arduino Serial Monitor to the Arduino board. For the curious, 255 is 1 less than 2 to the power of 8.
constintoutputPin=11;voidsetup(){pinMode(outputPin,OUTPUT);Serial.begin(9600);Serial.println("Enter brightness 0 to 255");}voidloop(){if(Serial.available()){intbrightness=Serial.parseInt();if(brightness>=0&&brightness<=255){analogWrite(outputPin,brightness);Serial.println("Changed.");}else{Serial.println("0 to 255");}}}
You can find this sketch, which is called ch_10_analog_output, with the downloads for the book (Recipe 10.2).
In addition to illustrating PWM output from a GPIO pin, this example sketch also illustrates how you can send data from your computer to the Arduino via the Serial Monitor.
The setup function sets outputPin to be an OUTPUT and then starts serial communication. Finally, the setup function sends a message to the Serial Monitor instructing you how to use the sketch by sending a number between 0 and 255.
Inside the loop function, the call to Serial.available() tests to see if anything has been sent from the Serial Monitor, and if it has, it is converted into an int and assigned to the variable brightness. The analogWrite command is then used to set the output of outputPin.
To see this sketch in operation, you will first need to follow Recipe 14.1 and attach an LED to pin 11.
Open the Arduino IDE’s Serial Monitor (see Recipe 10.10) and then try some different values between 0 and 255 to see how the brightness changes (Figure 10-11).
If, when you type a value into the Serial Monitor and click Send, the LED changes brightness momentarily, but then turns off, the Line ending drop-down list at the bottom of the Serial Monitor (see Figure 10-11) is probably not set to “No line ending.”
What is happening is that the number is being sent and works, but then the line ending arrives as another message and is interpreted as being 0, turning the LED off again.
Not all the pins on an Arduino can be used for PWM like this. In fact, only the pins on the Arduino Uno marker with a ~ can. On an Arduino Uno, that’s pins 3, 5, 6, 9, 10, and 11. Other Arduino models have different sets of pins that are PWM-capable, but you will need to refer to the Arduino documentation to know which ones.
For the Raspberry Pi version of this recipe, see Recipe 10.14.
Use the PWM feature of the RPi.GPIO library to control the output power of a GPIO pin. The following Python example program illustrates this:
importRPi.GPIOasGPIOled_pin=18GPIO.setmode(GPIO.BCM)GPIO.setup(led_pin,GPIO.OUT)pwm_led=GPIO.PWM(led_pin,500)pwm_led.start(100)try:whileTrue:duty_s=raw_input("Enter Brightness (0 to 100):")duty=int(duty_s)pwm_led.ChangeDutyCycle(duty)finally:("Cleaning up")GPIO.cleanup()
You can find this program in the downloads for the book (see Recipe 10.4). If you are using Python 3 rather than Python 2, change the command raw_input to just input.
To see this program in action, you will need to attach an LED to GPIO pin 18 (see Recipe 14.1).
The RPi.GPIO library is a little more complex to use than its Arduino counterpart. After defining the pin as an output, you then have to create a PWM channel using the line:
pwm_led = GPIO.PWM(led_pin, 500)
The number 500 is the frequency of the PWM pulses in Hz. This PWM channel is then started using the following line:
pwm_led.start(100)
Here, the value of 100 is the initial duty cycle (percentage of time the pin is high) of the PWM signal (in this case, 100% of the time).
The rest of the script interacts with the user requesting a value of the duty cycle between 0 and 100. Run the program and try different versions of brightness as shown here:
$ sudo python led_brightness.py Enter Brightness (0 to 100):0 Enter Brightness (0 to 100):20 Enter Brightness (0 to 100):10 Enter Brightness (0 to 100):5 Enter Brightness (0 to 100):1 Enter Brightness (0 to 100):90
When you want to exit the program, press CTRL-C.
The Raspberry Pi does not use a real-time operating system. That is, at any one time, there are many differnt processes running. So if you are trying to generate pulses of an exact length such as with PWM, you will find that you get a certain amount of jitter in the LED brightness as the pulse generation is interrupted.
For the Arduino counterpart to this recipe, see Recipe 10.13.
You want to enable the I2C bus on your Raspberry Pi to connect I2C peripherals to it such as the displays used in Recipe 14.9 and Recipe 14.10.
In the latest versions of Raspbian, enabling I2C (and for that matter SPI—Recipe 10.16) is simply a matter of using the Raspberry Pi configuration tool that you will find on the main menu under Preferences (Figure 10-13). Just check the box for I2C and click OK. You will be prompted to restart.
On older versions of Raspbian, the raspi-config tool does the same job.
Start raspi-config using the following command:
$ sudo raspi-config
Then select Advanced from the menu and scroll down to I2C (Figure 10-14).
When you are asked “Would you like the ARM I2C interface to be enabled?” say “Yes.” You will also be asked if you want the I2C module to load at startup, to which you should also say “Yes.”
I2C is a commonly used standard for connecting devices together. It uses two data pins SDA (data) and SCL (clock) to transfer data bidirectionally between devices. Usually one of the devices on the bus is a microcontroller or in this case, the SoC of the Raspberry Pi. Multiple devices can be connected to the same I2C bus pins, so, for example, you could have both a display and a sensor connected to the same two bus pins, each device having its own unique address.
To use I2C devices from Python, install the Python I2C library by using the commands:
$ sudo apt-get update $ sudo apt-get install python-smbus
You will then need to reboot the Raspberry Pi for the changes to take effect.
When using I2C hardware the i2c-tools software can be a great help in debugging and making sure devices are properly connected to the Raspberry Pi. This can be installed using the command:
$ sudo apt-get install i2c-tools
When you have a device attached to the I2C bus, running the i2cdetect utility will tell you if it’s connected and what I2C address it’s using, as shown in Figure 10-15.
To set up the Raspberry Pi’s SPI, see Recipe 10.16.
For recipes that connect I2C peripherals to a Raspberry Pi, see Recipe 14.9, Recipe 14.10, and Recipe 19.3.
By default, Raspbian is not configured for the Raspberry Pi’s SPI. To enable it use the Raspberry Pi configuration tool found in the main menu under Preferences (as in Recipe 10.15), or on older versions of Raspbian, use raspi-config using the command:
$ sudo raspi-config
Then select Advanced, followed by SPI, and then “Yes” before rebooting your Raspberry Pi. After the reboot, SPI will be available.
The SPI allows serial transfer of data between the Raspberry Pi and peripheral devices, such as ADCs and port expander chips, among other devices. It is similar in concept to I2C but uses four pins instead of two. As with I2C SPI data is synchronized with a clock signal (SCLK) but separate lines are used for each direction of communication: MOSI (master out slave in) and MISO (master in slave out) and a separate “Enable” pin is needed from the master for each of the devices connected to the bus. It is an older and less elegant standard than I2C but still widely used.
You may come across examples of interfacing with SPI that use an approach called bit banging, where the RPi.GPIO library is used to interface with the four GPIO pins used by the SPI.
Recipe 12.4 uses an SPI ADC converter chip.
The SPI is used in Recipe 12.4 and Recipe 19.4.
When you are connecting a 3.3V-level output to a 5V input, with very few exceptions (see discussion), no level conversion is needed—you can connect the two directly.
However, if you want to connect a 5V output to a 3.3V input, then that’s a different matter. Direct connection will wall damage the 3.3V device. If the 3.3V device is specified as having 5V-tolerant inputs, then you can just connect the two together directly. Note that the inputs of a Raspberry Pi are not 5V tolerant, so you should connect them together using a voltage divider as shown in Figure 10-16.
Occasionally you will find a 5V device that specifies that the logic level for an input should be above 3.3V. For example, WS2812 LED ICs (Recipe 14.8) theoretically need an input greater than 4V to be considered as logic high according to their datasheet. In practice, I have always found them to work without level conversion, but if you are designing a product to sell, then you would not take that chance and the kind of level shifter shown in Figure 10-17 should be used.
This circuit will actually convert levels in both directions; that is, 5V outputs will be reduced to 3.3V and 3.3V outputs increased to 5V. It makes use of the fact that MOSFETs have a “substrate” protection diode that prevents current from flowing from drain to source.
To understand how this circuit works, first consider the case where the 3.3V side is an output and the 5V side an input; that is, the level is being shifted up.
In this case, if the 3.3V GPIO is high, then the gate-source voltage will be 0V, the MOSFET will be off, and R2 will pull-up the 5V input HIGH. If the 3.3V GPIO output is low, the gate-source voltage will be 3.3V, the MOSFET will turn on, and the 5V input will be effectively connected to the LOW signal from the 3.3V side.
If we swap the direction so that the 5V side is now the output and the 3.3V side the input, then when the 5V output is HIGH the MOSFET source and gate will be at 3.3V, the MOSFET will be off, and the 3.3V input pulled up to 3.3V by R1. If the 5V output is LOW the MOSFET’s built-in protection diode will conduct, pulling the 3.3V input down to the diode’s forward voltage (about 0.6V). This turns the MOSFET on, pulling the 3.3V input fully to ground.
The simplest level conversion using just two resistors is a voltage divider as described in Recipe 2.6.
For a general background on MOSFETs see Recipe 5.3.
For an interesting discussion of the necessity of level shifting for Raspberry Pi inputs, see http://tansi.info/rp/interfacing5v.html.
If you have a lot of signals all requiring level shifting, then it makes sense to use a level-shifting IC or module such as these products from Adafruit: http://bit.ly/2lLHmuG (four signals) and http://bit.ly/2msMgku (eight signals).
Most modern electronics are concerned with switching things. Microcontrollers and any other digital logic device use transistors as switches. Taking this a step further, devices like Arduino and Raspberry Pi can switch external devices, perhaps controlling lighting or power to a heater.
The recipes in this chapter are all concerned with using transistors and other devices to switch. This includes some recipes to extend the switching power of an Arduino and Raspberry Pi.
Use a transistor in a common-emitter arrangement as a “low-side” switch with a resistor to limit the base current. Figure 11-1 shows the schematic for this circuit, that, along with Recipe 11.2, you will use time and time again in your designs.
This type of switching is called “low-side” switching because the transistor acts as a switch between the low voltage of GND and the load.
The resistor R makes sure that the current drawn from the GPIO pin does not exceed the current limit of the pin (40mA for Arduino and 16mA for Raspberry Pi; see also Recipe 10.7). It also protects the transistor from too much base current flowing. This protective role must be balanced against the limited gain of a bipolar transistor, which may only be 100 or less. So if you are planning to use the transistor to switch a current of 1A, you could reasonably expect a base current of 10mA. This means that for this 1A load, you need to choose a value of R that gives a base current somewhere between the available current of the GPIO and 10mA.
Aiming for a 10mA base current (if you are using a 5V GPIO pin and assume that the base-emitter voltage is a fairly constant 0.6V) you can calculate the value of R as:
Applying the same calculation for a 3.3V GPIO pin you get:
The two connections from this circuit to an Arduino or Raspberry Pi are the GND connection and the GPIO pin. The positive voltage supply to the load is entirely separate from the Raspberry Pi or Arduino. This means that you are not restricted to switching the logic level of the Arduino or Pi (3.3V or 5V) but can switch up to the maximum voltage that the transistor is capable of switching.
Having said that, you will often use the positive voltage supply of an Arduino or Raspberry Pi for the convenience of having a single voltage source.
For a discussion of bipolar transistors, see Recipe 5.1.
GPIO ports and their output logic are described in Recipe 10.7.
You will find an example of switching with a transistor using an Arduino in Recipe 11.6 and for a Raspberry Pi in Recipe 11.7.
For switching using a MOSFET, see Recipe 11.3.
The arrangement of Figure 11-1 is called low-side switching because the switching takes place on the lower voltage side; that is, to GND rather than from the positive supply. This means that whatever is being switched has to have a connection to the positive supply voltage.
One approach to high-side switching is to simply rearrange Figure 11-1 a little as shown in Figure 11-2.
The circuit of Figure 11-2 cannot switch voltages (+V) greater than the GPIO pin’s voltage less half a volt.
A transistor in this arrangement is called an emitter follower (Recipe 16.4) because the emitter will generally be about 0.6V less than the base. This means that we can use this arrangement for high-side switching but only so long as the voltage at the GPIO pin is less than +V.
In short, the circuit of Figure 11-2 is only useful for switch loads where one end of the load must be connected to ground and the other does not need a supply voltage that is greater than the control voltage of the GPIO pin.
If you need to switch a higher voltage (perhaps 12V) you might be tempted to consider an alternative to Figure 11-2 that uses a PNP transistor rather than an NPN transistor as shown in Figure 11-3.
This circuit is defective because Q2 will turn on with a base current when its base is about 0.6V lower than +V. So, if you were trying to switch a 12V load from 5V logic, the base voltage would always be over 0.6V and enough base current would flow to keep the transistor on whether the GPIO pin was at 5V or GND.
If you need to be able to switch voltages of V+ that are greater than the 5V of your Arduino or 3.3V of your Raspberry Pi and you don’t want to use the tristate logic trick, then you will need to use the arrangement shown in Figure 11-4.
This uses a separate NPN transistor Q1 to control the base current to Q2 giving a full switching range.
Low-side switching (Recipe 11.1) is the most common and simplest arrangement, and unless you have a good reason such as the need for one end of the load to be connected to ground, you should use low-side switching.
For a discussion of NPN and PNP bipolar transistors, see Recipe 5.1.
GPIO ports and their output logic are described in Recipe 10.7.
You will find an example of switching with a transistor using an Arduino in Recipe 11.6 and for a Raspberry Pi in Recipe 11.7.
For switching using a MOSFET, see Recipe 11.3.
You can use a MOSFET as an electronic switch. Use the transistor in a common-source arrangement. Figure 11-5 shows the schematic for this circuit. Along with Recipe 11.1, you will find yourself using this circuit a lot.
This type of switching is called “low-side” switching because the transistor acts as a switch between the low voltage of GND and the load.
If the GPIO pin is high (3.3V or 5V) and exceeds the gate-threshold voltage of the MOSFET, the MOSFET will turn on, allowing current to flow from +V through the load to GND.
When using MOSFETs as switches controlled by GPIO pins you should look for devices described as logic level. These have a low-threshold voltage (generally 2V or less), whereas MOSFETs not described as logic-level may well have gate-threshold voltages of 4V to 7V.
Logic-level versions of regular MOSFETs often have the same name, but an L after the name. For example, the FQP30N06L is the logic-level version of the FQP30N06.
Low-power MOSFETs like the 2N7000 generally have pretty low gate-threshold voltages anyway and are fine with 3.3V logic without having the L designation.
You may be wondering why the gate resistor R is needed. In reality for most MOSFETS in most relatively low-current applications, it isn’t needed at all and you can just connect the GPIO pin directly to the gate.
However, the MOSFET’s gate appears to the GPIO pin as a capacitor that will be charged and discharged as the GPIO pin goes high and low. So, if you are switching the MOSFET at high speed (say PWM at a high frequency) or the MOSFETs’ gate capacitance is high (it increases with load current) then the maximum rated output current of the GPIO pin may be exceeded and the transistors inside the GPIO output could overheat. In any case, resistors are cheap and it’s good practice to include one.
In Figure 11-5 the gate of the MOSFET is floating. If it is connected to a GPIO set to be an output, then the MOSFET will be in a stable state, but there are several reasons why this might not be the case:
To prevent this unwanted behavior, you can just add a pull-down resistor to keep the gate low unless the GPIO pin is actively driving the gate (see Figure 11-6). This resistor should have a resistance of perhaps 10 times that of the gate-protection resistor (R1) to prevent the effective voltage divider (Recipe 2.6) formed by R1 and R2 from reducing the gate voltage by any significant amount.
For a discussion of MOSFETs, see Recipe 5.3.
GPIO ports and their output logic are described in Recipe 10.7.
You will find an example of switching with a MOSFET using an Arduino in Recipe 11.6 and for a Raspberry Pi in Recipe 11.7.
For switching using a BJT, see Recipe 11.1.
The problems with high-side switching using a MOSFET are similar to those of Recipe 11.2. However, whereas in Recipe 11.2 it was okay to use an emitter-follower configuration or PNP transistor on its own, the need for a gate-source voltage above the threshold voltage to turn the MOSFET on means that the switchable range is reduced by at least the threshold voltage, making the circuit unsuitable for most applications.
So, for high-side switching there is little alternative to using the circuit of Figure 11-7.
By using a BJT rather than a MOSFET for Q1, there will always be enough leakage current through Q1 to keep the gate of Q2 low when the control pin is left floating.
For a discussion of MOSFETs, see Recipe 5.3.
GPIO ports and their output logic are described in Recipe 10.7.
You will find an example of switching with a MOSFET using an Arduino in Recipe 11.6 and for a Raspberry Pi in Recipe 11.7.
Use Table 11-1 to help you decide which NPN BJT or N-Channel MOSFET to use in low-side switching.
| Technology | Examples | |
|---|---|---|
| under 100mA | BJT or MOSFET | 2N3904 or 2N7000 |
| under 200mA | MOSFET | 2N7000 |
| under 500mA | Darlington or MOSFET | MPSA14 or FQP30N06L |
| under 3A | Darlington or MOSFET | TIP120 or FQP30N06L |
| under 20A | MOSFET | FQP30N06L |
While any of these transistors would technically work, over time you’ll find that you return to a few of your favorite transistors.
When it comes to switching small loads (say under 100mA) a small BJT (like the 2N3904) and a small MOSFET (like the 2N7000) are pretty much interchangeable. In fact, their pinouts mean that they are in the same transistor package and are pin-compatible.
Above 100mA but below 200mA I would usually select a 2N7000 because its low on-resistance means that it will not get as hot as a BJT.
Between 200mA and 500mA, I would either use a Darlington MPSA14 to save space over a FQP30N06L MOSFET (in a larger package), but only if I could afford the 1.5V or more voltage drop of the MPSA14.
Between 500mA and 3A you are definitely in large-transistor territory in a TO-220 package. If you can afford the voltage drop of a Darlington then the TIP120 is a good choice; otherwise, a FQP30N06L will serve you well.
For powers over 3A use a FQP30N06L with a heatsink.
See also Recipe 5.5.
2N3904 datasheet: https://www.sparkfun.com/datasheets/Components/2N3904.pdf
2N7000 datasheet: https://www.fairchildsemi.com/datasheets/2N/2N7000.pdf
MPSA14 datasheet: http://www.farnell.com/datasheets/43685.pdf
FQP30N06L datasheet: https://www.fairchildsemi.com/datasheets/FQ/FQP30N06L.pdf
TIP120 datasheet: https://www.fairchildsemi.com/datasheets/TI/TIP122.pdf
If you have a 5V Arduino like the Arduino Uno, then each GPIO pin can switch a maximum of 5V at 40mA. To increase either the voltage or the current, you need to use a transistor. The principles and even the breadboard layouts are much the same whether you use a BJT or a MOSFET. See Recipe 11.5 for the relative merits of each technology.
Figure 11-8 shows the schematic for this.
This circuit is for low-voltage DC only. Do not try and use it to switch AC. To do so would not work and would also be very dangerous.
You can build this circuit on a breadboard to experiment. Figure 11-9 shows the breadboard layout for the project using a 2N7000, which is good for 200mA (2.4W). If you prefer, you could use a 2N3904 or an MPSA14 with exactly the same breadboard layout.
If you have a higher-power LED lamp, you should use a FQP30N06L as shown in Figure 11-10. Again, you could if you prefer use a TIP120.
The Arduino test program for this project is listed here and is available in the book downloads (see Recipe 10.2) where the sketch is called ch_11_on_off:
constintoutputPin=11;voidsetup(){pinMode(outputPin,OUTPUT);Serial.begin(9600);Serial.println("Enter 0 for off and 1 for on");}voidloop(){if(Serial.available()){charonOff=Serial.read();if(onOff=='1'){digitalWrite(outputPin,HIGH);Serial.println("Output ON.");}elseif(onOff=='0'){digitalWrite(outputPin,LOW);Serial.println("Output OFF.");}}}
This sketch follows a similar pattern to that of Recipe 10.13. Pin 11 is set to be an output and when a single-command character “1” or “0” is sent from the Serial Monitor (Figure 11-11) digitalWrite is used to turn pin 11 on or off.
You can see the circuit in action in Figure 11-12, where a 12V SLA battery is used to power the lamp.
Although intended as a demonstration circuit, this recipe is actually quite powerful, allowing you to control the lamp from your computer.
For information on getting started with breadboard, see Recipe 20.1.
For transistor pinouts, see Appendix A.
The basics of an Arduino Uno are described in Recipe 10.1.
To use this same design with Raspberry Pi, see Recipe 11.7.
The circuits used in Recipe 11.6 will also work just fine if you wire the control connection and GND to a Raspberry Pi rather than an Arduino. Figure 11-13 shows the breadboard layout for using a 2N7000 MOSFET with a Raspberry Pi to switch a 12V LED lamp module.
To control the lamp, you can use the following program, which is called ch_11_on_off.py and can be found with the downloads for the book (see Recipe 10.4):
importRPi.GPIOasGPIOGPIO.setmode(GPIO.BCM)led_pin=18GPIO.setup(led_pin,GPIO.OUT)try:whileTrue:answer=input("1 for on 0 for off: ")ifanswer==1:GPIO.output(led_pin,True)# LED onelifanswer==0:GPIO.output(led_pin,False)# LED offfinally:("Cleaning up")GPIO.cleanup()
When you run the program you should see this in the terminal session:
$ sudo python ch_11_on_off.py 1 for on 0 for off: 1 1 for on 0 for off: 0
When you enter 1, the lamp should light (pressing 0 will turn it off again).
As with Recipe 11.6 you can also use other transistors than the 2N7000 or FQP20N06L MOSFETs.
For information on getting started with breadboards, see Recipe 20.1.
For transistor pinouts, see Appendix A.
The basics of a Raspbery Pi are described in Recipe 10.3.
To use this same design with an Arduino, see Recipe 11.6.
Use transistors in the half-bridge configuration shown in Figure 11-14.
This circuit combines elements of Recipe 11.3 and Recipe 11.4 and relies on their being three power lines: +V, –V, and GND in the middle. Thus, the three power lines might be +6V, –6V, and 0V.
The control signals A and B turn on Q2 and Q3, respectively. If A and B are both low with respect to –V no current will flow through the load. If A is high, Q2 will conduct and current will flow through Q2 to the load and then to GND. Conversely, if A is low and B is high, Q3 will conduct and current will flow from GND through the load to –V.
Under no circumstances should A and B both be high, since if both Q2 and Q3 are conducting there will effectively be a short-circuit between +V and –V and a damagingly large current will flow. In fact, if you are connecting A and B to GPIO pins and using software to set them high or low, you should put a small delay in between settings to allow A and B to be high at the same time. For example, to change from A high, B low to A low, B high, you should follow these steps:
The half-bridge and its relative the full-bridge are often used to control DC motors, where their ability to reverse the direction of the flow of current allows them to reverse the direction in which the motor rotates.
Although it is perfectly possible to build half-bridge circuits from discrete components, it is more common to use an IC. You will meet several of these in Chapter 13.
For a full-bridge circuit, see Recipe 13.3.
For the FQP27P06 P-Channel MOSFET’s datasheet, see https://www.sparkfun.com/datasheets/Components/General/FQP27P06.pdf.
Use a low-power BJT or MOSFET to switch the power to the relay’s coil as shown in Figure 11-15.
A typical relay coil will need about 50mA to activate the relay contacts, which is slightly too much to use an Arduino pin directly and far too much for a Raspberry Pi GPIO pin. A relay with a nominal 5V coil will generally work with a little over 4V if you use a BJT, but supplying the full 5V by way of a MOSFET is generally better. So a good choice for Q1 would be a 2N7000. R is not at all critical, but 1kΩ would be fine.
The diode D1 is called a “freewheeling” or “flyback” diode and provides a discharge path for high voltages generated as the relay coil is switched off, which protects Q1.
Building a design like this on a breadboard can be a little tricky, as most common relay packages don’t have pins that will fit into the breadboard, so you may have to solder short extension wires to the relay coil or use a prototyping setup like the MonkMakes Protoboard that has a place to solder a relay. Figure 11-16 shows the breadboard layout for using a relay with an Arduino and Figure 11-17 for a Raspberry Pi.
To test out the relay on an Arduino and Raspberry Pi, you can use the programs described in Recipe 11.6 and Recipe 11.7, respectively.
Although it can be tempting to try to get away with connecting the relay coil directly to a GPIO pin, this may damage the Arduino or Pi and is most certainly operating outside of the specifications for the Arduino, Raspberry Pi, or relay and cannot be guaranteed to work correctly.
For information on relays see Recipe 6.4.
SSRs are generally opto-isolated, which means that controlling them is as simple as using an LED. In fact, it’s usually easier because in an SSR a series resistor is generally included. Figure 11-18 shows an SSR module connected to a Raspberry Pi. The SSR’s negative input terminal is connected to GND and the positive terminal to a GPIO pin.
Do not use an SSR to control AC unless you are sure you can wire things up safely and you know exactly what you are doing.
Under no circumstances should you work on a live/hot system while you are prototyping, and always use an RCD-protected AC outlet.
See also Recipe 21.12.
To test out the relay on an Arduino and Raspberry Pi, you can use the programs described in Recipe 11.6 and Recipe 11.7, respectively.
A safe and easy way to control AC using an SSR is to use a PowerSwitch Tail.
As the name suggests, a circuit that has an open-collector output uses an NPN BJT as an output stage (Figure 11-19) with the implication that the emitter is connected to GND, with no internal connections to the collector except to the output.
At first glance this may seem strange, and a common mistake is to treat an open-collector output as a logic output and connect it straight to a GPIO pin. Unless the internal pull-up resistor on the GPIO pin (Recipe 10.7) is enabled, this will not work.
Leaving the collector floating like this has the advantage that by simply using a resistor from the collector to a positive supply, the output voltage of the open collector can be set to match that of the GPIO input you are connecting it to. Figure 11-20 shows how an open-collector output can be used with 3.3V logic (left) and 5V logic (right).
The value of R1 is not critical and needs to lie somewhere in the large range of not exceeding the transistor’s collector current limit and not being succeptable to electrical noise. So, anything between 1kΩ and 1MΩ is fine. Common resistor values for this are 1kΩ and 10kΩ.
If your GPIO pin has the ability to enable an internal pull-up resistor you can use this instead of an external resistor.
If the circuit or module you are using specifies the current rating of the open-collector output, you can use it to directly drive a load (e.g., a relay). The load should be in place of the resistor between the output and a positive voltage supply.
The MOSFET equivalent of an open-collector output is the open-drain output (see Figure 11-21). This can be used in exactly the same way as its BJT equivalent. In fact, it’s not uncommon to find device outputs labeled as open collector that actually use a MOSFET.
This chapter looks at sensors that convert some physical measurement such as temperature, light, or physical movement into an analog or digital electronic signal.
Many different sensors are explained, and where appropriate, ways of using them with an Arduino or Raspberry Pi are included.
Connect the switch between GND and a GPIO pin set to be a digital input as shown in Figure 12-1 and enable the GPIO pin’s internal pull-up resistor.
Your software will probably also need to “debounce” the signal from the switch.
Here is an Arduino sketch that writes a message to the Serial Monitor whenever the switch is pressed. You can find this sketch (ch_12_switch) with the downloads for the book (see Recipe 7.2):
constintinputPin=12;voidsetup(){pinMode(inputPin,INPUT_PULLUP);Serial.begin(9600);}voidloop(){if(digitalRead(inputPin)==LOW){Serial.println("Button Pressed!");while(digitalRead(inputPin)==LOW){};delay(10);}}
The internal pull-up resistor is turned on by specifying INPUT_PULLUP in the pinMode function.
Inside the loop the inputPin is continually read until it is pressed (becomes LOW). At this point, a message is displayed in the Serial Monitor and the while loop ensures there are no further triggerings until the switch has been released. The debouncing is achieved by the 10-millisecond delay that is triggered after each button press is detected. This gives the switch contacts time to settle before they are tested again.
You can try out the example by poking the pins of a tactile push switch between GND and pin 12 on the Arduino as shown in Figure 12-3.
The equivalent code for a Raspberry Pi is listed here (ch_12_switch.py):
importRPi.GPIOasGPIOimporttimeGPIO.setmode(GPIO.BCM)input_pin=23GPIO.setup(input_pin,GPIO.IN,pull_up_down=GPIO.PUD_UP)try:try:whileTrue:ifGPIO.input(input_pin)==False:("Button Pressed!")whileGPIO.input(input_pin)==False:time.sleep(0.01)finally:("Cleaning up")GPIO.cleanup()
The logic of this program follows exactly the same pattern as for the Arduino.
Having male GPIO pins on a Raspberry Pi makes it a little more difficult to attach a switch. One way to attach the switch is to use a microswitch pushed into a pair of female-to-female jumper wires (Figure 12-4) or use a Squid Button (Figure 12-5).
If you plan to use a number of push switches, then whether or not you are using a Squid Button, you can use the Squid library to simplify the process of debouncing. Download and install the Squid library from https://github.com/simonmonk/squid where you will also find installation instructions. Once installed, the test program can be simplified to the following example (ch_12_switch_squid.py):
frombuttonimport*b=Button(23)whileTrue:ifb.is_pressed():("Button Pressed!")
Microswitches (Figure 12-6) are push switches that are not designed to be directly pressed by a person, but rather have a lever attached and are used to sense physical movement such as when a linear actuator has reached its end position or as a safety interlock to make sure a microwave door is closed.
The microswitch is an SPDT device generally with closed, normally open, and common terminals (see Recipe 6.2).
Although switch using an Arduino or Raspberry Pi generally uses a pull-up resistor and switches to ground, you can also switch to the positive supply.
To switch to the positive supply on an Arduino, you have to use an external pull-down resistor to prevent the input from floating because the Arduino does not have internal pull-down resistors on its GPIO pins (pin mode INPUT).
On the other hand, the Raspberry Pi does have internal pull-down resistors that can be enabled for a particular pin using the command:
GPIO.setup(input_pin,GPIO.IN,pull_up_down=GPIO.PUD_DOWN)
For information on the Squid Button, see https://www.monkmakes.com/squid_combo/.
Digital inputs are also described in Recipe 10.10 and Recipe 10.11.
GPIO pins are described in Recipe 10.7.
You’ll want a type of rotary encoder called a quadrature encoder, which behaves like a pair of switches (Figure 12-7). The sequence in which they open and close as the rotary encoder’s shaft is turned determines the direction of rotation.
A basic rotary encoder will have three pins. One for A, one for B, and a common pin. The rotary encoder shown in Figure 12-7 has two extra pins that are used for a push switch that is activated when the knob is pushed rather than turned.
When using a rotary encoder with a microcontroller or SBC, the common contact is connected to GND and the switch contacts connected to digital inputs with pull-up resistors enabled.
The following Arduino sketch, which is called ch_12_quadrature, can be found with the downloads for the book (Recipe 10.12). The sketch assumes that the two switch pins are connected to pins 6 and 7:
constintaPin=6;constintbPin=7;intx=0;voidsetup(){pinMode(aPin,INPUT_PULLUP);pinMode(bPin,INPUT_PULLUP);Serial.begin(9600);}voidloop(){intchange=getEncoderTurn();if(change!=0){x+=change;Serial.println(x);}}intgetEncoderTurn(){// return -1, 0, or +1staticintoldA=0;staticintoldB=0;intresult=0;intnewA=digitalRead(aPin);intnewB=digitalRead(bPin);if(newA!=oldA||newB!=oldB){// something has changedif(oldA==0&&newA==1){result=(oldB*2-1);}elseif(oldB==0&&newB==1){result=-(oldA*2-1);}}oldA=newA;oldB=newB;returnresult;}
To avoid skipping turns, the function getEncoderTurn must be called as frequently as possible in loop.
getEncoderTurn compares the current state of the A and B switches with their states last time getEncoderTurn was called to infer whether the knob is being turned clockwise or counterclockwise, returning a value of 1 or –1, respectively. If there is no change to the values of A and B then 0 is returned.
You can find the Raspberry Pi version of the rotary encoder program in the file ch_12_quadrature.py (see Recipe 10.4) and here:
importRPi.GPIOasGPIOimporttimeGPIO.setmode(GPIO.BCM)input_A=18input_B=23GPIO.setup(input_A,GPIO.IN,pull_up_down=GPIO.PUD_UP)GPIO.setup(input_B,GPIO.IN,pull_up_down=GPIO.PUD_UP)old_a=1old_b=1defget_encoder_turn():# return -1, 0, or +1globalold_a,old_bresult=0new_a=GPIO.input(input_A)new_b=GPIO.input(input_B)ifnew_a!=old_aornew_b!=old_b:ifold_a==0andnew_a==1:result=(old_b*2-1)elifold_b==0andnew_b==1:result=-(old_a*2-1)old_a,old_b=new_a,new_btime.sleep(0.001)returnresultx=0whileTrue:change=get_encoder_turn()ifchange!=0:x=x+change(x)
The test program counts up as you turn the rotary encoder clockwise, and counts down when you rotate it counterclockwise:
pi@raspberrypi ~ $ sudo python rotary_encoder.py 1 2 3 4 5 6 7 8 9 10 9 8 7 6 5 4
Both the Arduino and Raspberry Pi versions of the software work in just the same way.
Figure 12-8 shows the sequence of pulses that you will get from the two contacts, A and B. You can see that the pattern repeats itself after four steps (hence the name quadrature encoder).
When rotating clockwise (left to right in Figure 12-8), the sequence will be:
| Phase | A | B |
|---|---|---|
|
1 |
0 |
0 |
|
2 |
0 |
1 |
|
3 |
1 |
1 |
|
4 |
1 |
0 |
When rotating in the opposite direction, the sequence of phases will be reversed:
| Phase | A | B |
|---|---|---|
|
4 |
1 |
0 |
|
3 |
1 |
1 |
|
2 |
0 |
1 |
|
1 |
0 |
0 |
The Python program listed previously implements the algorithm for determining the rotation direction in the function get_encoder_turn. The function will return 0 (if there has been no movement), 1 for a rotation clockwise, or -1 for a rotation counterclockwise. It uses two global variables, old_a and old_b, to store the previous states of the switches A and B. By comparing them with the newly read values, it can determine (using a bit of clever logic) which direction the encoder is turning.
The sleep period of 1 millisecond is used to ensure that the next new sample does not occur too soon after the previous sample; otherwise, the transitions can give false readings (see “Contact Bounce”).
The test program should work reliably no matter how fast you twiddle the knob on the rotary encoder; however, try to avoid doing anything time consuming in the loop, or you may find that turn steps are missed.
To use a pot to sense rotation, use Recipe 12.3.
Put the resistive element in a voltage divider with a fixed-value resistor to convert the resistance measurement into a voltage as shown in Figure 12-9.
The Raspberry Pi does not have analog inputs, so to use resistive sensors with a Raspberry Pi, you either need to add analog inputs to your Raspberry Pi (see Recipe 12.4) or use the step-response method (see Recipe 12.5).
When it comes to choosing the value of a fixed resistor, the aim should be to try and maximize the range of output voltages that will be presented to the analog input. With an Arduino Uno’s analog input range of 0 to 5V you ideally want an analog input voltage of 0 to 5V. Because a voltage divider “divides” the input voltage, you are never going to get the full voltage range as an output unless you use a higher input voltage. This introduces the potential for overvoltage at the analog input and so generally it is better to accept a slightly narrowed range rather than risk damaging your board.
Let’s take as an example a photoresistor that has a minimum resistance of 1kΩ under bright light and a resistance that rises to 1MΩ in total darkness. Assuming that you are using a 5V Arduino:
If we pick a value for the fixed resistor R2 of about 10 times of the minimum value of the photoresistor R1 then R2 would have a value of 10kΩ, so at maximum brightness:
For a resistance of 10k for the photoresistor, the Vout would be 2.5V and when the photoresistor is in complete darkness (1MΩ), the Vout would fall to 0.05V.
This would give pretty good coverage of the whole range of the photoresistor’s readings.
The following Arduino sketch assumes that R1 is a photoresistor with 1kΩ light resistance and R2 is a fixed 10kΩ resistor. The sketch calculates the resistance of R1 and displays it in the Arduino IDE’s Serial Monitor every half-second. You can find the sketch here and with the downloads for the book (see Recipe 10.2). It is called ch_12_r_adc.
constintinputPin=A0;constfloatr2=1000.0;constfloatvin=5.0;voidsetup(){pinMode(inputPin,INPUT);Serial.begin(9600);}voidloop(){intreading=analogRead(inputPin);floatvout=reading/204.6;floatr1=(r2*(vin-vout))/vout;Serial.(r1);Serial.println(" Ohms");delay(500);}
For an introduction to photoresistors, see Recipe 2.8.
For Arduino code to display such analog readings, see Recipe 10.12.
For information on voltage dividers, see Recipe 2.6.
To add analog inputs to a Raspberry Pi, see Recipe 12.4.
The Raspberry Pi does not have analog inputs so connect an ADC IC to the Raspberry Pi.
Use the MCP3008 8-channel ADC chip. This chip actually has eight analog inputs, so you can connect up to eight sensors to one of these and interface to the chip using the Raspberry Pi SPI. Figure 12-10 shows the schematic for using an MCP3008 with a Raspberry Pi.
Note that these analog inputs have a maximum input voltage of 3.3V. You will also need to make sure the SPI of the Raspberry Pi is enabled and the py-spidev Python library (included in new releases of Raspbian) is installed (Recipe 10.16).
You can find the Raspberry Pi program to access and display the analog readings from analog channel 0 in the program ch_12_mcp3008.py (see Recipe 10.4):
importspidev,timespi=spidev.SpiDev()spi.open(0,0)defanalog_read(channel):r=spi.xfer2([1,(8+channel)<<4,0])adc_out=((r[1]&3)<<8)+r[2]returnadc_outwhileTrue:reading=analog_read(0)voltage=reading*3.3/1024("Reading=%d\tVoltage=%f"%(reading,voltage))time.sleep(1)
You can use this recipe with Recipe 12.7, Recipe 12.9, and Recipe 12.10 to read analog sensors with a Raspberry Pi.
You can use resistive sensors with a Raspberry Pi directly, without the need for an ADC IC (see Recipe 12.5).
See how long it takes for a capacitor to charge the resistive sensor and use this time to calculate the resistance of the sensor.
Figure 12-11 shows the schematic for measuring resistance using nothing more than two resistors and a capacitor.
A Python library to simply read values of resistance can be downloaded from GitHub where you will also find installation instructions and documentation.
The following example shows how you can use this library to measure the value of the sensor resistance when the schematic of Figure 12-11 is wired up to a Raspberry Pi with pin A connected to GPIO 18 and pin B to GPIO 23. The program is located in the examples folder of the pi_analog library and is called resistance_meter.py:
fromPiAnalogimport*importtimep=PiAnalog()whileTrue:(p.read_resistance())time.sleep(1)
To test out the method, try using a few different values of fixed resistance. You can also use different values of C1 and R1 by specifying the value of capacitance in µF and R1 in Ω in the constructor. For example, for high resistance values you might want to use a smaller capacitor (10nF) to speed up the conversion. You could use the following code:
fromPiAnalogimport*importtimep=PiAnalog(0.01,1000)whileTrue:(p.read_resistance())time.sleep(1)
This technique relies on the ability of GPIO pins to switch between being an input and an output while the controlling program is running.
The basic steps for taking a measurement are as follows:
The Monk Makes Electronics Starter Kit for Raspberry Pi has several projects that use this step-response method to measure temperature and light.
If you have an Arduino or board with analog inputs then use Recipe 12.3. If your board does not have analog inputs (say a Raspberry Pi) then use Recipe 12.4 or Recipe 12.5.
All the preceding methods will work just fine for determining if the sensor is illuminated more brightly in one reading than in another, but obtaining a measurement in common units of light measurement is a lot trickier. Questions that make getting the light measurement difficult are:
Even if you answer these questions, you get into problems with the linearity of the photoresistor and will likely need to manually calibrate your meter to account for manufacturing differences in the photoresistors.
In other words, despite its apparrant simplicity making a light meter that will give you a reading in Lux or Watts per square meter is a specialist task.
For a discussion on light measurement, see https://en.wikipedia.org/wiki/Lux.
Use a thermistor in a voltage-divider arrangement (see Recipe 12.3), calculate the resistance, and then use the Steinhart–Hart equation to calculate the temperature.
Figure 12-12 shows the schematic for connecting a thermistor to an Arduino analog input. You should use an NTC thermistor, which has a specified nominal resistance (its resistance at 25° C) and a value of B (sometimes called beta) that determines its resistance characteristics.
You can calculate the resistance of the thermistor R1 using the voltage-divider formula (see Recipe 2.6):
This can be rearranged to:
With a 5V Arduino and a fixed 1k resistor for R2, this gives:
The Steinhart–Hart equation states that:
where:
If you plug all this math into an Arduino sketch and wire up a thermistor as shown in Figure 12-12, you end up with the following code, which can also be found with the downloads for the book in the sketch ch_12_thermistor:
constintinputPin=A0;// r2 is the bottom fixed resistor in the voltage dividerconstfloatr2=1000.0;// thermistor propertiesconstfloatB=3800.0;constfloatr0=1000.0;// other constantsconstfloatvin=5.0;constfloatt0k=273.15;constfloatt0=t0k+25;voidsetup(){pinMode(inputPin,INPUT);Serial.begin(9600);}voidloop(){intreading=analogRead(inputPin);floatvout=reading/204.6;floatr=(r2*(vin-vout))/vout;floatinv_t=1.0/t0+(1.0/B)*log(r/r0);floatt=(1.0/inv_t)-t0k;Serial.(t);Serial.println(" deg C");delay(500);}
To measure temperature using a thermistor, the step-response method, and a thermistor, see Recipe 12.8.
You can find an example of using an analog temperature-sensing IC in Recipe 12.10 and a digital device in Recipe 12.11.
Use a thermistor and the pi-analog library as described in Recipe 12.5. Figure 12-13 shows the schematic for connecting a thermistor to a Raspberry Pi.
The thermistor should be an NTC device. This just means that as the temperature gets hotter the resistance gets lower. You will need to know its nominal resistance (at 25 C) and its value of B.
The pi-analog library has a program for reading the temperature in degrees C that you will find in the examples folder for the library called thermometer.py. The code for this is listed here:
fromPiAnalogimport*importtimep=PiAnalog()whileTrue:(p.read_temp_c(3800,1000))time.sleep(1)
The two parameters to read_temp_c are the thermistor’s value of B and resistance, which should be changed to suit your thermistor.
To use a thermistor with analog inputs, see Recipe 12.7.
For more information on thermistors, see https://en.wikipedia.org/wiki/Thermistor.
You can find an example of using an analog temperature-sensing IC in Recipe 12.10.
Use the pot as a potential divider, with the slider attached to an analog input as shown in Figure 12-14.
The voltage at the slider will vary from 0V to the supply voltage as you rotate the pot’s knob. You can use the same test program as Recipe 12.3 to measure the position.
Although a Raspberry Pi does not have analog inputs, you can still use this technique with a Raspberry Pi if you add an ADC chip as described in Recipe 12.4.
For devices without an analog input, you can use the step-response method to measure the resistance between one end of the pot and the slider as shown in Figure 12-15.
The resistance between the slider and the end of the pot will vary from 0Ω to the maximum resistance of the pot as you rotate the pot’s knob. You can use the test program from Recipe 12.5 to measure the resistance of the pot and hence the rotary position.
The voltage-divider approach will produce more consistent results than the step-response method.
For more on pots, see Recipe 2.3.
You can use a quadrature encoder (Recipe 12.2) to measure rotary movement.
For background on voltage dividers, see Recipe 2.6.
Use a temperature-sensing IC such as the TMP36 or LM35. Figure 12-16 shows how you would connect such a device to the analog input of an Arduino. If you want to use such a sensor with a Raspberry Pi, you need to add analog inputs as described in Recipe 12.4. The TMP36 can operate from 3.3V or 5V.
Note that only the SMD version of this IC has the extra SHUTDOWN pin. This can be connected to a digital output of, say, an Arduino to reduce the current consumption of the IC to 100nA when the pin is set to LOW.
C1 should be placed as close to the IC as possible.
The temperature of a TMP36 in degrees C (let’s call it t) is related to the voltage by the following formula:
where v is the output voltage of the TMP36. So, if the output voltage is 0V, the temperature is –50° C; if it is 1V, the temperature is 50° C.
Figure 12-17 shows the breadboard layout for connecting the three-pin through-hole version of the TMP36, connected to an Arduino.
The Arduino sketch ch_12_tmp36 illustrates the use of this device. You can find this sketch here and with the downloads for the book (see Recipe 10.2):
constintinputPin=A0;constfloatsensitivity=0.01;// V/deg Cconstfloatoffset=-50.0;// deg Cvoidsetup(){pinMode(inputPin,INPUT);Serial.begin(9600);}voidloop(){intreading=analogRead(inputPin);floatvolts=reading/204.6;floatdegC=(volts/sensitivity)+offset;// float degF = degC * 9.0 / 5.0 + 32.0;Serial.println(degC);delay(500);}
The two constants sensitivity and offset allow you to use the sketch with other temperature sensors in the TMP36 family of ICs that have different sensitivity and temperature ranges.
The TMP36 is not a very accurate device. The datasheet says ±2° C, which is fairly typical in practice and probably with similar accuracy as a thermistor (although the math is a lot easier). For greater accuracy, you should look at a digital sensor like the DS18B20 (see Recipe 12.11).
For the TMP36 datasheet, see http://bit.ly/2mbtFsg.
To measure temperature using a thermistor and an analog input, see Recipe 12.7.
You don’t have to have a microcontroller or SBC to make use of a sensor like this. For simple thermostatic applications, you can use a comparator IC (see Recipe 17.10).
Use a digital temperature measurement IC like the DS18B20, which is factory calibrated to provide an accuracy of ±0.5° C.
This IC uses a 1-wire interface bus that allows up to 255 of the ICs to be connected to just one GPIO port. Figure 12-18 shows a schematic diagram for connecting a DS18B20s to an Arduino. The IC will work just as well with the 3.3V supply of a Raspberry Pi, although in the case of the Pi, GPIO pin 4 must be used as this pin is earmarked for use by the 1-wire interface.
The 4.7kΩ external pull-up resistor is necessary for the 1-wire bus to operate reliably.
Having connected the DS18B20 as shown in Figure 12-18, you will need to download the OneWire library and the DallasTemperature library. In both cases choose the Download ZIP option from the GitHub page and then add the ZIP library to your Arduino IDE from the Sketch→Include Library→Add ZIP Library menu option.
The following sketch illustrates the use of a single DS18B20, reporting the temperature to the Serial Monitor every half-second. You can find the sketch here and with the downloads for the book; it is called ch_12_ds18b20:
#include <OneWire.h>#include <DallasTemperature.h>constinttempPin=2;OneWireoneWire(tempPin);DallasTemperaturesensors(&oneWire);voidsetup(){Serial.begin(9600);sensors.begin();}voidloop(){sensors.requestTemperatures();floattemp=sensors.getTempCByIndex(0);Serial.println(temp);}
Because you can attach multiple sensors to a single GPIO pin, the getTempCByIndex function takes the number of the sensor that you wish to use (starting at 0). If you have multiple sensors you will have to use trial and error to identify which is which.
Raspbian has support for the 1-wire interface used by the DS18B20 but you have to enable it by editing the file /boot/config.txt and adding the following line to the end of the file. Then reboot your Raspberry Pi for the change to take effect.
dtoverlay=w1-gpio
The program for this is called ch_12_ds18b20.py and can be found with the downloads for the book (see Recipe 10.4):
importglob,timebase_dir='/sys/bus/w1/devices/'device_folder=glob.glob(base_dir+'28*')[0]device_file=device_folder+'/w1_slave'defread_temp_raw():f=open(device_file,'r')lines=f.readlines()f.close()returnlinesdefread_temp():lines=read_temp_raw()whilelines[0].strip()[-3:]!='YES':time.sleep(0.2)lines=read_temp_raw()equals_pos=lines[1].find('t=')ifequals_pos!=-1:temp_string=lines[1][equals_pos+2:]temp_c=float(temp_string)/1000.0returntemp_cwhileTrue:(read_temp())time.sleep(1)
As with the Arduino version of this program, the sensor to be read is accessed by position in the line:
device_folder = glob.glob(base_dir + '28*')[0]
The interface to the DS18B20 uses a file-like structure. The file interface will always be in the folder /sys/bus/w1/devices/ and the name of the file path will start with 28, but the rest of the file path will be different for each sensor.
The code assumes that there will only be one sensor, and finds the first folder starting with 28. To use multiple sensors, use different index values inside the square brackets.
Within that folder will be a file called w1_slave, which is opened and read to find the temperature.
The sensor actually returns strings of text like this:
81 01 4b 46 7f ff 0f 10 71 : crc=71 YES 81 01 4b 46 7f ff 0f 10 71 t=24062
The code extracts the temperature part of this message. This appears after t= and is the temperature in one-thousandths of a degree Celsius.
The read_temp function calculates the temperature in degrees Celsius and returns it.
If you want to attach multiple sensors (up to 255) you can wire them up as shown in Figure 12-19. Only the one pull-up resistor is needed, and because the sensor is digital and at a low data transmission rate, you can attach sensors to long leads with no effect on the accuracy of the reading.
If you would rather have just two wires running to your DS18B20, you can use the device’s special parasitic power feature. In essence, it harvests energy from the data line, storing it temporarily in capacitors inside the IC. In parctical terms, the 3-wire method will allow you to use longer wires to your sensor and will be more reliable, but see the IC’s datasheet if you wish to use this mode.
If you plan to deploy your sensor somewhere wet, use encapsulated DS18B20 sensors that are enclosed in a waterproof case that can be found on eBay.
The DS18B20 datasheet can be found here: http://bit.ly/2mTPyuu
To measure temperature with a thermistor, see Recipe 12.7 and Recipe 12.8.
To measure temperature with the TMP36 analog temperature-sensing IC, see Recipe 12.10.
Use a DHT11 humidity and temperature sensor, which has a serial output that does not really conform to any bus standard like 1-wire, I2C, or SPI. However, libraries for both Arduino and Raspberry Pi are available for it.
Figure 12-20 shows how it should be connected to an Arduino. When used with a Raspberry Pi, the pin labeled VDD (voltage drain drain) should be connected to 3.3V and the DATA pin to GPIO 4.
When connecting to a Raspberry Pi, use the 3.3V power connector not the 5V one and connect the data pin of the DHT11 to GPIO4.
The Arduino sketch can be found with the downloads for the book (Recipe 10.2) and is called ch_12_dht11. The sketch requires the Arduino SimpleDHT library to be installed. You can do this from the Arduino Library Manager by using the option Sketch→Include Library→Manage Libraries, searching for SimpleDHT, and then clicking the Install button next to the library.
#include <SimpleDHT.h>constintpinDHT11=2;SimpleDHT11dht11;voidsetup(){Serial.begin(9600);}voidloop(){bytetemp;bytehumidity;dht11.read(pinDHT11,&temp,&humidity,NULL);Serial.(temp);Serial.(" C, ");Serial.(humidity);Serial.println(" %");delay(1000);}
The call to dht11.read is a little unusual because it passes the variables temp and humidity with an & in front of them to indicate that they can be changed within the read function. In this way, after the read function has finished executing, temp and humidity will have updated values.
The Raspberry Pi code for this sensor requires an Adafruit library to be installed using the following commands:
$ git clone https://github.com/adafruit/Adafruit_Python_DHT.git $ cd Adafruit_Python_DHT $ sudo python setup.py install
The program itself can be found with the downloads for the book (Recipe 10.4) and is called ch_12_dht11.py:
importtime,Adafruit_DHTsensor_pin=4sensor_type=Adafruit_DHT.DHT11whileTrue:humidity,temp=Adafruit_DHT.read_retry(sensor_type,sensor_pin)(str(temp)+" C "+str(humidity)+" %")time.sleep(1)
The DHT11 is the cheapest and most common series of similar sensors with different accuracies. For better quality results use the DHT22.
Other recipes for measuring temperature are Recipe 12.7, Recipe 12.8, Recipe 12.10, and Recipe 12.11.
For distances between 4 inches (10cm) and 6 feet (2m) use an HC-SR04 ultrasonic rangefinder module.
Figure 12-21 shows how the rangefinder is connected to an Arduino. Interfacing to it requires one pin of the Arduino to act as a digital output (connected to TRIG) and one as a digital input (connected to ECHO).
The TRIG pin causes the HC-SR04 to emit a pulse of ultrasound at 40kHz and the ECHO pin goes high when the reflected sound wave is received. The time taken for this to happen is an indication of the distance from the sensor to the object.
To connect the rangefinder to a Raspberry Pi, the output voltage of the ECHO pin of the rangefinder needs to be reduced to 3.3V. This can be done with a simple level converter using a pair of resistors as a voltage divider. The schematic for this is shown in Figure 12-22.
For more information on level conversion, see Recipe 10.17.
An Arduino sketch (ch_12_rangefinder) for rangefinding can be found with the downloads for the book (see Recipe 10.2):
constinttrigPin=9;constintechoPin=10;voidsetup(){pinMode(trigPin,OUTPUT);pinMode(echoPin,INPUT);Serial.begin(9600);}voidloop(){floatcm=takeSounding();Serial.(int(cm));Serial.(" cm ");intinches=int(cm/2.5);Serial.(inches);Serial.println(" inches");delay(500);}floattakeSounding(){digitalWrite(trigPin,HIGH);delayMicroseconds(10);// 10us trigger pulsedigitalWrite(trigPin,LOW);delayMicroseconds(200);// ingore echos while sending 200uslongduration=pulseIn(echoPin,HIGH,100000)+200;floatdistance=duration/29.0/2.0;returndistance;}
All the action takes place in the takeSounding function. First, a 10µs pulse is sent to the TRIG pin of the rangefinder resulting in a burst of eight cycles of 40kHz ultrasound. The 200µs delay allows time for this burst to complete before measuring the time taken until an echo is received.
The distance is calculated using the speed of sound (29cm/µs.) The value is divided by 2 because the time taken is for both the outward and return journey of the sound signal.
The Raspberry Pi program can be found in the file ch_12_rangefinder.py with the downloads for the book (see Recipe 10.4):
importRPi.GPIOasGPIOimporttimetrigger_pin=18echo_pin=23# USE LEVEL CONVERTER 5V->3.3VGPIO.setmode(GPIO.BCM)GPIO.setup(trigger_pin,GPIO.OUT)GPIO.setup(echo_pin,GPIO.IN)deftime_to_echo(timeout):t0=time.time()whileGPIO.input(echo_pin)==Falseandtime.time()<(t0+timeout):passt0=time.time()whileGPIO.input(echo_pin)==Trueandtime.time()<(t0+timeout):passreturntime.time()-t0defget_distance():GPIO.output(trigger_pin,True)time.sleep(0.00001)# 10usGPIO.output(trigger_pin,False)time.sleep(0.0002)# 200uspulse_len=time_to_echo(1)distance_cm=pulse_len/0.000058distance_in=distance_cm/2.5return(distance_cm,distance_in)whileTrue:("cm=%f\tinches=%f"%get_distance())time.sleep(1)
The HC-SR04 rangefinders are not particularly accurate, especially when used with a Raspberry Pi, where the operating system will sometimes increase the timing readings for the echo.
Another unwanted influence on the readings comes from variations in the speed of sound. This changes a little both with temperature and humidity.
The datasheet for the HC-SR04 module can be found here: http://bit.ly/2mTOPtn.
This chapter looks at various types of motors and how both their speed and direction can be controlled. This involves the electronics of controlling fairly high load currents as well as the software needed. This chapter will cover examples for Arduino and Raspberry Pi.
When people talk of motors, what tends to spring to mind are the small DC motors that you might find in a battery-powered toy car. DC motors are common and often combined with a gearbox to reduce their high speed of rotation into a single unit called a gearmotor.
Stepper motors operate on a different principle and are found in printers of all sorts including 3D printers as they can be advanced in small steps (typically 1/200 of a revolution or more).
Servomotors fit a different niche, allowing accurate positioning of their “arm” in a restricted range of angles (about 180°). Servomotors are often found controlling the steering of a remote-control car or the control surfaces of a remote-control plane or helicopter.
All of these types of motors are available in various sizes to meet the power requirements of different applications. Whatever the size, controlling such motors follows the same basic principles.
Use a transistor switch, but add a snubbing diode as shown in Figure 13-1. This is based on Recipe 11.1, which is fine for a small DC motor. For higher currents use a power MOSFET as described in Recipe 11.3.
The diode D1 prevents the transistor from being damaged. A “snubbing” diode like this should always be used to protect a switching transistor from excessive reverse voltage that occurs when the inductive load of the motor releases stored energy as a pulse of voltage in the opposite polarity to that in which it was driven. This reverse voltage is called “back-emf.”
It is not usually necessary to use a snubbing diode with a power MOSFET, because these devices have built-in diodes to prevent damage from electrostatic discharge, which will also protect against voltage spikes. They are (at least for relatively modest motors) sufficient to protect the transistor. However, adding a diode as you would with a BJT is the safest thing to do.
If you want to wire up the circuit of Figure 13-1, you can use the test programs in Recipe 11.6 and Recipe 11.7 to control a motor from an Arduino or Raspberry Pi.
Many of the techniques described in Chapter 11 can be used to switch a motor.
To control the speed of a motor, see Recipe 13.2.
Using a transistor switch and PWM to adjust the speed of the motor, measure the motor’s speed using an optical detector and slotted wheel attached to the shaft of the motor.
You can use the schematic in Figure 13-2 and pulse the GPIO control pin with PWM as described in Recipe 10.13 and Recipe 10.14.
Using PWM to control a motor actually controls the power supplied to the motor rather than its speed, but assuming the motor’s load remains constant, these amount to the same thing.
Measuring the motor speed requires a sensor that does not interfere with the rotation of the motor. One way to do this is to use an optical sensor like the prebuilt model shown in Figure 13-2 along with a laser-cut disk that has slots in it. As the disk rotates it alternately blocks and allows light to pass, resulting in a series of pulses that can be used to determine both the speed of the motor and the number of rotations it has made.
The optical sensor includes a built-in comparator and has an “open collector” (Recipe 11.11) output that requires a 1kΩ pull-up resistor to 5V. These sensors are readily available from eBay for a few dollars.
The motor-control circuit uses a MOSFET in the circuit described in Recipe 11.3.
The sketch ch_13_motor_speed_feedback (see Recipe 10.2) reports the speed of the motor in RPM (revolutions per minute) once every second in the Serial Monitor. It also allows you to send a PWM value of 0 to 255 to control the speed of the motor.
Make sure that the Line endings drop-down list of the Serial Monitor is set to “No line ending.”
constintoutputPin=11;constintsensePin=2;constintslotsPerRev=20;constlongupdatePeriod=1000L;// mslonglastUpdateTime=0;longpulseCount=0;floatrpm=0;voidsetup(){pinMode(outputPin,OUTPUT);Serial.begin(9600);Serial.println("Enter speed 0 to 255");attachInterrupt(digitalPinToInterrupt(sensePin),incPulseCount,RISING);}voidloop(){if(Serial.available()){intsetSpeed=Serial.parseInt();analogWrite(outputPin,setSpeed);}updateRPM();}voidincPulseCount(){pulseCount++;}voidupdateRPM(){longnow=millis();if(now>lastUpdateTime+updatePeriod){lastUpdateTime=now;rpm=float(pulseCount)*60000.0/(20.0*updatePeriod);pulseCount=0;Serial.println(rpm);}}
An interrupt is used so that every time the sensePin goes from LOW to HIGH the function incPulseCount is called that increments the value of pulseCount.
The function updateRPM will use pulseCount to calculate the RPM once per second before resetting pulseCount to 0.
To just turn a motor on and off, see Recipe 13.1, and to control the direction of a DC motor, see Recipe 13.3.
Use an H-bridge circuit that consists of two push-pull drivers. To keep the number of components low, this is normally accomplished using an H-bridge IC. Figure 13-3 shows the schematic for using the popular L293D motor controller with an Arduino to control two DC motors independently.
The L293D has separate voltage supplies for the ICs logic (VCC1) and the motor (VCC2). This allows the motor to operate at a different voltage than the logic and also reduces the problem of electrical noise caused by the motor disrupting the logic.
Speed control of the motors is accomplished by using a PWM signal to drive the 1,2EN and 3,4EN pins that enable the push-pull drivers in pairs. The direction of one motor is controlled by the L293D pins 1A and 2A and the second motor by 3A and 4A. Table 13-1 shows the four possible states of motor drive for the control pins 1A and 2A.
| 1A | 2A | Motor M1 |
|---|---|---|
| LOW | LOW | Off |
| LOW | HIGH | Clockwise |
| HIGH | LOW | Counter-clockwise |
| HIGH | HIGH | Fast-stop |
To control the motors, three Arduino pins are needed for each motor. One to control the speed and two for the A and B control pins for the direction that are connected to the 1A and 2A control pins for one motor and the 3A and 4A pins of the L293 for the other.
constintmotor1SpeedPin=5;constintmotor2SpeedPin=6;constintmotor1DirAPin=2;constintmotor1DirBPin=3;constintmotor2DirAPin=4;constintmotor2DirBPin=7;voidsetup(){pinMode(motor1SpeedPin,OUTPUT);pinMode(motor2SpeedPin,OUTPUT);pinMode(motor1DirAPin,OUTPUT);pinMode(motor1DirBPin,OUTPUT);pinMode(motor2DirAPin,OUTPUT);pinMode(motor2DirBPin,OUTPUT);Serial.begin(9600);// M1 full speed clockwiseanalogWrite(motor1SpeedPin,255);digitalWrite(motor1DirAPin,LOW);digitalWrite(motor1DirBPin,HIGH);// M2 half speed counter-clockwiseanalogWrite(motor2SpeedPin,127);digitalWrite(motor2DirAPin,HIGH);digitalWrite(motor2DirBPin,LOW);}voidloop(){}
The code sets all the control pins to be outputs and then sets one motor to go at full speed in one direction and the other at half speed in the other. Try experimenting with this code to make the motors behave differently.
The 3.3V digital outputs of a Raspberry Pi will work just fine connected to the L293D, but the logic supply to the L293D must be 4.5V or more, so the 5V pin of the Raspberry Pi GPIO connector should be used. Table 13-2 shows the connections between Raspberry Pi and L293D.
| Raspberry Pi GPIO Pin | L293D Pin Name | L293 Pin Number(s) | Function |
|---|---|---|---|
| 5V | VCC1 | 16 | Logic supply |
| GND | GND | 12 | Ground |
| GPIO18 | 1,2EN | 1 | M1 speed |
| GPIO23 | 3,4EN | 9 | M2 speed |
| GPIO24 | 1A | 2 | M1 direction A |
| GPIO17 | 2A | 7 | M1 direction B |
| GPIO27 | 3A | 10 | M2 direction A |
| GPIO22 | 4A | 15 | M2 direction B |
The following Python programs (ch_13_l293d.py) will set M1 to operate at full speed in one direction and M2 at half-speed in the other direction:
importRPi.GPIOasGPIOGPIO.setmode(GPIO.BCM)# Define pinsmotor_1_speed_pin=18motor_2_speed_pin=23motor_1_dir_A_pin=24motor_1_dir_B_pin=17motor_2_dir_A_pin=27motor_2_dir_B_pin=22# Set pin modesGPIO.setup(motor_1_speed_pin,GPIO.OUT)GPIO.setup(motor_2_speed_pin,GPIO.OUT)GPIO.setup(motor_1_dir_A_pin,GPIO.OUT)GPIO.setup(motor_1_dir_B_pin,GPIO.OUT)GPIO.setup(motor_2_dir_A_pin,GPIO.OUT)GPIO.setup(motor_2_dir_B_pin,GPIO.OUT)# Start PWMmotor_1_pwm=GPIO.PWM(motor_1_speed_pin,500)motor_1_pwm.start(0)motor_2_pwm=GPIO.PWM(motor_2_speed_pin,500)motor_2_pwm.start(0)# Set one motor to full speedmotor_1_pwm.ChangeDutyCycle(100)GPIO.output(motor_1_dir_A_pin,False)GPIO.output(motor_1_dir_B_pin,True)# Second motor to half speedmotor_2_pwm.ChangeDutyCycle(50)GPIO.output(motor_2_dir_A_pin,True)GPIO.output(motor_2_dir_B_pin,False)input("Enter '0' to stop ")("Cleaning up")GPIO.cleanup()
The code follows the same pattern as its Arduino counterpart. First, the pins are set to be outputs and then two PWM channels are defined to control the motor speeds. Finally, one motor is set to full speed in one direction and the other to half-speed in the other direction.
The function GPIO.cleanup() sets all the pins to be inputs just before the program exits to stop both motors.
Figure 13-4 shows a “schematic” for what is going on with an H-bridge driver. Don’t try and build this schematic; if you do, prepare for the possibility of destroying some of the transistors if Q1 and Q2 or Q3 and Q4 are turned on at the same time. Also, this circuit will only stand a chance of working if the motor voltage is almost the same as the logic voltage of the control pins (see Recipe 11.4).
The idea of the circuit is that the control pin A makes Q1 conduct if it is LOW and Q2 conduct if it is HIGH. Similarly control pin B makes Q3 conduct if it is low and Q4 conduct if pin B is HIGH.
By setting A and B, you can control the direction of flow of current through the motor according to Table 13-1.
For more information on push-pull (half-bridge) drivers, see Recipe 11.8.
A servomotor offers the solution to this problem. Wire the servomotor up as shown in Figure 13-5.
Generally servomotors will use a separate power supply from the supply used by the Arduino or Raspberry Pi, as the large load current as the motor starts may well drop the supply voltage enough to reset the controlling device. However, for a small lightly loaded servomotor, you may get away with using the same supply for both.
The resistor R1 is there to protect the GPIO pin, but is not strictly necessary as most servomotors draw very little current from the control pin. But if you do not have the datasheet for the servo you are using then R1 is a sensible precaution.
Figure 13-6 shows a small 9g hobby servo. The connector to the servo is fairly standardized, but you should also check the servomotor’s datasheet.
The red lead is the positive supply to the motor, the brown lead the ground connection, and the orange lead the control signal.
The control signal will normally be fine with a 3.3V logic, but if the datasheet for the servomotor indicates that this needs to be higher, use a level converter (Recipe 10.17).
The following example code (ch_13_servo) in the downloads for the book (see Recipe 10.2) assumes that the control pin of a servo is connected to pin 9 of an Arduino Uno.
When you open the Arduino Serial Monitor you will be prompted to enter an angle for the servoarm:
#include <Servo.h>constintservoPin=9;Servoservo;voidsetup(){voidsetup(){servo.attach(servoPin);servo.write(90);Serial.begin(9600);Serial.println("Angle in degrees");}voidloop(){if(Serial.available()){intangle=Serial.parseInt();servo.write(angle);}}
Make sure that you have Line endings drop-down on the Serial Monitor set to “No line ending.”
The servo.write method of the servo library sets the servo arm to an angle in degrees between 0 and 180.
The Raspberry Pi equivalent of the Arduino sketch is ch_13_servo.py in the book downloads (see Recipe 10.4):
importRPi.GPIOasGPIOimporttimeservo_pin=18# Tweak these values to get full range of servo movementdeg_0_pulse=0.5# msdeg_180_pulse=2.5# msf=50.0#50Hz = 20ms between pulses# Do some calculations on the pulse width parametersperiod=1000/f# 20msk=100/period# duty 0..100 over 20msdeg_0_duty=deg_0_pulse*kpulse_range=deg_180_pulse-deg_0_pulseduty_range=pulse_range*kGPIO.setmode(GPIO.BCM)GPIO.setup(servo_pin,GPIO.OUT)pwm=GPIO.PWM(servo_pin,f)pwm.start(0)defset_angle(angle):duty=deg_0_duty+(angle/180.0)*duty_rangepwm.ChangeDutyCycle(duty)try:whileTrue:angle=input("Angle (0 to 180): ")set_angle(angle)finally:("Cleaning up")GPIO.cleanup()
The set_angle function makes use of the variables deg_0_duty and duty_range, which are calculated once at the start of the program to calculate the duty cycle that will generate a pulse of the right length for the specified angle.
Servomotors rarely have exactly the same range of movement, so this program and its Arduino equivalent are a great way to find the range of angles that your servomotor can reach.
Figure 13-7 shows how the pulses arriving at a servomotor’s control pin alter the angle of the servomotor’s arm.
The servomotor expects a pulse every 20ms to maintain its position. The length of that pulse determines the position of the servomotor’s arm, which can normally travel through about 180°. A short pulse of between 0.5 and 1ms will position the arm at one end of its travel. A pulse of 1.5ms will position the servomotor’s arm in the center position and a long pulse of up to 2.5ms at its furthest travel.
If you have a lot of servomotors to connect to an Arduino or a Raspberry Pi, then it can help to use a servomotor interface board such as the ServoSix board (Figure 13-8).
Using the Python GPIO library to generate the pulses can result in some jitter in the movement of the servoarm. This is due to inaccuracies of the pulse timing as Raspbian tries to do several things at once.
This can be improved by using the ServoBlaster service that configures certain GPIO pins exclusively for servo use or the ServoSix library that is built on ServoBlaster, but it just configures the pins for servo use while the controlling program is running.
Another alternative is to devolve the control of the servos entirely to hardware such as the Adafruit 16-channel servoboard, which is then sent control messages from the Raspberry Pi.
For more information on the ServoBlaster Python library for Raspberry Pi, see https://github.com/richardghirst/PiBits/tree/master/ServoBlaster.
You can find the ServoSix library at https://github.com/simonmonk/servosix and the ServoSix connection board at https://www.monkmakes.com/servosix/.
To use the Adafruit servo interface board, see https://www.adafruit.com/product/815.
A bipolar stepper motor can do what you need. Use a dual H-bridge IC such as the L293D used in Recipe 13.3 to drive the two coils of a bipolar stepper motor. Figure 13-9 shows the schematic diagram for this using an Arduino Uno and Figure 13-10 shows the diagram for a Raspberry Pi.
A push-pull driver is needed for each of the two coils of the stepper motor. The enable pins of the L293D are both tied to a single GPIO pin. Generally the enable pins will be permanently enabled, although they could be used with a high-frequency PWM signal if the stepper motor voltage is below the power-supply voltage.
You can find an Arduino sketch called ch_13_bi_stepper in the downloads for the book (Recipe 10.2):
#include <Stepper.h>constintin1Pin=2;constintin2Pin=3;constintin3Pin=4;constintin4Pin=7;constintenablePin=5;Steppermotor(200,in1Pin,in2Pin,in3Pin,in4Pin);voidsetup(){pinMode(in1Pin,OUTPUT);pinMode(in2Pin,OUTPUT);pinMode(in3Pin,OUTPUT);pinMode(in4Pin,OUTPUT);pinMode(enablePin,OUTPUT);digitalWrite(enablePin,HIGH);Serial.begin(9600);Serial.println("Command letter followed by number");Serial.println("p20 - set the motor speed to 20");Serial.println("f100 - forward 100 steps");Serial.println("r100 - reverse 100 steps");motor.setSpeed(20);}voidloop(){if(Serial.available()){charcommand=Serial.read();intparam=Serial.parseInt();if(command=='p'){motor.setSpeed(param);}elseif(command=='f'){motor.step(param);}elseif(command=='r'){motor.step(-param);}}}
The sketch uses the Stepper library that is included with the Arduino IDE. The library requires you to specify the number of steps as the first parameter in the following line:
Steppermotor(200,in1Pin,in2Pin,in3Pin,in4Pin);
To try out the program, open the Serial Monitor and send commands such as f100, where f is the direction (forward or reverse) and 100 is the number of steps.
The Raspberry Pi software for driving a bipolar stepper motor can be found in the file ch_13_bi_stepper.py. To download the code for the book see Recipe 10.4.
importRPi.GPIOasGPIOimporttimeGPIO.setmode(GPIO.BCM)in_1_pin=18in_2_pin=23in_3_pin=24in_4_pin=25en_pin=22GPIO.setup(in_1_pin,GPIO.OUT)GPIO.setup(in_2_pin,GPIO.OUT)GPIO.setup(in_3_pin,GPIO.OUT)GPIO.setup(in_4_pin,GPIO.OUT)GPIO.setup(en_pin,GPIO.OUT)GPIO.output(en_pin,True)period=0.02defstep_forward(steps,period):foriinrange(0,steps):set_coils(1,0,0,1)time.sleep(period)set_coils(1,0,1,0)time.sleep(period)set_coils(0,1,1,0)time.sleep(period)set_coils(0,1,0,1)time.sleep(period)defstep_reverse(steps,period):foriinrange(0,steps):set_coils(0,1,0,1)time.sleep(period)set_coils(0,1,1,0)time.sleep(period)set_coils(1,0,1,0)time.sleep(period)set_coils(1,0,0,1)time.sleep(period)defset_coils(in1,in2,in3,in4):GPIO.output(in_1_pin,in1)GPIO.output(in_2_pin,in2)GPIO.output(in_3_pin,in3)GPIO.output(in_4_pin,in4)try:('Command letter followed by number');('p20 - set the inter-step period to 20ms (control speed)');('f100 - forward 100 steps');('r100 - reverse 100 steps');whileTrue:command=input('Enter command: ')parameter_str=command[1:]# from char 1 to endparameter=int(parameter_str)ifcommand[0]=='p':period=parameter/1000.0elifcommand[0]=='f':step_forward(parameter,period)elifcommand[0]=='r':step_reverse(parameter,period)finally:('Cleaning up')GPIO.cleanup()
This code does not use a library, but directly sets the outputs of the push-pull drivers to activate the coils in the right sequence to move the motor forward or backward for the specified number of steps.
The preceding code is written for Python 3. If you are running the program as Python 2, then you will need to change the line:
command = input('Enter command: ')
to:
command = raw_input('Enter command: ')
The Python programs in this book are designed to work with Python 2 or Python 3, but the input/raw_input issue is one source of incompatibility between the Python versions that is difficult to code around.
Unlike servomotors, stepper motors can rotate continuously—they just do it one step at a time. Typically a stepper motor will have a few tens to a few hundred steps to one full rotation. Moving the stepper motor from one step position to the next involves activating its two coils in a certain pattern.
The L293D lends itself well to experimenting with stepper motors on a breadboard. Figure 13-11 shows an Arduino wired up from the schematic of Figure 13-9. Note that the GND connections are connected inside the chip, so not all ground connections in the schematic need to be made.
The stepper motor used to test out the preceding examples is from Adafruit, where you will also find a datasheet for the motor).
To use unipolar stepper motors (usually 5-lead), see Recipe 13.6.
Unipolar stepper motors are a little easier to use than their bipolar relatives discussed in Recipe 13.6. They do not need a push-pull half-bridge driver, but can be controlled using a Darlington array chip like the ULN2803. Figure 13-12 shows the schematic for using this IC with an Arduino and Figure 13-13 for a Raspberry Pi.
The ULN2803 contains eight open-collector Darlington transistors, each capable of sinking about 500mA and so can be used to drive two unipolar stepper motors.
You can find an example Arduino sketch that uses the stepper library in ch_13_uni_stepper with the downloads for the book (see Figure 10-2).
#include <Stepper.h>constintin1Pin=2;constintin2Pin=3;constintin3Pin=4;constintin4Pin=7;Steppermotor(513,in1Pin,in2Pin,in3Pin,in4Pin);voidsetup(){pinMode(in1Pin,OUTPUT);pinMode(in2Pin,OUTPUT);pinMode(in3Pin,OUTPUT);pinMode(in4Pin,OUTPUT);Serial.begin(9600);Serial.println("Command letter followed by number");Serial.println("p20 - set the motor speed to 20");Serial.println("f100 - forward 100 steps");Serial.println("r100 - reverse 100 steps");motor.setSpeed(20);}voidloop(){if(Serial.available()){charcommand=Serial.read();intparam=Serial.parseInt();if(command=='p'){motor.setSpeed(param);}elseif(command=='f'){motor.step(param);}elseif(command=='r'){motor.step(-param);}}}
The sketch is pretty much the same as that of Recipe 13.5, but in this case there is no enable pin possible. See the sketch in Recipe 13.5 for a description of the code.
The Raspberry Pi version of the software can be found in the program ch_13_uni_stepper.py. It is identical to that of Recipe 13.5 but with the driver-enable feature removed:
importRPi.GPIOasGPIOimporttimeGPIO.setmode(GPIO.BCM)in_1_pin=18in_2_pin=23in_3_pin=24in_4_pin=25GPIO.setup(in_1_pin,GPIO.OUT)GPIO.setup(in_2_pin,GPIO.OUT)GPIO.setup(in_3_pin,GPIO.OUT)GPIO.setup(in_4_pin,GPIO.OUT)period=0.02defstep_forward(steps,period):foriinrange(0,steps):set_coils(1,0,0,1)time.sleep(period)set_coils(1,0,1,0)time.sleep(period)set_coils(0,1,1,0)time.sleep(period)set_coils(0,1,0,1)time.sleep(period)defstep_reverse(steps,period):foriinrange(0,steps):set_coils(0,1,0,1)time.sleep(period)set_coils(0,1,1,0)time.sleep(period)set_coils(1,0,1,0)time.sleep(period)set_coils(1,0,0,1)time.sleep(period)defset_coils(in1,in2,in3,in4):GPIO.output(in_1_pin,in1)GPIO.output(in_2_pin,in2)GPIO.output(in_3_pin,in3)GPIO.output(in_4_pin,in4)try:('Command letter followed by number');('p20 - set the inter-step period to 20ms (control speed)');('f100 - forward 100 steps');('r100 - reverse 100 steps');whileTrue:command=raw_input('Enter command: ')parameter_str=command[1:]# from char 1 to endparameter=int(parameter_str)ifcommand[0]=='p':period=parameter/1000.0elifcommand[0]=='f':step_forward(parameter,period)elifcommand[0]=='r':step_reverse(parameter,period)finally:('Cleaning up')GPIO.cleanup()
The unipolar stepper motor that I used to validate these recipes is this Adafruit model: https://www.adafruit.com/product/858.
To use bipolar stepper motors, see Recipe 13.6.
The ULN2803 datasheet can be found here: http://www.ti.com/lit/ds/symlink/uln2803a.pdf.
LEDs can be used both for illumination and as indicators. They can also be arranged as 7-segment displays or as tiny pixels in an OLED (organic LED) display.
This chapter contains recipes relating to powering and controlling LEDs as well as for using a display with an Arduino or Raspberry Pi.
Back in Recipe 4.4 you saw how an LED needs a series resistor to prevent too much current from flowing. Too much current will shorten the life of an LED, but more importantly, it may damage or destroy the Arduino or Raspberry Pi GPIO pin that is controlling the LED.
Wire up your LED to a GPIO pin as shown in Figure 14-1 and then use Table 14-1 to select a value for the series resistor.
| Infrared | Red | Orange/Yellow/Green | Blue/White | Violet | UV | |
|---|---|---|---|---|---|---|
| Vf | 1.2-1.6V | 1.6-2V | 2-2.2V | 2.5-3.7V | 2.7-4V | 3.1-4.4V |
| 3.3V GPIO 3mA | 1kΩ | 680Ω | 470Ω | 270Ω | 220Ω | 68Ω |
| 3.3V GPIO 16mA | 150Ω | 120Ω | 82Ω | 56Ω | 39Ω | 15Ω |
| 5V GPIO 20mA | 220Ω | 180Ω | 150Ω | 150Ω | 120Ω | 100Ω |
In practice, nearly all LEDs will illuminate to some degree even from 3.3V with a 1kΩ resistor limiting the current. So, as an even broader rule of thumb, if you don’t care about optimizing the brightness of your LED then a 270Ω resistor is fine.
For optimum brightness find the datasheet for your LED and use the forward-voltage Vf and maximum forward current If with the formula in Recipe 4.4 to calculate the optimum value of resistor.
If you connect an LED as shown in Figure 14-1 you can test turning it on and off using an Arduino and Raspberry Pi with Recipe 10.8 and Recipe 10.9.
A convenient thing to have around if you want to use LEDs with a Raspberry Pi is a Raspberry Squid (Figure 14-2). This has series resistors for the red, green, and blue LEDs built-in to the leads, so you can just plug it straight onto the GPIO connector of a Raspberry Pi.
For more background on LEDs, see Recipe 4.4.
To make your own Raspberry Squid, see https://github.com/simonmonk/squid.
Modify Recipe 7.7 to add a control input for the LED driver as shown in Figure 14-4.
When the GPIO pin is low, Q1 will be off and effectively takes no part in the circuit. The LM317 then acts as a constant-current source where R2 sets the current as discussed in Recipe 7.7 according to the formula:
So if you know what current you want to set, you can calculate the value of R2 using:
Since R3 is very low compared to the input impedance of the Adjust pin of the LM317, it can be ignored.
When the GPIO pin is taken above the gate-threshold voltage of Q1, Q1 will turn on, pulling the Adjust pin low and reducing the regulated voltage to 0V.
The LM317 will get hot if the DC-input voltage is significantly higher than the forward voltage of the LED. In fact, the power it will turn into heat will be:
where If is the forward voltage of the LED, Vin is the input voltage, and Vf is the forward voltage of the LED.
R2 will generally be a low-value resistor that will produce heat with a power of:
As an example, Figure 14-5 shows the circuit of Figure 14-4 supplying 120mA to a high-power LED. For this, R2 is a 10Ω 1/4W resistor. The control pin is connected to a GPIO pin of an Arduino.
You can turn the LED on and off using the sketch from Recipe 10.8 but on and off will be swapped over because a HIGH at the GPIO pin will turn the LED off.
You can also use PWM to control the LED brightness, but again, the logic is inverted, so you will need to modify the following line in ch_10_analog_output from:
int brightness = Serial.parseInt();
to be:
int brightness = 255 - Serial.parseInt();
You can use the Python program from Recipe 10.9, but as with the equivalent Arduino sketch the on/off logic will be inverted.
For brightness control, you will also need to modify the line:
duty = int(duty_s)
to be:
duty = 100 - int(duty_s)
The LM317 datasheet can be found here: http://www.ti.com/lit/ds/symlink/lm317.pdf.
Arrange columns of LEDs in series to match the supply voltage, with a current-limiting resistor for each column. The example in Figure 14-6 shows how you could power 20 LEDs with a forward voltage of 1.7V and a forward current of around 20mA from a 12V power supply.
In this case, five forward-biased LEDs in a column will drop a total of 8.5V, leaving 3.5V to be dropped across the resistor. Using Ohm’s Law, this means the resistor should have a value of 175Ω so a standard value of 180Ω would lower the current just slightly but enough.
While it’s tempting to reduce the number of resistors you need by putting more LEDs in series, this can cause practical problems of overcurrent if the stated forward voltage of the LEDs is not quite accurate. As a rule of thumb, I generally like to keep ¼ of the supply voltage for the series resistor.
The extreme version of this design is to power a long series of LEDs directly from mains voltage. It works, but frankly this is just terrifying—don’t do it.
It’s tempting to consider just putting LEDs in series to share a series resistor as shown in Figure 14-7.
The problem with doing this is that if there are slight variations in the forward voltage of each LED (which there will be) the LED with the smallest Vf will start conducting first and immediately draw ALL the current from the resistor. This may well burn out the LEDs one at a time.
For basic information on LEDs and series resistors, see Figure 14-1.
There is a nice online calculator that will do the series resistor calculations for you here: http://led.linear1.org/led.wiz.
You have a big bank of LEDs (see Recipe 14.3) and you want to switch them all on and off from an Arduino or Raspberry Pi.
Switching a big bank of LEDs is really no different from switching any sizeable load. You can use Recipe 13.3 to do this.
For programs to turn the LEDs on and off, you can use Recipe 10.8 and Recipe 10.9.
You can also use a PWM signal to control the brightness of a big bank of LEDs using the programs found in Recipe 10.13 and Recipe 10.14.
See Chapter 11 for a whole load of recipes concerned with switching loads like this.
Use multiplexing—a technique that reduces the number of GPIO pins needed to light lots of LEDs. Figure 14-8 shows how you can control a 4-digit LED display from an Arduino Uno.
Each digit of the display has seven segments in a figure-8 arrangement. Each of these segments is labeled A to G and is connected, inside the LED package, to all the segments of the same name. In this display, all the cathodes of the segments for a particular digit are connected together as a common cathode. The LED display has a pin for each of these four common cathodes so that the software can enable each digit in turn, set its segment pattern, and then move on to the next digit.
The sketch ch_14_7_seg_mux displays the numbers 1 to 4 on the display (see Figure 14-9).
The sketch can be found with the downloads for the book (see Recipe 10.2):
constintdigitPins[]={2,3,4,5};constintsegPins[]={6,7,8,9,10,11,12,13};// abcdefgDconstcharnum[]={0b11111100,// 0 abcdef0b00001100,// 1 ef0b11011010,// 2 ab de g0b10011110,// 3 a defg0b00101110,// 4 c efg0b10110110,// 5 a cd fg0b11110110,// 6 abcd fg0b00011100,// 7 def0b11111110,// 8 abcdefg0b10111110};// 9 a cdefgintdigits[]={1,2,3,4};voidsetup(){for(inti=0;i<4;i++){pinMode(digitPins[i],OUTPUT);}for(inti=0;i<8;i++){pinMode(segPins[i],OUTPUT);}}voidloop(){refreshDisplay();}voidrefreshDisplay(){for(intd=0;d<4;d++){for(intseg=0;seg<8;seg++){digitalWrite(segPins[seg],LOW);}digitalWrite(digitPins[d],HIGH);for(intseg=0;seg<8;seg++){digitalWrite(segPins[seg],bitRead(num[digits[d]],7-seg));}delay(1);digitalWrite(digitPins[d],LOW);}}
The digit and segment pins are contained in arrays. The setup function sets them all as outputs.
Two other arrays are defined: num contains the bit patterns for the numbers 0 to 9. A 1 in the bit position means the segment should be lit for that value. The array digits holds the numeric value to be displayed on each of the four positions.
Every time the refreshDisplay function is called, all four digits of the display will be displayed and then the display blanked. This means that refreshDisplay must be called as frequently as possible or the display may become flickery or dim. The function has an outer loop that loops for each digit number d between 0 and 3. Inside this loop, the segments are first turned off and then the control pin for the current digit is enabled.
An inner loop then loops for each segment (seg) and determines whether the current segment should be lit or not, based on the expression:
bitRead(num[digits[d]],7-seg)
This first finds the current digit value and then looks up the bit pattern for that value.
The critical thing about the preceding example code is that anything that you do inside the loop function along with refreshDisplay must happen quickly, or the display will start to flicker. The human eye will not see the flickering until refreshDisplay is called less frequently than 30 times a second, giving you a theoretical 30 milliseconds (approximately) to do something else in loop. This is more than enough time to check the state of digital inputs and perform other simple actions, but remember—always keep loop as fast as possible.
Figure 14-9 shows that there is quite a lot of wiring involved in multiplexing the display. The same hardware can be attached to the GPIO pins of a Raspberry Pi (at least a 40-pin GPIO Raspberry Pi) but the nature of the operating system means that you might find the refresh a little uneven. For a Raspberry Pi, it is probably better to use a display module that has its own hardware such as the I2C LED display in Recipe 14.9.
To use an I2C 7-segment LED module, see Recipe 14.9.
Use a technique called Charlieplexing.
The name Charlieplexing comes from the inventor Charlie Allen of the company Maxim, and the technique takes advantage of the feature of GPIO pins that allows them to be changed from outputs to inputs while a program is running. When a pin is changed to be an input, not enough current will flow through it to light an LED or influence other pins connected to the LED that are set as outputs.
Figure 14-10 shows the schematic for controlling six LEDs with three pins.
Looking at Figure 14-10, if you want to turn on LED1, you need to make pin A high and B low. But to make sure that none of the other LEDs light, you need to set C to be an input, so that no current can flow into or out of it. More accurately, to make sure that not enough current to light an LED flows into or out of it.
For a small number of LEDs, you can test out Charlieplexing on a breadboard as shown in Figure 14-11.
Connect the three control points on the breadboard to pins D5, D6, and D7 of your Arduino (D6 to the middle control pin). You can then use the following sketch (ch_14_charlieplexing) to try out Charlieplexing. You will find the sketch with the downloads for the book (see Recipe 10.2):
constintpins[]={5,6,7};constintpinLEDstates[6][3]={{1,0,-1},// LED 1{0,1,-1},// LED 2{-1,1,0},// LED 3{-1,0,1},// LED 4{1,-1,0},// LED 5{0,-1,1}// LED 6};intledState[6];voidsetup(){Serial.begin(9600);Serial.println("LED Number (0 to 5)");}voidloop(){if(Serial.available()){intled=Serial.parseInt();ledState[led]=!ledState[led];}refresh();}voidrefresh(){for(intled=0;led<6;led++){clearPins();if(ledState[led]){setPins(led);}else{clearPins();}delay(1);}}voidsetPins(intled){for(intpin=0;pin<3;pin++){if(pinLEDstates[led][pin]==-1){pinMode(pins[pin],INPUT);}else{pinMode(pins[pin],OUTPUT);digitalWrite(pins[pin],pinLEDstates[led][pin]);}}}voidclearPins(){for(intpin=0;pin<3;pin++){pinMode(pins[pin],INPUT);}}
The key to this code is the pinLEDstates data structure. This specifies the states that the controlling pins should be set to for a particular LED. So, LED3 has the pattern –1, 1, 0. This means that for LED3 to be lit, the first control pin should be set to an input (–1), the second control pin to a HIGH digital output, and the third to a LOW digital output. If you check Figure 14-10 this will confirm those settings.
The loop function first prompts for a particular LED and then toggles that LED turning it on if it was off and off if it was on. The array ledStates is used to keep track of which LEDs should be on or off.
The loop function then calls refresh, which first clears all the pins setting them to inputs using clearPins and then for each of the LEDs uses setPins to either set the pins appropriately to turn the LED on or not depending on that LED’s entry in ledState.
This works fine for a fairly small number of LEDs, assuming that the Arduino is not doing much else, so that refresh can be called frequently. You may have noticed that the LEDs flicker when serial communication is in progress through the Serial Monitor.
Using a Raspberry Pi instead of an Arduino just requires you to swap the male-to-male header leads to be male-to-female connectors and choose three GPIO pins. In the case of the following example program (ch_14_charlieplexing.py) these should be 18, 23, and 24. You should also increase the value of the resistors to 270Ω.
You can find the program with the downloads for the book (see Recipe 10.4):
importRPi.GPIOasGPIOimportthread,timeGPIO.setmode(GPIO.BCM)pins=[18,23,24]pin_led_states=[[1,0,-1],# LED1[0,1,-1],# LED2[-1,1,0],# LED3[-1,0,1],# LED4[1,-1,0],# LED5[0,-1,1]# LED6]led_states=[0,0,0,0,0,0]defset_pins(led):forpininrange(0,3):ifpin_led_states[led][pin]==-1:GPIO.setup(pins[pin],GPIO.IN)else:GPIO.setup(pins[pin],GPIO.OUT)GPIO.output(pins[pin],pin_led_states[led][pin])defclear_pins():forpininrange(0,3):GPIO.setup(pins[pin],GPIO.IN)defrefresh():whileTrue:forledinrange(0,6):clear_pins()ifled_states[led]:set_pins(led)else:clear_pins()time.sleep(0.001)thread.start_new_thread(refresh,())whileTrue:x=int(raw_input("Pin (0 to 5) :"))led_states[x]=notled_states[x]
The Raspberry Pi version follows the same pattern as the Arduino version except that the call to refresh is in a separate thread of execution, so the display will automatically update, even if the Python program is waiting for input.
The number of LEDs that can be controlled for the number of GPIO pins (n) used is given by the formula:
Using four pins, you can have 16–4 = 12 LEDs, whereas 10 pins would give you a massive 90 LEDs.
For a great description of Charlieplexing as well as layouts for large numbers of LEDs, see https://en.wikipedia.org/wiki/Charlieplexing.
Wire up a common-cathode RGB LED as shown in Figure 14-12.
The red, green, and blue LEDs, in this example, all have different values of series resistor to try and provide equal brightness. The three LED channels can either be simply turned on and off to mix seven different colors from the three control pins, or you can use PWM on the pins to mix more subtle colors.
Connect an RGB LED to an Arduino as shown in Figure 14-12 using the three Arduino pins 9, 10, and 11 for the blue, green, and red channels, respectively.
The following sketch can be found with the downloads for the book (Recipe 10.2) and is called ch_14_rgb_led:
constintredPin=11;constintgreenPin=10;constintbluePin=9;voidsetup(){pinMode(redPin,OUTPUT);pinMode(greenPin,OUTPUT);pinMode(bluePin,OUTPUT);Serial.begin(9600);Serial.println("Enter R G B (E.g. 255 100 200)");}voidloop(){if(Serial.available()){intred=Serial.parseInt();intgreen=Serial.parseInt();intblue=Serial.parseInt();analogWrite(redPin,red);analogWrite(greenPin,green);analogWrite(bluePin,blue);}}
By sending three numbers separated by spaces from the Arduino Serial Monitor, you can mix pretty much any color from the LED.
When using a Raspberry Pi, you can follow the same approach of creating three PWM channels using the RPi.GPIO library (see Recipe 10.14) or, as in the following example, you can install the Python Squid library, which simplifies the process.
To install the Squid library, run the following commands:
$ git clone https://github.com/simonmonk/squid.git $ cd squid $ sudo python setup.py install
The equivalent program for controlling the RGB LED from a Raspberry Pi can be a little fancier and use the Tkinter Python library to make a user interface that allows you to use sliders to adjust the red, green, and blue channels (Figure 14-14):
fromsquidimport*fromTkinterimport*rgb=Squid(18,23,24)classApp:def__init__(self,master):frame=Frame(master)frame.pack()Label(frame,text='Red').grid(row=0,column=0)Label(frame,text='Green').grid(row=1,column=0)Label(frame,text='Blue').grid(row=2,column=0)scaleRed=Scale(frame,from_=0,to=100,orient=HORIZONTAL,command=self.updateRed)scaleRed.grid(row=0,column=1)scaleGreen=Scale(frame,from_=0,to=100,orient=HORIZONTAL,command=self.updateGreen)scaleGreen.grid(row=1,column=1)scaleBlue=Scale(frame,from_=0,to=100,orient=HORIZONTAL,command=self.updateBlue)scaleBlue.grid(row=2,column=1)defupdateRed(self,duty):rgb.set_red(float(duty))defupdateGreen(self,duty):rgb.set_green(float(duty))defupdateBlue(self,duty):rgb.set_blue(float(duty))root=Tk()root.wm_title('RGB LED Control')app=App(root)root.geometry("200x150+0+0")root.mainloop()
The LED in Figure 14-12 is a common cathode device; that is, all the negative terminals (cathodes) of the LEDs are connected together. RGB LEDs are also available in common anode form, which can sometimes be more convenient if they are being controlled by transistors as it allows low-side switching.
For recipes on PWM for Arduino and Raspberry Pi, see Recipe 10.13 and Recipe 10.14, respectively.
The easiest way to control large numbers of RGB LEDs is to use addressable LED strips as described in Recipe 14.8.
Do the power calculations carefully for your pixels and then use a single GPIO pin to send the data to the pixel array. Figure 14-15 shows a typical arrangement for a large number of pixels. If you only have a few pixels (say 5–10), you can power them directly from your Arduino or Raspberry Pi.
If you don’t mind taking the risk of damaging your Pi, Arduino, or whatever is supplying USB power to them, you can power more pixels as long as you are extremely careful in your code to keep the brightness of the pixels well below the maximum brightness. However, this is not recommended.
To test out an addressable LED strip with an Arduino, connect pin D9 to the data terminal of an addressable LED strip.
The Arduino sketch ch_14_neopixel is included in the downloads for the book (see Recipe 10.2). The sketch uses the Adafruit NeoPixel library. This can be installed from within the Arduino IDE using the Library Manager by selecting the menu option Sketch→Include Library→Manage Libraries.
Once the Library Manager is open scroll down and select Adafruit NeoPixel and then click Install.
#include <Adafruit_NeoPixel.h>constintpixelPin=9;constintnumPixels=10;Adafruit_NeoPixelpixels=Adafruit_NeoPixel(numPixels,pixelPin,NEO_GRB+NEO_KHZ800);voidsetup(){pixels.begin();}voidloop(){for(inti=0;i<numPixels;i++){intred=random(64);intgreen=random(64);intblue=random(64);pixels.setPixelColor(i,pixels.Color(red,green,blue));pixels.show();}delay(100);}
Change the values of pixelPin and numPixels to match the GPIO pin you are using and the number of pixels in your strip.
Each pixel will be allocated red, green, and blue intensities at random. Note that the maximum of 64 is used rather than the full range of 0 to 255 because an intensity of 255 is actually very bright.
To test out an addressable LED strip with Raspberry Pi, connect GPIO10 to the data terminal of an addressable LED strip.
To use the display, you first need to install some libraries by running the following commands:
$ git clone https://github.com/doceme/py-spidev.git $ cd py-spidev/ $ make $ sudo make install $ cd .. $ git clone https://github.com/joosteto/ws2812-spi.git $ cd ws2812-spi $ sudo python setup.py install
You still also need to enable SPI on your Raspberry Pi (see Recipe 10.16).
You can find a program to test out the LED display in the file ch_14_neopixels.py. See Recipe 10.4 for information on downloading the Python example programs.
importspidevimportws2812fromrandomimportrandintimporttimespi=spidev.SpiDev()spi.open(0,0)N=10# g r bpixels=[]forxinrange(0,10):pixels.append([0,0,0])whileTrue:foriinrange(0,N):pixels[i]=[randint(0,64),randint(0,64),randint(0,64)]ws2812.write2812(spi,pixels)time.sleep(0.1)
Each pixel is represented in an array of three values. These are in order green, red, and blue rather than the more usual red, green, blue. That’s just how the library is. An array (pixels) of N elements where N is the number of pixels is created by using a for loop to append N arrays of green, red, and blue to the pixels array.
The main loop acts just like its Arduino counterpart. It allocates color intensities at random to each pixel position before using the ws2812 library to write out the pixels to the GPIO pin.
If you are using a Raspberry Pi, then you may need to level shift the data output (Recipe 10.17), although I have never found this to be necessary in practice. Looking at the datasheet for the WS2812, the minimum input voltage to count as a logical HIGH is 0.7 times the supply voltage (5V). This gives a theoretical value of 3.5V.
You can make a convenient display to attach to an Arduino or Raspberry Pi by sacrificing jumper leads by snipping off one connector and soldering the wire to the LED strip. Figure 14-16 shows such a display connected to a Raspberry Pi. Note the use of the heat-shrink sleave to help stop the solder joints from flexing.
For more information on the ws2812-spi library, see https://github.com/joosteto/ws2812-spi, including instructions on using the NumPy library to improve performance for long LED strings.
You can find the datasheet for the WS2812 here: https://cdn-shop.adafruit.com/datasheets/WS2812.pdf.
To control a single RGB LED directly, see Recipe 14.7.
Addressable LED pixels are not confined to strips of LEDs; you can also buy them organized into rings (Adafruit product 1586) and arrays (Adafruit product 1487).
An alternative library that is based on the Raspberry Pi’s DMA hardware rather than its SPI can be found here: https://github.com/richardghirst.
You want to use a 7-segment display but without the spaghetti wiring of Recipe 14.5.
Use a ready-made I2C display module like the one shown in Figure 14-17.
This module and similar modules that can be found on eBay, with four or even eight digits, are a convenient way to add a 7-segment LED display to an Arduino or Raspberry Pi.
Figure 14-18 shows how to wire one up using two GPIO pins.
The I2C serial interface needs two data pins as well as 5V of power. On both the Arduino and Raspberry Pi, specific pins must be used for the I2C interface. On the Arduino Uno, these are the SCL (serial clock) and SDA (serial data) pins (see Recipe 10.7) and on a Raspberry Pi, these are GPIO2 and GPIO3.
This display and many types of displays like it use the HT16K33 IC, which can actually control up to 16 segments in 8 digits. Although the module needs to be powered with 5V, its I2C interface works fine from 3.3V Raspberry Pi GPIO pins, so no level conversion is necessary.
The sketch uses the Adafruit LED Backpack library and Adafruit GFX library. These can be installed from within the Arduino IDE using the Library Manager by selecting the menu option Sketch→Include Library→Manage Libraries.
Once the Library Manager has opened scroll down and select the two libraries and and then click Install.
Adafruit provides a whole load of examples for using the library that you can access directly from the Arduino IDE. A good example to try out can be found under the menu item File→Examples→Adafruit Backpack Library→sevenseg.
The connections between the Raspberry Pi and the module are as follows:
VCC is the abbreviation for volts collector collector, and is frequently used to identify the positive power supply pin of an IC or module.
Before you can use the display, you will need to enable the Raspberry Pi’s I2C interface by following Recipe 10.15.
Adafruit also provides Python code for this module. To install it, enter the following commands into the terminal:
$ sudo apt-get update $ sudo apt-get install build-essential python-dev $ sudo apt-get install python-imaging $ git clone https://github.com/adafruit/Adafruit_Python_LED_Backpack.git $ cd Adafruit_Python_LED_Backpack $ sudo python setup.py install
A good example to try out is the clock example sevensegment_test.py.
Building a project using a module like this is fine when you are developing a prototype, but in a finished product, you would most likely use direct multiplexing as described in Recipe 14.5 (to reduce costs) or use the HT16K33 IC on a circuit board of your own design, if you really need a hardware driver.
You can find lots more information on this display at its project page on Adafruit.
To control a similar display but using multiplexing, see Recipe 14.5.
You can download the HT16K33 datasheet from http://bit.ly/2mbaWyP.
Use an I2C OLED display like the one shown attached to an Arduino in Figure 14-20.
The display has the same four connections as the display used in Recipe 14.9 so you can make the same connections as shown in Figure 14-18.
Wire up the display as described in Recipe 14.9.
You will also need to add the Adafruit GFX and SSD1306 libraries to your Arduino IDE by using the Library Manager (from the menu Sketch→Include Library→Library Manager and then scroll down the list and install both the Adafruit GFX Library and the Adafruit SSD1306 library).
The example sketch ch_14_oled will display the message shown in Figure 14-20. To install the Arduino programs for the book, see Recipe 10.2.
#include <Wire.h>#include <Adafruit_GFX.h>#include <Adafruit_SSD1306.h>Adafruit_SSD1306display(4);voidsetup(){display.begin(SSD1306_SWITCHCAPVCC,0x3c);display.clearDisplay();display.drawRect(0,0,display.width()-1,display.height()-1,WHITE);display.setTextSize(1);display.setTextColor(WHITE);display.setCursor(5,10);display.("Electronics Cookbook");display.display();}voidloop(){}
Wire up the display as described in Recipe 14.9.
Before you can use the display, you will need to enable the Raspberry Pi’s I2C interface by following Recipe 10.15.
You will also need to download and install the SSD1306 Python library and prerequisites using the following commands:
$ sudo pip install pillow $ git clone https://github.com/rm-hull/ssd1306.git $ cd ssd1306 $ sudo python setup.py install
Now change the directory to the book’s example programs and run the program ch_14_oled.py (see Recipe 10.4). The text “Electronics Cookbook” with a rectangular border should appear on the display. If it doesn’t, then there is a good chance you will need to change the I2C address of the device in the file demo_opts.py that is with the other downloads. Change line 13 from 0x3c to the I2C address of your device. The file ch_14_oled.py is listed here:
fromdemo_optsimportdevicefromoled.renderimportcanvasfromPILimportImageFontfromdemo_optsimportargsfont=ImageFont.load_default()withcanvas(device)asdraw:draw.rectangle((0,0,device.width-1,device.height-1),outline=255,fill=0)font=ImageFont.load_default()draw.text((5,20),'Electronics Cookbook',font=font,fill=255)
Once you get into the realm of needing a display that can show text and graphics, you can of course use an HDMI monitor with your Raspberry Pi.
For a simple numeric display see Recipe 14.9 and for a low-cost two-line alphanumeric display see Recipe 14.11.
The SSD1306 library page on GitHub has more examples and documentation for using these displays: https://github.com/rm-hull/ssd1306.
Use an LCD module based on the HD44780 IC. Figure 14-21 shows one of these displays wired to an Arduino and Figure 14-22 shows how the display should be connected on a breadboard. Figure 14-23 shows the connections for a Raspberry Pi as a schematic.
The HD44780 can be configured to use either an 4- or 8-bit parallel data bus. If the 4-bit bus is used only bits 4 to 7 of the bus are used. The pin Vo is used to control the contrast of the screen. You will need to adjust R1 to be able to see anything on the screen.
The Arduino IDE includes a library called LiquidCrystal that takes care of all the communications with the HD44780 IC. The following example can be found with the Arduino downloads for the book (Recipe 12.2) in the sketch ch_14_lcd:
#include <LiquidCrystal.h>// RS EN D4 D5 D6 D7LiquidCrystallcd(7,8,9,10,11,12);voidsetup(){lcd.begin(16,2);lcd.("Electronics");lcd.setCursor(0,1);lcd.("Cookbook");}voidloop(){lcd.setCursor(10,1);lcd.(millis()/1000);}
To use an HD44780 display on a Raspberry Pi, you will first need to install the Adafruit CharLCD Python library by entering the following commands:
$ git clone https://github.com/adafruit/Adafruit_Python_CharLCD.git $ cd Adafruit_Python_CharLCD $ sudo python setup.py install
You can now try out the example program ch_14_lcd.py:
importtimeimportAdafruit_CharLCDasLCD# Raspberry Pi pin configuration:lcd_rs=27# Note this needs to be changed to 21 for Model B rev1 Pis.lcd_en=22lcd_d4=25lcd_d5=24lcd_d6=23lcd_d7=18lcd_backlight=4lcd_columns=16lcd_rows=2lcd=LCD.Adafruit_CharLCD(lcd_rs,lcd_en,lcd_d4,lcd_d5,lcd_d6,lcd_d7,lcd_columns,lcd_rows,lcd_backlight)lcd.message('Electyronics\nCookbook')t0=time.time()whileTrue:lcd.set_cursor(10,1)lcd.message(str(int(time.time()-t0)))time.sleep(0.1)
Adafruit has a wide selection of these types of displays, including ones that have an RGB color backlight (https://www.adafruit.com/products/399).
In many projects the only digital IC you will need is a microcontroller. With sufficient GPIO pins you can do most digital tasks. In this chapter, you will find recipes for digital ICs that still manage to find a role in modern electronics design.
Sometimes, a single digital logic IC is all you need. A single digital logic IC is often cheaper and removes the need for programming that would otherwise arise if you used a microcontroller.
Use a 100nF capacitor as close as possible to the power pins of the digital IC. The shorter the leads to the capacitor the better.
This process of connecting a capacitor with short circuit board tracks to the power pins of an IC is called “decoupling” because each IC has its own little reservoir of charge and will therefore not be “coupled” to a neighboring capacitor by affecting its power supply. Capacitors used in this way are also called “bypass” capacitors.
Figure 15-1 shows a circuit board containing a digital IC with a 100nF multilayer ceramic (MLC) capacitor for both a through-hole and SMD.
The circuit board on the right of Figure 15-1 actually has two capacitors in parallel as the decoupling capacitor. The smaller one is 100nF and the larger one 10µF. You may think that the effect of the 100nF would be lost, but its lower ESR (see Recipe 3.2) allows it to respond faster to pulses of power consumption from the chip. So, the 10µF capacitor is in turn providing a larger local energy store for the smaller capacitor and IC to draw on, but one that has a higher ESR and therefore cannot respond as quickly. Such an arrangement of ever-decreasing capacitor values as you approach the power rails of the IC is particularly common where larger currents are being switched such as in motor controllers and audio power amplifiers.
Digital ICs contain lots of transistors that switch very quickly. The decoupling capacitor provides a little reservoir of charge so that this switching does not result in excessive electrical noise on the power lines that could go on to affect other parts of the circuit.
It is considered to be good practice to include a decoupling capacitor next to every digital IC. In fact, this is also true of analog ICs.
For more information on capacitors, see Chapter 3.
Logic-gate ICs, like the mafia, are arranged into families. TTL (transistor transistor logic) used to be a popular choice, but is now totally obsolete unless you are repairing an equally obsolete computer from the last century. TTL chips starting with the number 74 (e.g., 7400) used to compete with CMOS chips with names that started with 40 (e.g., 4011). Each had their own overlapping ranges of logic gates, flip-flops, shift registers, and counters.
TTL was faster than CMOS, but CMOS used less current and was far less fussy about its supply-voltage range. Now these two families have merged into a single “best-of-both-worlds” family called high-speed CMOS. If you started playing with electronics in the 1970s, you can still find your favorite logic ICs from both families but under one name starting with 74HC. For instance, the 7400 of old is now the 74HC00 and the 4011 of old is now called the 74HC4001.
A high-speed CMOS chip has a supply-voltage range of 2V to 6V and only consumes about 1µA until it starts switching. Their outputs can also generally source or sink 4mA at their outputs (per gate).
The original 40xx CMOS is still available and can be useful where you need a greater power-supply range than high-speed CMOS can provide.
For the datasheet of a typical high-speed CMOS device, see http://www.ti.com/lit/ds/symlink/sn74hc00.pdf.
Use a serial-to-parallel shift register such as the 74HC4094 and write some code to load its registers with data using a serial interface that only requires three pins. LEDs can then be attached to the outputs. Figure 15-2 shows a schematic for this.
The total current allowed by the 74HC4094 is 50mA so assuming 6mA per LED, a suitable series resistor would be 680Ω if all the LEDs are lit at the same time, to allow 8 x 6mA = 48mA.
You can find the Arduino code to send data to the shift register with the downloads for the book (Recipe 10.2) in the sketch ch_15_sift_reg:
constintstrobePin=5;constintdataPin=6;constintclockPin=7;voidsetup(){pinMode(strobePin,OUTPUT);pinMode(dataPin,OUTPUT);pinMode(clockPin,OUTPUT);Serial.begin(9600);Serial.println("Enter Byte");}voidloop(){if(Serial.available()){charbits=Serial.parseInt();shiftOut(dataPin,clockPin,MSBFIRST,bits);digitalWrite(strobePin,HIGH);delayMicroseconds(10);digitalWrite(strobePin,LOW);Serial.println(bits,2);}}
This sketch uses the Arduino shiftOut function to send the serial data and uses these parameters: the pin to send the data on, the clock pin, a flag to determine the order the data is sent (in this case, most significant bit [MSB] first), and the actual data to send.
If you open the Arduino Serial Monitor, you will be prompted for a value to load into the shift register. This value will be shifted in and then a confirmation of the data in binary will be displayed as shown in Figure 15-3. The value entered should be a decimal value between 0 and 255. This value will be echoed in binary in the Serial Monitor for confirmation.
The following test program assumes you have connected the STROBE pin of the 74HC4094 to GPIO18, the DATA pin to GPIO23, and the CLOCK pin to GPIO24.
The Python code (ch_15_shift_reg.py) follows a similar pattern as that of the Arduino, but in this case we have to implement the shift_out function. This sets the data_pin to the eighth bit of the data, and then pulses the clock_pin before shifting the data left by one bit position, and so on for all eight bits in MSB first order:
importRPi.GPIOasGPIOimporttimeGPIO.setmode(GPIO.BCM)strobe_pin=18data_pin=23clock_pin=24GPIO.setup(strobe_pin,GPIO.OUT)GPIO.setup(data_pin,GPIO.OUT)GPIO.setup(clock_pin,GPIO.OUT)defshift_out(bits):# MSB first. 8 bitsforiinrange(0,8):b=bits&0b10000000bits=bits<<1GPIO.output(data_pin,(b==0b10000000))time.sleep(0.000001)GPIO.output(clock_pin,True)time.sleep(0.000001)GPIO.output(clock_pin,False)time.sleep(0.000001)try:whileTrue:bits=input("Enter Byte ")(bin(bits))shift_out(bits)GPIO.output(strobe_pin,True)time.sleep(0.000001)GPIO.output(strobe_pin,False)finally:("Cleaning up")GPIO.cleanup()
Figure 15-4 shows the logical diagram for the 74HC4094.
The 74HC4094 is a serial-to-parallel shift register. The 8-stage shift register’s data is set a bit at a time by setting the data (D) pin either HIGH or LOW and then pulsing the clock (CP) pin to transfer that bit. The data pin is then set to the next value and the clock pulsed again to shift the bit already in the shift register along one position and then add the new bit at the beginning. This process continues until all eight bits are loaded into the shift register.
The contents of the shift register are not actually transferred to the 74HC4094’s outputs until the strobe pin (STR) is pulsed.
The 74HC4094 also has an output enable (OE) pin that switches all eight outputs either to a high impedance state or to the bit pattern of HIGHs and LOWS in the 3-state-outputs register. If you connect this OE pin to a PWM output you can use it to control the brightness of all the LEDs at the same time.
You can cascade a number of shift registers together by tying their clocks together and attaching the QS2 data output from one shift register to the data input of the next.
Another way of controlling lots of LEDs from a small number of GPIO pins is to use Charlieplexing (Recipe 14.6).
You can find the datasheet for the 74HC4094 here: http://bit.ly/2mqB0ET.
For more information on the Arduino shiftOut function, see http://bit.ly/2msRHAg.
Use an 74HC00 IC to make a reset-set flip-flop as shown in Figure 15-5.
When SW1 is pressed the LED will light and stay lit until SW2 is pressed.
R1 and R2 are pull-up resistors that keep the inputs to flip-flop high until the buttons are pressed. One advantage of this way of switching is that if the switches bounce (Recipe 12.1) it will have no effect on the operation of the circuit.
Note that in Figure 15-5 the inputs of the two unused gates in the 74HC00 are tied to ground. This is considered good practice as it prevents the otherwise floating inputs from causing the gates to oscillate in time with electrical noise.
In addition to switching an LED on or off, you could adapt this circuit to switch large loads with a transistor by combining it with Recipe 11.1 or Recipe 11.3.
You can find the datasheet for the 74HC00 here: http://bit.ly/2lLK0R5.
Use a frequency-divider IC such as the 8-stage 74HC590 in the arrangement shown in Figure 15-6.
The output at QA will be half the input frequency f, QB a quarter, and so on until QH has an output frequency of 1/256 of the input frequency.
For most designs it is preferable to use a microcontroller when it comes to things like counting. However, counting clock cycles with a microcontroller is significantly slower than the clock frequency of the microcontroller itself. So, a maximum frequency might be a few hundred kHz. To count higher frequencies, QH or one of the other outputs of the 74HC590 could be connected to a digital input on a microcontroller to allow frequencies up to the 24MHz maximum the 74HC590 allows.
You can find the datasheet for the 74HC590 here: http://www.nxp.com/documents/data_sheet/74HC590.pdf.
Connect the clock and reset the pins of a 74HC4017 decimal counter IC to an Arduino or Raspberry Pi and attach LEDs to the outputs of the 74HC4017 with suitable current-limiting resistors as shown in Figure 15-7.
The 74HC4017 is a decade counter with decoded outputs. That is, each time it receives a pulse on its clock (CLK) pin it advances to the next output. So, first Q0 is high, then Q1, and so on. The reset pin (RES) sets the counter back to the first output Q0.
Since only one of the LEDs is ever on at a time, the full 20mA output of the 74HC4017 can be used to drive the LEDs.
The Arduino sketch ch_15_decade_counter is given here. You can find it with the downloads for the book (Recipe 10.2):
constintresetPin=6;constintclockPin=7;voidsetup(){pinMode(resetPin,OUTPUT);pinMode(clockPin,OUTPUT);Serial.begin(9600);Serial.println("Enter digit 0..9");}voidloop(){if(Serial.available()){intdigit=Serial.parseInt();setDigit(digit);}}voidsetDigit(intdigit){digitalWrite(resetPin,HIGH);delayMicroseconds(1);digitalWrite(resetPin,LOW);for(inti=0;i<digit;i++){digitalWrite(clockPin,HIGH);delayMicroseconds(1);digitalWrite(clockPin,LOW);delayMicroseconds(1);}}
The code starts by pulsing the reset pin so that the output Q0 will be high. It then issues the number of pulses to the clock pin requested by the number sent from the Serial Monitor.
The reason the LEDs don’t flicker and you don’t see the LEDs before the selected LED flash is that this pulsing happens very quickly (in fact, in a few millionths of a second).
The equivalent Python sketch for the Raspberry Pi assumes you have GPIO18 connected to the reset pin of the 74HC4017 and GPIO23 connected to the clock pin.
The program is called ch_15_decade_counter.py. See Recipe 10.4 for information on installing the example programs:
importRPi.GPIOasGPIOimporttimeGPIO.setmode(GPIO.BCM)reset_pin=18clock_pin=23GPIO.setup(reset_pin,GPIO.OUT)GPIO.setup(clock_pin,GPIO.OUT)defset_digit(digit):GPIO.output(reset_pin,True)time.sleep(0.000001)GPIO.output(reset_pin,False)time.sleep(0.000001)foriinrange(0,digit):GPIO.output(clock_pin,True)time.sleep(0.000001)GPIO.output(clock_pin,False)time.sleep(0.000001)try:whileTrue:digit=input("Enter digit 0..9 ")set_digit(digit)finally:("Cleaning up")GPIO.cleanup()
The program works in just the same way as its Arduino counterpart.
Using a counter like the 74HC4017 can be useful when multiplexing an LED display (Recipe 14.5), as you can use it to select each digit of a 7-segment display or column of an LED matrix, without tying up too many GPIOs.
You can find the datasheet for the 74HC4017 here: http://www.nxp.com/documents/data_sheet/74HC_HCT4017.pdf.
In these circumstances, a simple RC filter (Figure 16-1) will suffice to remove most of the unwanted high-frequency PWM carrier.
Intuitively, all the resistor and capacitor do is make the output slow to respond to changes to the input. All that remains is to decide on suitable values for R and C. We can illustrate this with an example.
The Arduino Mozzi library (Recipe 18.1) generates PWM (Recipe 10.13) audio output. The length of the pulses on the constant PWM frequency of 32.7kHz determine the amplitude of the lower frequency underlying the audio signal (440 Hz). Figure 16-2 illustrates this.
The average output voltage is shown by the dashed line, which increases as the pulses lengthen.
Using a value of 270Ω for R and \330nF for C produces the filtering shown in Figure 16-3. The top trace shows the filtered output and the bottom trace the PWM signal.
You can see that the original sine wave from (top) has been extracted from the PWM signal (bottom).
The kind of RC filter used here is called a first-order filter and only really works well if the signal being filtered is much greater than the frequency you want to keep. Figure 16-4 shows the characteristic plot of gain against frequency.
A gain of 1 means the signal is unchanged in magnitude. In the “stop band” where the signal is being attenuated, the signal’s amplitude halves every time the frequency doubles.
The start of the stop band is taken to be after the “corner frequency” (f0), which is defined as the frequency at which the signal amplitude has been reduced to 75% for its original value.
The corner frequency is given by the formula:
Using a resistor of 270Ω and 330nF capacitor the corner frequency is:
With a corner frequency of 1.768kHz and a frequency of 32.7kHz for the PWM signal (that we are trying to filter out) a quick check will show you that you are looking at a little over four doublings of 1.786kHz, which gives a reduction of four halvings of the amplitude of that high-frequency component. This will reduce the amplitude of the 32.7kHz signal to about 1/16 of its unattenuated value, which is why the PWM frequency is still visible on top of the 440Hz sinewave shown in Figure 16-3.
If you want to try out this experiment, then install the Mozzi library into your Arduino IDE by downloading the ZIP for the library from GitHub and then installing the ZIP for the library from the Arduino IDE’s menu (Sketch→Include Library→Add .ZIP Library).
From the Arduino IDE’s example menu, upload Files→Examples→Mozzi→Basics→Sinewave onto your Arduino and wire it up as shown in Figure 16-1.
Attaching an oscilloscope to the unfiltered and filtered outputs of D9 should give you a trace similar to Figure 16-3.
For a better-quality filter with a much steeper fall-off of gain with frequency, see Recipe 17.7.
In this recipe, we have talked about attenuation of a signal’s amplitude in terms of halving or quartering. The more common unit for attenuation and amplification of a signal is the dB (decibel). This is described in Recipe 17.1.
A great way to help design filters is to use simulation. This example is used in Recipe 21.11.
For instructions on using an oscilloscope, see Recipe 21.9.
Use the transistors in the arrangement shown in Figure 16-5. This arrangement is also sometimes called an “astable,” meaning it has no stable state, and instead oscillates between two states.
When power is first applied to the circuit both Q1 and Q2 will be off. Very slight differences between the capacitor values and the values of R2 and R3 mean that one of the capacitors will start to charge through R2 or R3 faster than the other. The faster-charging capacitor will win the race to turn on the transistor whose base it is connected to. Current flows through this transistor turning on the LED and drops the collector voltage allowing the slower capacitor to start charging until the opposite transistor turns on and so on.
The frequency of this oscillator is determined by the time constant of C1 and R2 (C1 and C2 should have the same value, as should R2 and R3), but also depends on the characteristics of the transistor. For the circuit shown in Figure 16-5 and a supply voltage of 9V, the frequency was measured as 2.8Hz, implying that the frequency is related to R2 and C1 by the formula:
For an oscillator that uses the NE555 timer IC, see Recipe 16.5.
You can see a video of this circuit in action here: https://youtu.be/-NvMFmPHc4s.
Build a ring oscillator using MOSFETs as shown in the schematic in Figure 16-6.
The way to understand how this circuit works is to think of each transistor stage as an inverter. That is, if the gate of the transistor is low, then the drain of the transistor will be pulled high by the LED and resistor. As the transistor’s associated gate capacitor charges, the gate voltage will gradually rise until the transistor is on and then the drain will go low. The final inverter stage then feeds back to the first transistor and the cycle continues. This does not work with an even number of stages as the outputs of the first and last stages would both be high and low (in phase) with each other and no oscillation would occur.
This oscillator produces quite a mesmeric effect as the LED brightness gradually increases and decreases.
In practical terms, when considering a large number of LEDs, you would probably use a microcontroller with LEDs attached to digital outputs, or a decade counter like the 4017 described in Recipe 15.6.
For an interesting Wikipedia article on the ring oscillator, see https://en.wikipedia.org/wiki/Ring_oscillator.
There is a video of this circuit here: https://youtu.be/9O5Ojhr0oGg.
Use a BJT arranged as an emitter-follower, as shown in Figure 15-7. In this case, the input is provided by a pot. The output voltage will follow the input voltage (less the base-emitter voltage).
On the face of it, this may seem pointless and you might be asking yourself why you wouldn’t just take the output from the slider of R1. The reason is that even a very slight load resistance on R1 will alter its output voltage, whereas by using a transistor, a much larger load current can be drawn.
Whatever the voltage set at the base of the transistor (above about 0.6V), the emitter will always be about 0.6V lower, but able to provide significantly more current. In fact, the ratio of base-to-collector current is the DC gain of the transistor. For a transistor like the 2N3904, this is generally taken to be about 100. So for a collector current of say 10mA, less than 100µA should be flowing into the base from R1.
An emitter-follower like this can be used as the basis of a voltage regulator using the schematic in Figure 16-8, although generally a voltage-regulator IC is an easier option.
As described in Recipe 4.3 the Zener diode will keep the base of Q1 at 5.6V as long as the input voltage is greater than 5.6V. The Zener diode acts as a voltage reference to Q1, whose emitter will remain at 5V as long as the load current does not become great enough to start drawing significant base current and hence cause the voltage at the base to drop. Using a power Darlington like the TIP120 with its DC current gain of around 10,000 will provide even better regulation, at higher currents, but at the expense of a bigger base-emitter voltage drop (see Recipe 5.2).
For a more or less perfect unity gain buffer without the base-emitter voltage drop, see Recipe 17.6.
For more information on BJTs, see Recipe 5.1.
Use an NE555 timer IC in the configuration shown in Figure 16-9.
This is not the standard astable oscillator schematic for an NE555. But unless you need to control the duty cycle for PWM or other purposes, it’s fine for a simple oscillator.
The frequency is set by the values of R2 and C1:
So, for an R2 of 10kΩ and a C1 of 10nF, the frequency is:
To simplify the calculations, standardize a few values of C1. For low-frequency LED blinking, use a 1μF capacitor; for audio frequencies of a few hundred Hz, use 100nF; and for higher frequencies into the kHz, use a 10nF capacitor. Fixing the capacitor in this way means you can use the following formula to calculate the value of R2 that you need:
Table 16-1 shows some common frequencies and suitable component values.
| Frequency | C1 | R2 |
|---|---|---|
| 1Hz | 1µF | 693kΩ |
| 2Hz | 1µF | 347kΩ |
| 50Hz | 1µF | 13.9kΩ |
| 100Hz | 1µF | 6.93kΩ |
| 1kHz | 10nF | 69.3kΩ |
| 10kHz | 10nF | 6.93kΩ |
| 100kHz | 10nF | 693Ω |
Remember that capacitors in particular are generally only accurate at values of ±10% and the frequency is also somewhat dependent on the supply voltage. Table 16-2 shows the effect of supply voltage on output frequency for this circuit using an R2 of 10kΩ and a C1 of 10nF.
| Supply Voltage (V) | Output Frequency (kHz) |
|---|---|
| 5 | 5.46 |
| 9 | 6.63 |
| 12 | 7.03 |
| 16 | 7.33 |
You can find the datasheet for the NE555 here: http://www.ti.com/lit/ds/symlink/ne555.pdf.
If you need complimentary outputs from your oscillator, use a 4047 timer IC (Recipe 7.10 ).
The NE555 IC is a versatile device and can also be used as a one-shot timer (Recipe 16.7).
You can also make an oscillator with just two transistors as described in Recipe 16.2.
Use an NE555 timer IC, but this time in the configuration shown in Figure 16-10.
The frequency and duty cycle (proportion of the time the output is high to the time it is low) are set by the values of C1, R1, and R2. The period of time the output is high during each cycle is:
The time it is low is given by:
The overall frequency in Hz will be the inverse of these two times added together:
If you want a fairly even duty cycle, you can just use Recipe 16.5, or make sure that R1 is much smaller than R2 (without being 0).
To avoid all the math, there are lots of good online calculators out there you can use. This one is particularly useful as it allows you to enter just the frequency and duty cycle you want.
The NE555 timer is an extremely flexible device. Figure 16-11 shows the internal structure of the IC.
The design is centered around a reset-set (RS) flip-flop (see Recipe 15.4). This flip-flop has an output that will become high if the S input goes high. It will then stay high until the flip-flop is reset, either by R becoming high or R1 becoming low. The output of the flip-flop drives both a push-pull output stage (Recipe 11.8) connected to the OUT pin and an open-collector output connected to pin DISCH, which is used to discharge a timing capacitor.
Setting and resetting the flip-flop is achieved by using an arrangement of three resistors in a voltage divider from the positive supply (VCC) to GND and two comparitors (Recipe 17.10). If the voltage at TRIG falls below ⅓ of the supply voltage, the lower comparitor sets the flip-flop until the voltage at THRES exceeds ⅔ of the supply voltage and the flip-flop is reset.
The CONT (control) pin is not generally used, but it can be used to adjust the comparitor-threshold voltages. You will also often find schematics where a 10nF capacitor is connected between CONT and GND. This is an additional decoupling capacitor that can improve the oscillator stability, but is by no means essential.
In addition to the standard NE555 timer, a number of variations of the device have been developed. The NE556 is simply a 14-pin IC package that has two NE555 timers in it sharing common supply pins.
The LMC555 is a CMOS version of the 555 timer that is pin compatible and will operate down to 1.5V supply.
You can find the datasheet for the NE555 here: http://www.ti.com/lit/ds/symlink/ne555.pdf and the datasheet for the 555 here: http://www.ti.com/lit/ds/symlink/lmc555.pdf.
Figure 16-11 is taken from an informative Wikipedia page on the 555 timer: https://en.wikipedia.org/wiki/555_timer_IC.
Figure 16-12 shows an NE555 timer configured as a one-shot (monostable) timer.
When SW1 is pressed, OUT becomes HIGH and stays HIGH until either SW2 is pressed (to cancel the timer) or a period of time 1.1 x R1 x C1 has elapsed.
For example, a value of C1 of 100µF and R1 of 100kΩ will give a delay of:
1.1 x 100µ x 100k = 11 seconds
In this timer circuit to achieve timings of a second or more, you need to use an electrolytic of 100µF or greater.
You can, of course, make R1 a variable resistor, or more likely a fixed resistor and variable resistor in series in order to set a minimum delay.
For other 555 timer recipes see Recipe 16.5, Recipe 16.6, Recipe 16.8, Recipe 16.9, and Recipe 16.10.
Use an NE555 timer as shown in Figure 16-13.
For a PWM frequency of around 1kHz, use a value for R1 of 270Ω, R2 a 10kΩ pot, and C1 100nF.
The NE555 timer output can drive about 200mA, which is only sufficient for a pretty small motor. Drawing more current than this will cause the IC to overheat and eventually fail. To drive a higher power motor, use a transistor as described in Recipe 13.2.
The minimum duty cycle of this circuit depends on the ratio of R1 to R2. R1 should be considerably lower than R2 to minimize the duty cycle, but R1 cannot be 0Ω or the oscillations will stop. A ratio of 40:1 is sufficient to ensure the minimum duty cycle is just 3–4%.
Figure 16-14 shows the minimum duty cycle with the knob of R2 at one end of its travel, Figure 16-15 shows a 50% duty cycle, and Figure 16-16 the maximum duty cycle.
To use PWM outputs from an Arduino or Raspberry Pi, see Recipe 13.2.
Use an NE555 timer in the configuration shown in Figure 16-17.
The analog signal must be between 0 and VCC and is applied to the CONT (control) pin of the IC. The Clock signal should be at the modulation frequency and can be provided by another NE555 timer in a stable configuration as described in Recipe 16.5. Rather than using a separate chip to provide the clock, you can use an NE556, which contains the equivalent of two NE555s in one package.
The NE555 is configured as a monostable whose pulse length is determined by R1, C1, and the voltage at CONT. This monostable fires every time the TRIG pin pulses in response to the modulation clock.
R1 and C1 set the maximum pulse length, which should be timed to be one wavelength of the clock.
For example, if the clock frequency is 30kHz, the period length is:
1/30k = 33.3µs
The maximum pulse length Tmax (see Recipe 16.7) is:
Tmax = 1.1 R1 C1
So, an R1 of 470Ω and a C1 of 100nF would give a Tmax of:
1.1 × 270 × 100n = 29.7µs
This would allow the full voltage range of 0 to 5V to be modulated as PWM.
The use of two NE555 ICs (or a single NE556) configured as an oscillator providing a clock with the second configured as a monostable is an alternative to Recipe 16.8 for using PWM top-control power to a load. In such a case, the CONT pin could be connected to the slider of a pot connected between 5V and GND to control the pulse width.
Creating a PWM output signal is the first step in class-D digital amplification (see Recipe 18.5).
To control power to say a motor or other load, see Recipe 16.8.
Use an NE555 configured as an astable and use the CONT pin voltage to control the switching thresholds and hence the frequency. This arrangement is shown in Figure 16-18.
VCOs are standard building blocks in analog audio synthesizers, where the output of a low-frequency oscillator can be used to modulate the audio frequency of a VCO.
This VCO design operates over a fairly limited range of frequencies. Using a 5V supply and values of R1 = 1kΩ, R2 = 10kΩ, and C1 = 10nF the plot of Figure 16-19 shows how the frequency varies with the control voltage.
The useful control voltage range is between about 3 and 5V in this example. Oscillation stopped completely below 1.8V.
For the use of a VCO in an FM transmitter, see Recipe 19.1.
The term “decibel” is not strictly speaking a unit of anything, but rather a way of expressing ratios that is suitable for properties such as sound whose perception by humans is logorithmic. That is, for a sound signal to sound a little bit louder, you might need to double the amplitude (voltage).
That is why a 1W amplifier can provide a reasonable volume of sound, but if you need more volume, then rather than take the next step to 2W of output power, you might jump straight to 10W and then on to 100W.
A positive value of dB represents amplification of a signal and a negative dB attenuation (reduction in amplitude) of a signal.
A gain expressed in dB can either apply to voltage (amplitude) or to power, the power being proportional to the amplitude squared. The unit dB is most commonly used with amplitude, in which case the gain is as follows (log is log to the base 10):
Figure 16-20 shows various common ratios and the dB equivalents.
A gain of 0dB means the output is exactly the same amplitude as the input. A gain of +6dB means a doubling of the amplitude and –6dB an attenuation of the signal by half.
Table 16-3 shows some common dB ratios and what they mean in terms of amplification or attenuation of both amplitude (voltage) and power.
| dB | Amplitude (Voltage) | Power |
|---|---|---|
| 100 | gain of 100,000 | gain of 10,000,000,000 |
| 80 | gain of 10,000 | gain of 100,000,000 |
| 60 | gain of 1,000 | gain of 1,000,000 |
| 40 | gain of 100 | gain of 10,000 |
| 20 | gain of 10 | gain of 100 |
| 10 | gain of 3.162 | gain of 10 |
| 6 | gain of approx. 2 | gain of 3.981 |
| 3 | gain of 1.413 | gain of approx. 2 |
| 0 | no change | no change |
| –3 | attenuation of 1.413 | attenuation of approx. 2 |
| –6 | attenuation of approx. 2 | attenuation of 3.981 |
| –10 | attenuation of 3.162 | attenuation of 10 |
| –20 | attenuation of 10 | attenuation of 100 |
| –40 | attenuation of 100 | attenuation of 10,000 |
| –60 | attenuation of 1,000 | attenuation of 1,000,000 |
| –80 | attenuation of 10,000 | attenuation of 100,000,000 |
| –100 | attenuation of 100,000 | attenuation of 10,000,000,000 |
Wikipedia has a useful description of decibels as a unit of gain at http://bit.ly/2lPeant.
Operational amplifiers, or more commonly known as op-amps, have a helpful way of making theory easy to implement. If you need to make a filter or preamplifier, an op-amp is often the best solution.
An op-amp has two inputs and one output and is represented in schematic diagrams (Figure 17-1) as a triangle with the output coming from one apex and the two inputs labeled + and – on the opposite side. They also need positive and negative power connections. They are available in a variety of IC packages with 5, 6, or 8 pins. ICs are also available that contain two or four op-amps in a single package.
Op-amps amplify the difference between the + and – inputs. The gain of an amplifier will generally be millions or even billions. So the output voltage may be 1,000,000 times the difference between the input voltages. Such a high gain may sound desirable, but it is actually too high to do anything useful with. To reduce the gain to a more manageable level, an op-amp is almost always used with negative feedback where some of the output is fed back to the negative input. You will find examples of using feedback in this way in Recipe 17.4 and Recipe 17.5. In Recipe 17.6 you will see how if all of the output is fed back to the negative input the output will follow the positive input to the op-amp rather like the emitter-follower described in Recipe 16.4.
Traditionally op-amps are powered with a split power supply that has positive and negative supply voltages (Recipe 17.2) in addition to GND in the middle. However, the prevelance of microcontrollers with single 3.3V or 5V supplies has led to many op-amps being capable of single-supply operation (Recipe 17.3).
An op-amp IC is much better than a discrete-transistor design in most situations, providing a lower component count and generally excellent performance. Special types of op-amps are available for different power supply, frequency, and noise requirements.
Here I have tried to simplify this enormous choice to a small set of readily available devices to suit all applications.
Factors that you need to consider include:
A good selection of devices to start from are listed in Table 17-1.
| LM741 | LM321 | TLV2770 | OPA365 | |
|---|---|---|---|---|
| Description | Perhaps the longest-lived and most popular op-amp. | A good high-supply voltage device capable of single-supply operation. | A single-supply low-voltage device with a standby, low-current mode. | A high-performance, low-voltage, low-noise device. SMD only. |
| Guide cost | $0.50 | $0.70 | $2 | $2 |
| Supply voltage range | ±10–22V | 3–30V | 2.5–5.5V | 2.2–5.5V |
| Rail to rail | N | N | Y | Y |
| Gain bandwidth product | 1MHz | 1MHz | 5.1MHz | 50MHz |
| Slew rate | 0.5V/µs | 0.4V/µs | 10V/µs | 25V/µs |
| Common mode rejection | 96dB | 85dB | 86dB | 120dB |
| Noise (nV/√Hz) | Not specified | 40 | 17 | 4.5 |
| Supply current | 1.7mA | 0.7mA | 1mA (1µA standby) | 4.6mA |
| Output current | 25mA | 20mA | 50mA | 65mA |
| Dual-amp package | LM747 | LM358 | TLV2773 | OPA2385 |
| Quad-amp package | LM148 | LM324 | TLV2775 | Not available |
There will be times when you need to step out from the selections in Table 17-1 for some particular application. Perhaps you need an op-amp that works at high frequencies, but has a high upper supply voltage. In such cases, there will almost certainly be a device that fits the niche, but to find it, you will need to do some searching on the internet for recommendations and then carefully inspect the datasheets.
Note that not all op-amps have the same pinout. See Appendix A for pinouts for the op-amps described in this recipe.
Take a look at the datasheets for the op-amps featured in this recipe:
You will also find an op-amp used in Recipe 18.3.
Use a regulated supply or batteries, or both. In any case, use a linear voltage regulator rather than a switching regulator. The current consumption of an op-amp is low enough that power-supply efficiency does not need to be considered.
If you are operating the op-amp with a split power supply, you can use positive and negative versions of a linear regulator as shown in the ±12V supply shown in Figure 17-2.
Op-amps benefit greatly from the use of decoupling capacitors (see Recipe 15.1). If you have an undemanding application, a single 100nF capacitor placed close to the op-amp IC will be just fine. For more demanding applications where you have a lot of gain, it is common to use both a 100nF and 10µF capacitor next to each other and close to the IC body.
The positive side of the supply is as described in Recipe 7.4, but in this case, in addition to a 78L12 (L for low-power) to regulate the positive side of the supply, a 79L12 negative voltage regulator is used to regulate the negative side of the supply.
Although a split supply like this is quite common in audio and scientific instruments, in general, it is more convenient to use a single supply as described in Recipe 17.3.
Figure 17-3 shows a common way of providing a 5V regulated supply and a 2.5V reference voltage using a voltage divider and capacitor. The capacitor C3 stabilizes the voltage further, making it less likely to be influenced by changes in the current flowing through the reference voltage.
As you will see in Recipe 17.4 and Recipe 17.5 nearly all op-amp circuits need this middle reference voltage to provide negative feedback to reduce the op-amp’s gain.
To improve this and provide a stable center voltage use a voltage divider and capacitor with a unity gain buffer as described in Recipe 17.6. If you have a design that uses several op-amps, you will often find that there is a “spare” op-amp in a quad op-amp package that can be used for this purpose.
To power an op-amp using a split-voltage supply, see Recipe 17.2.
Connect up your op-amp as shown in the schematic in Figure 17-4, which shows the arrangement assuming a split ±12V supply.
Without any feedback from the output of an op-amp to its input, the gain of the op-amp will be millions or billions, which is far too high to do anything useful other than amplify noise. This circuit uses R1 and R2 to reduce the gain of the op-amp to a reasonable level. A reasonable level is a factor between 10 and 10,000. If you need more gain than this, you will need to use multiple stages of amplification as well as some filtering to avoid amplifying unwanted noise.
The voltage gain of the circuit is set by the formula:
So if we want our amplifier to have a gain of –10 (times 10 but inverted), we could choose a value for R2 of 10kΩ and of R1 of 1kΩ. That way when we put +1V at IN, OUT would have a voltage of –10V. Conversely, if we put –0.1V at IN, OUT would be +1V.
If you want to use a single 5V supply, the same principle applies, but now the amplification takes place relative to the center voltage of 2.5V. Figure 17-5 shows the schematic for using a 5V regulated supply with an OPA365 rail-to-rail single-supply op-amp.
With single-supply operation, the voltage at IN must be between 0 and 5V and the amplification is relative to the center voltage of 2.5V. This means that if the voltage at IN is 2.5V then OUT will also be 2.5V, but if IN is 2.6V (0.1V higher than 2.5V) then OUT will be at 1.5V (1V less than 2.5V).
So, the formula to calculate Vout for any given Vin in the schematic in Figure 17-5 is:
No matter what the gain of your amplifier is, the op-amp’s output cannot exceed that of the supply voltages. A rail-to-rail op-amp will allow the voltage to swing from one supply to another but not beyond, but a non–rail-to-rail type op-amp may only allow you to get within a volt or two of the supply voltages.
Recipe 17.5 shows a noninverting op-amp configuration.
Use an op-amp in the noninverting configuration of Figure 17-6.
In this case, the gain of the amplifier is given by the formula:
If we used a 10kΩ resistor as R2 and a 1kΩ resistor as R1, the gain would be 11. In other words, the voltage at OUT would be 11 times the voltage at IN. If the voltage at IN is negative, the voltage at OUT will also be negative.
In the case of single-supply operation of the amplifier, let’s say 5V, we have the same 2.5V offset to contend with as we did in Recipe 17.4. Figure 17-7 shows how you might build a single-supply noninverting amplifier.
In this case, the gain is still:
And the output voltage is related to the input voltage by the equation:
The amplifiers described thus far are capable of amplifying both a DC signal (say from a sensor) and AC-changing signals (perhaps an audio signal). A single-supply 5V (or even 3.3V) design like this is ideally suited to connecting the output to the analog input of a microcontroller, as the voltage can swing between 0V and the supply voltage. In such cases, it is conceptually easier to deal with amplification of a voltage without the added complication of the amplified voltage being inverted about 2.5V, so it is more common to use this noninverting recipe in single-supply designs.
See Recipe 17.4 for inverting amplifier designs.
Configure the op-amp as shown in Figure 17-8.
The output voltage will track the input voltage. So if the input is 1V, the output will also be 1V. You can then hang whatever load you like off the output, without worrying too much about it affecting the input.
In other words, the voltage is not being amplified but the current that can pass through a load is greatly increased. An example where this might be used is as a headphone amplifier where the signal voltage is high enough in theory to drive the headphones, but the output would not otherwise be sufficient to power the low impedance of the headphones.
One situation where a buffer like this can be used is to provide the center voltage for a single-supply op-amp amplifier. Figure 17-9 shows a 5V single supply amplifier modified from Figure 17-7 to use a buffer in this way.
Because the input impedance to the buffer is very high, the value of C3 can be reduced as very little current at all will be flowing out of it. Think of it as reducing ripple on an unloaded power supply.
Another way to think of the action of a unity gain buffer is as a current amplifier, which is like using a bipolar transistor in an emitter-follower configuration in Recipe 16.4.
You want a low-pass filter to reduce the amplitude of high frequencies, but you need it to have a steeper cutoff than the simple RC filter of Recipe 16.3.
Use an op-amp and a 2-pole filter.
As an example, let’s say we want to revisit the crude filter you saw in Recipe 16.3 designed to separate a 440Hz signal from a 32.7kHz PWM carrier frequency. In that simple RC filter, we ended up with a corner frequency of 1.786kHz and saw that there would be a halving of signal amplitude for each doubling of the frequency. This resulted in a reduction in the amplitude of about a factor of 16 at 32kHz. By using an active filter, the attenuation (fall-off) at 32kHz can be improved to a factor of 100 easily.
When selecting component values for R1, R2, and C2, you can do a whole load of complicated math by hand, or you can use a filter design tool. In this recipe, we will use the Analog Filter Wizard provided by the chip manufacturer Analog Devices available as an online tool at http://www.analog.com/designtools/en/filterwizard/.
When you navigate to that page in your browser, you will be offered the choice of low-pass, high-pass, or band-pass. When you select low-pass, you will be given the opportunity to specify the corner frequency and other parameters for the filter as shown in Figure 17-10.
The tool is by default configured to work in units of dB (see Recipe 16.11). You can change this to just the amplitude voltage as a ratio by changing the drop-down lists under Passband and next to View to both be V/V as shown in Figure 17-10, where the corner frequency has been set to 1.78kHz and the desired stop-band set to –40dB (factor of 1/100) at 32kHz.
Use the filter-response slider to determine just how steep the curve will be as well as how flat the pass-band’s response is. This will also alter the number of op-amps needed for the design (stages) and the order of the filter. A single op-amp can implement a second-order filter. More orders than that and you will need to chain together several op-amps. The filter type (Butterworth, Chebyshec, or Bessel) will all use the same schematic but different component values to provide different behaviors. See the discussion section for the differences.
For the sake of this example, position the slider so that the second-order Butterworth (first stage) is recommended by the tool and then click Go to Component Selection and “presto,” a schematic complete with component values will be recommended to you as shown in Figure 17-11.
You can then specify supply voltages and other properties of your design as well as look at the effect of component accuracy on the design. Since this is an Analog Devices tool, it will obviously recommend the op-amps they manufacture, but the designs can be used with other manufacturers’ op-amps.
There is nothing to stop you from adding some gain to your filter so that it both filters and amplifies by replacing the connection from the op-amp output to the negative input with a pair of resistors as used in the noninverting amplifier design of Recipe 17.5. In fact, the design tool does allow you to specify a gain when you are specifying the filter (see Figure 17-10).
Unless you have a particularly demanding project, a second-order filter using a single op-amp will generally provide a good balance between complexity and performance. There are whole books written on filter design and other more complex filter design tools.
The properties of the three filter types offered by the Analog Filter Wizard are:
These types are all implemented using the same schematic in Figure 17-11; the calculations performed by the Analog Filter Wizard determine the type of filter.
For other types of filter designs, see the next few recipes.
Use a second-order filter implemented using a single op-amp and design it using a design tool such as the Analog Filter Wizard. Figure 17-12 shows the frequency response of a filter designed by the Analog Filter Wizard to provide high-pass filtering with a gain of 10 and a corner frequency of 1kHz.
Notice that there is a little “hump” in the response between 2kHz and 3kHz where the gain goes above the desired value of 10. This is called overshoot and is another characteristic of Chebyshev filters.
The corresponding schematic for this filter is shown in Figure 17-13.
Most of the things said in the discussion section of Recipe 17.7, especially about the different types of filters, apply equally well to high-pass filters.
Notice that in Figure 17-13 the Analog Filter Wizard has also helpfully suggested the necessary bypass capacitor values (Recipe 15.1).
For a low-pass filter see Recipe 17.7 and for a band-pass filter see Recipe 17.9.
If the band of frequencies you are interested in is reasonably wide, then the best solution is to simply pass the signal through a low-pass filter (Recipe 17.7) and then a high-pass filter (Recipe 17.8.) This will require two op-amps, but then dual op-amp ICs are not much more expensive than single op-amp ICs.
Figure 17-14 shows the schematic for a band-pass filter with corner frequencies of 20Hz and 20kHz, which might be used to restrict a signal to the audio-frequency range.
The filter was designed using the Analog Filter Wizard used in Recipe 17.7 and Recipe 17.8. This time the filter type of Band-pass is selected and the parameters entered as shown in Figure 17-15.
The pass-band is set to 20kHz for a 3dB drop in amplitude (0.71 of the original amplitude) and the stop-band to 100kHz at the high end where we are aiming for attenuation of 20dB (0.1 of original signal amplitude).
The center frequency is not the 10kHz that you might expect but rather the square root of the product of the upper- and lower-corner frequencies. In other words:
Filter design is a specialized field, and in this book, there is only room to look at the most common electronics recipes. However, for many applications a simple design that uses a single op-amp stage will be perfectly adequate.
For low-pass active filter design see Recipe 17.7 and for high-pass filter design see Recipe 17.8.
Use a device closely related to the op-amp called a comparator. Figure 17-16 shows how you could make a simple automatic light that turns on an LED when the light level falls below a certain threshold.
R1 and R3 form a voltage divider whose output corresponds to the light level; that is, the higher the volate, the higher the light level. The variable resistor R2 is used to set the reference voltage at IN–.
The output of the LM311 provides optimal flexibility by providing connections to both the emitter and collector of the NPN output transistor.
If the light level is low enough for IN+ to be lower than IN– the base of the output transistor is supplied with current, and since the emitter is grounded, the transistor turns on and current flows through the LED.
This logic of the transistor being on if IN+ is lower than IN– would seem to be counterintuitive, but the output transistor will often have its emitter grounded and the logic output taken from the collector, which is pulled up to VCC. This effectively acts as an inverter and hence the collector output will be high if IN+ is greater than IN–.
To sense light using an Arduino, see Recipe 12.3 and for a Raspberry Pi Recipe 12.6.
Audio electronics is all about generating signals and amplifying them enough to power a loudspeaker so that you can hear them.
This chapter contains a number of amplification and signal-generation recipes. Any resource that deals with audio-power amplifier design will explain the different classes of amplifiers, which are designated by A, B, AB, and D, and some other more exotic designs. For the most part, these letters designate how the amplifier is constructed from bipolar junction transistors and how they are biased. Since these days there is no real cost or even quality advantage (apart from the most demanding audiophile) to building an amplifier from separate transistors rather than just using an IC, I feel it is only necessary here to highlight the most common designs along with their main characteristics:
Before launching into the construction of your own amplifier designs, think about whether you need to build the amplifier from scratch. For most one-off projects, it is easier and cheaper to use ready-made modules or even USB-powered amplified speakers.
When it comes to generating sound waves from an Arduino, you can easily generate tones. The Raspberry Pi with its large amount of memory and sophisticated hardware allows MP3 and other sounds files to be played through its audio jack, which can then be connected to an external amplifier.
You can experiment with generating tones and driving a speaker from an Arduino if you connect a speaker to an Arduino as shown in Figure 18-1.
The sketch ch_18_speaker can be found with the downloads for the book (see Recipe 10.2):
constintoutputPin=10;voidsetup(){pinMode(outputPin,OUTPUT);Serial.begin(9600);Serial.println("Enter frequency 100-8000 Hz (0 off)");}voidloop(){if(Serial.available()){intf=Serial.parseInt();if(f==0){noTone(outputPin);}else{tone(outputPin,f);}}}
The Arduino tone function takes two parameters, the pin to generate a tone on and the frequency of the tone to generate as a long integer value. The tone function can generate frequencies from 31Hz to 65,535Hz.
To use it, open the Arduino Serial Monitor and make sure you have the Line Ending drop-down list set to “No line ending” then type in a frequency in Hz and click Send.
The 5V signal generated by the tone command is a little too high a voltage to feed directly into an amplifier. It should be reduced to below 2V or so using a pair of resistors as a voltage divider. 1kΩ and 270Ω resistors with the 270Ω resistor to GND will reduce the output by a factor of about 5.
A loudspeaker is an inductive load, so, like the coil of a relay, there is a risk of voltage spikes arising that could damage the GPIO pin driving the speaker. In reality, when using a small speaker driven through a resistor, these spikes will be sufficiently low in energy for the antistatic protection of the GPIO pin to take care of them.
Making crude square-wave buzzing has its place, but the Arduino is actually capable of more sophisticated sound generation using the Mozzi library, which uses a high-frequency PWM signal at 32.7kHz to generate the sound file using PWM.
To try out Mozzi and hear the difference between the square and sinewaves, install the Mozzi library and then run the example program included with the Mozzi library 01. Basics→Sinewave.
You will need to change the connection to R1 from Arduino pin 10 to pin 9 that is used by Mozzi.
If you want to know how Mozzi sounds are generated skip ahead to Recipe 18.1.
For using a voltage divider, see Recipe 2.6.
For oscillator recipes that do not require an Arduino, see Recipe 16.2, Recipe 16.5, and Recipe 16.6.
To generate better-sounding audio from an Arduino, take a look at the Arduino Mozzi library.
When it comes to hardware, most models of Raspberry Pi have a 3.5mm headphone-style jack socket that can be attached to a stereo amplifier and speakers.
In recent versions of Raspbian, you will find the OMXPlayer preinstalled. To play a sound file, you just need to name the sound file you want to play OMXPlayer. For example:
$ omxplayer file.mp3
If you need to play the sound file from within a Python program you can use the os.system command to run OMXPlayer, as follows:
importosos.system('omxplayer file.mp3')
In addition to the headphone jack, sound can also be played through the HDMI connector. The OMXPlayer software should automatically play through HDMI unless the audio jack has something plugged into it.
You can choose the channel the sound should be played through by using the -o option, which can have a value of either local (audio socket) or hdmi. For example:
$ omxplayer -o hdmi file.mp3
You can find out more about the OMXPlayer here: http://elinux.org/Omxplayer. In addition to sound files in most formats, the player can also play video files.
For an alternative method of playing sound files using the Pygame library, see http://bit.ly/2mt4eDM.
The Raspberry Pi Zero does not have an audio jack, but you can still use it to play audio; see http://bit.ly/2mIjZH9 for details.
Use a single-supply rail-to-rail op-amp like the OPA365 and amplify the signal by a factor of between 30 and 100. A gain of 30 is about right if you will be speaking directly into the microphone and 100 if you want the microphone to be useful in picking up ambient sounds.
Figure 18-3 shows the schematic for the microphone preamp with a gain of 101. For a discussion of how to set the gain, see Recipe 17.5.
C1 is used to “AC couple” the weak output from the microphone to the noninverting input of the op-amp. It allows only the AC part of the signal from the mic, rejecting the DC bias that would otherwise be present.
Electret microphones operate like capacitors. Sound waves effectively move one plate of the capacitor closer or further away. The plates of the electret are charged during manufacture and retain that charge for the life of the microphone. These changes in capacitance are converted into a small voltage using an FET transistor built into the microphone. The microphone module is polarized and must be connected the right way around. You also need to supply a drain resistor for the FET (R5 in Figure 18-3).
The circuit of Figure 18-3 will produce an output centered around 2.5V that can be connected directly to an Arduino’s analog input and allow you to do things like measure the maximum sound level.
Figure 18-4 shows the circuit used with an Arduino Uno.
This circuit can be built on a breadboard, but the OPA365 is only available as an SMD, so you will need to use a SOT-23 or SOIC breakout board such as the one from Schmartboard.com, as shown in Figure 18-5.
The Arduino sketch ch_18_sound_meter (see Recipe 10.2) samples the analog input A0 for 100ms and then reports on the maximum amplitude it sampled (Figure 18-6). You could modify this sketch to trigger some action if the sound level rises above a certain level.
Note that the maximum possible reading will be 512 (half the full analog value reading):
constintsoundPin=A0;constlongsamplePeriod=100;// mslonglastSampleTime=0;intmaxAmplitude=0;intn=0;voidsetup(){Serial.begin(9600);}voidloop(){longnow=millis();if(now>lastSampleTime+samplePeriod){processSoundLevel();n=0;maxAmplitude=0;lastSampleTime=now;}else{intamplitude=analogRead(soundPin)-512;if(amplitude>maxAmplitude){maxAmplitude=amplitude;}n++;}}voidprocessSoundLevel(){// replace or add your own code to use maxAmplitudeSerial.("Of ");Serial.(n);Serial.(" samples, the maximum was ");Serial.println(maxAmplitude);}
Ready-made microphone preamplifier modules are available that use electret microphones, for example: https://www.sparkfun.com/products/12758.
Alternatively, you can use the type of microphone found in cellphones called MEMS (microelectromechanical systems). These are essentially microphones on a chip. SparkFun and others sell breakout boards for these extremely tiny microphones, such as this one: https://www.sparkfun.com/products/9868.
For information on using analog inputs with an Arduino, see Recipe 10.12.
You need a low-cost power amplifier to power a small speaker at low volumes, say to accompany an FM radio receiver as in Recipe 19.3.
Use a power-amp IC like the TDA7052, which will work with any power supply from 3V to 15V and can supply 1W of power into an 8Ω speaker. The schematic for a simple amplifier using this device is shown in Figure 18-7.
R1 and R2 are only provided to show how to mix the left and right signals of a stereo audio source to mono. If you have a mono source, just connect it directly to C3.
R3 acts as a volume control, and if the sound source has a volume control, you can replace this with two fixed resistors acting as a voltage divider.
C1 and C2 provide energy stores for the rapidly changing load of the IC as it drives the speaker. C1 should be placed as close to IC1 as possible.
Figure 18-8 shows how you can build an amplifier like this on a solderless breadboard. In this case, the breadboard is stuck to a Monk Makes Protoboard for the convenience of being able to attach the speaker to screw terminals and use the audio jack and power jack.
1W is not very powerful compared with the 20W or more you will generally find in a home stereo system. An amplifier is generally considered a “power” amp if it has enough current amplification to drive a low impedance load (i.e., 4 or 8Ω loudspeakers).
The TDA7052 datasheet can be found here: http://bit.ly/2nA0GgB.
For high-power class-D design, see Recipe 18.5.
Use a class-D digital amplifier IC such as the TPA3122D2. The schematic for this is shown in Figure 18-9.
This design is a modified version of the one found on page 14 of this chip’s datasheet. It will operate on a supply voltage of 10 to 30V, but at a convenient 12V will supply about 7.5W per channel into 4Ω speakers. For more power you need to increase the supply voltage.
The TPA3122D2 is a 20-pin DIL (dual in-line) IC that makes the design very suitable for prototyping on a breadboard (Figure 18-10).
One interesting feature of the TPA3122D2 is that the gain is set by two digital inputs that set the gain to one of four values. Table 18-1 shows how these pins are used. In the schematic of Figure 18-9 the lowest gain of 20dB is selected.
| GAIN1 | GAIN0 | Amplifier gain (dB) |
|---|---|---|
| LOW | LOW | 20 |
| LOW | HIGH | 26 |
| HIGH | LOW | 32 |
| HIGH | HIGH | 36 |
Unlike traditional amplifier designs like that of Recipe 18.4 class-D amplifiers are extremely efficient, transferring sometimes over 90% of the power supplied to them to the output load (loudspeaker).
Figure 18-11 shows how a class-D amplifier works.
The input signal is converted into high-frequency PWM (250kHz in the case of the TPA3122D2) by a combination of a triangle-wave generator and comparator. This is actually the way Recipe 16.9 works. The length of the pulse will be determined by the time it takes for the triangular signal to exceed the value of the analog input. Since the analog input is a much lower frequency than the triangle wave, it can be considered as having a constant instantaneous value, while the triangle wave is “sampling” it. It’s a bit like driving fast past someone who is walking—the pedestrian is effectively stationary from the car’s perspective.
This PWM signal can then be amplified by transistors in a half-bridge switching arrangement such as the one in Recipe 11.8. This is then low-pass filtered and fed to the loudspeaker.
Digital amplifiers are perfectly acceptable for many applications, but they are unlikely to be accepted by HiFi enthusiasts without considerable improvements in design. They generally have higher levels of distortion than analog amplifiers. In Figure 18-12 you can clearly see the distortion in the sinewave being amplified.
For the TPA3122D2 datasheet see http://www.ti.com/lit/ds/symlink/tpa3122d2.pdf.
It used to be that any electronics book worth its salt would include discrete circuits for AM and FM broadcast receivers and maybe even discuss how an analog TV works. In these digital days, topics like this are only for historical interest.
For this reason, this chapter mostly concentrates on the use of digital communications using radio frequencies. The discussion of the nature of radio is restricted to this introduction. The recipes themselves are fundamentally practical.
We take radio frequency for granted now, but when it first became popular, it must have seemed like magic. After all, it allowed you to talk to someone miles away without any wires connecting them. How could this be possible?
Recipe 19.1, Recipe 19.2, and Recipe 19.4 are radio transmitters. Although most countries allow the use of low-power, short-range FM transmitters and allocate certain bands for use with packet radio, you should check your local regulations and make sure you are not breaking the law by using any of these designs.
It all starts with AM transmissions, which use a carrier frequency modulated by the audio signal that is being transmitted. Figure 19-1 shows how this works.
In Figure 19-1 the carrier frequency is only about 4.5 times the audio signal. In a real AM broadcast, the audio signal will generally be a maximum of 16kHz against a carrier frequency of 500kHz, making at least ten times as many cycles of carrier in each cycle of the audio frequency shown in Figure 19-1. But it’s easier to see what is going on with fewer cycles.
Each transmitting station has its own frequency, and for AM public broadcasts in the medium wave (MW) band, this range is around 520kHz to 1600kHz. The amplitude of the carrier is modulated by the audio signal and the resulting signal broadcast through an antenna.
One of the reasons the quality of AM is so bad is that there are many other factors that can affect the amplitude of the carrier, including atmospheric conditions or changes in position of the receiver if you are listening in a moving vehicle.
When it comes to the receiver, you need to be able to separate the radio-frequency carrier (RF) from the audio signal.
The first step in this is to “tune in” to the transmission frequency you are interested in. This means using a narrow band-pass filter (Recipe 17.9) so that all the other stations get tuned out. This is traditionally accomplished by using a tuned circuit in the form of a fixed inductor (also acting as the antenna) and a variable capacitor that is varied to tune into different frequencies.
Since your ears cannot hear frequencies above 20kHz (lower as you get older) a radio carrier frequency of 500kHz or more will be inaudible. With your ears acting as a low-pass filter, you might expect that with suitable amplification of the tuned radio signal, you would be able to hear the audio signal modulating it. This is almost correct, but because the “average” of each cycle (whatever the amplitude) is zero (each positive wave followed by a negative one), you won’t hear anything. However, if you introduce a diode to remove one half of the signal (Figure 19-2), then suddenly the original audio signal can be separated and you will be able to hear the audio in the envelope of the AM signal and your ears will now happily be a low-pass filter for you.
The big empty space on the bottom of Figure 19-2 serves to show where the diode has removed the negative part of the tuned signal.
The earliest AM receivers (crystal sets) were literally a coil, antenna, variable capacitor, diode (germanium for its lower forward voltage), and sensitive headphones as shown in Figure 19-3.
Improvements have been made to the design of AM receivers, in particular amplification of the RF signal before detection, followed by further amplification to drive a loudspeaker, but the basic principles of an AM receiver are as they were a century ago.
Frequency modulation (FM) improves on AM by varying the frequency of the carrier rather than its amplitude. This improves the quality of the sound being broadcast, as the frequency is immune from changes due to atmospheric conditions or movement of the receiver. Figure 19-4 shows how an audio signal would be used to modulate a carrier.
To create an FM transmitter, a VCO (Recipe 16.10) is used. The audio signal is fed into the frequency control input of the VCO to vary the frequency. The first recipe in this chapter (Recipe 19.1) is a simple, low-power FM transmitter.
Extracting the audio signal from an FM broadcast can be accomplished by using a number of techniques, but perhaps the most common is to use a VCO in an arrangement called a phase-locked-loop (PLL). Figure 19-5 shows a PLL configured as an FM demodulator.
The RF signal is first tuned to a particular frequency as with an AM receiver, but then to demodulate the original audio, the RF signal is fed into a phase comparator. The phase comparator produces an output that is zero if its two input signals are completely in phase. If the signals are out of phase with each other then the comparator produces an output proportional to the difference in phase. This signal is then low-pass filtered, amplified, and used to control a VCO whose output supplies the second input to the phase comparator. This feedback results in the VCO producing a signal of the same frequency as the RF input to the phase comparator. As the output of the VCO tracks the RF frequencies the small shifts in phase resulting from the modulation will result in the audio signal being available in the filtered and amplified output of the phase detector. The amplified output contains the demodulated audio signal almost as a side effect of the PLL tracking the broadcast signal.
PLL chips are available that include the VCO, phase comparator, and other parts all in one convenient package. However, if you are making an FM receiver, then you would just use an FM receiver IC that includes the RF amplification, PLL, and pretty much everything needed for the receiver aside from a few resistors, capacitors, and inductors.
Radio is now very much a digital affair. FM radio receivers and transmitters are now often implemented as software-defined radios (SDRs). Processors are now so fast that with a very small amount of hardware they can produce and decode analog broadcast signals in software. For example, the filtering, phase detecting, etc. of a PLL can all be done as software algorithms rather than directly in hardware. In Recipe 19.2 you will find a recipe for a SDR FM transmitter using a Raspberry Pi.
In addition to using digital electronics to decode analog signals, the use of digital signals carried on RF is everywhere from your cellphone to the remote you use to unlock your car.
This chapter has several recipes for passing digital data wirelessly between devices.
Use a high-frequency VCO chip (MAX2606) set to operate in a frequency on the FM band and use the audio signal to make small adjustments to the frequency.
The schematic for this is shown in Figure 19-6.
The variable resistor R4 is used to tune the transmitter to a particular frequency. The antenna can be a telescopic FM antenna or simply a few feet of wire.
The inductor L1 sets the center frequency of the VCO. The datasheet for this device indicates that an inductor of 390nH will give a center frequency of around 102MHz.
The control signal applied to the TUNE pin of the VCO comprises a fixed DC offset supplied by R4 (to allow tuning to a particular transmission frequency) and an audio signal that is sufficient to produce the desired frequency modulation.
The output OUT+ of the MAX2606 drives the antenna. The datasheet also suggests that complementary open-collector output OUT– is also supplied with a 1kΩ pull-up resistor.
This recipe is based on the tutorial by Afroman who also has an open source hardware circuit board that you can make yourself or buy from OSHPark.
The datasheet for the MAX2606 can be found at http://bit.ly/2ltwp5O.
Use the PiFM software and attach an antenna to GPIO pin 4 of your Raspberry Pi. This can be just a female-to-male jumper wire as shown in Figure 19-7.
First, you’ll need to download and install PiFM using the following commands:
$ mkdir pifm $ cd pifm $ wget http://omattos.com/pifm.tar.gz $ tar -xvf pifm.tar.gz
If you have a Raspberry Pi 2 or 3, you have to download and compile a modified version of the software to work on the newer hardware, so run the following commands:
$ git clone https://github.com/oatmeal3000/pi2fm.git $ mv pi2fm pi2fmdir $ mv pi2fmdir/pi2fm.c . $ gcc -lm -std=c99 -g pi2fm.c -o pi2fm
You will now have two executable programs, one called pifm for the Raspberry Pi 1 models and pi2fm for the Raspberry Pi 2 and 3. If you have an original Pi 1 you will need to modify pi2fm to be just pifm in the following commands, which will play the file sound.wav supplied with the pifm software:
pi@raspberrypi:~/pifm $ sudo ./pi2fm sound.wav 94.0 starting... -> carrier freq: 94.0 MHz -> band width: 8.0 now broadcasting: sound.wav ...
Attaching a longer wire to pin 4 will considerably increase the range of the transmitter.
The original web page for the PiFM project can be found here: http://bit.ly/18AcT5u.
Details on the Raspberry Pi 2 version are here: https://github.com/oatmeal3000/pi2fm.
Use a TEA5767 FM radio-receiver module controlled by an Arduino and either connect headphones or use a power amplifier to drive speakers.
Figure 19-8 shows how the module is connected to an Arduino.
To make the module as easy to program as possible, download the Arduino TEA5767 library by clicking on Clone or download on GitHub. Select the option to download as a ZIP file and then from the Arduino IDE select the menu option Sketch→Include Library→Add ZIP Library and navigate to the ZIP file you just downloaded.
To build a circuit using this module on a breadboard (Figure 19-9), you will need a breakout circuit board that allows you to connect the fine pitch of the module’s connectors to the breadboard. You can make this yourself using stripboard or buy a breakout board from OSHPark or Monk Makes.
The sketch ch_19_fm_radio uses the Serial Monitor so that you can enter the frequency you want to tune in to. When using the Serial Monitor with this sketch, make sure the “Line ending” drop-down list is set to “No line ending” before sending a frequency to the Arduino.
The sketch is available with the book downloads (see Recipe 10.2) and is listed here:
#include <Wire.h>#include <TEA5767Radio.h>TEA5767Radioradio=TEA5767Radio();voidsetup(){Serial.begin(9600);Serial.println("Enter Frequency:");Wire.begin();}voidloop(){if(Serial.available()){floatf=Serial.parseFloat();radio.setFrequency(f);Serial.println(f);}}
The setFrequency function accepts a decimal value in MHz (e.g., 93.0).
To make a suitable power amplifier for this project, see Recipe 18.4 or Recipe 18.5.
For an FM transmitter to accompany this receiver, see Recipe 19.1 or Recipe 19.2.
Use a CC1101 RF transceiver (transmitter/receiver). These boards are readily available on eBay at very low cost. Figure 19-10 shows how you would wire one up to the SPI interface of an Arduino.
The module is a 3.3V device and the datasheet states that none of the pins should have a voltage of more than 3.9V applied to them, so a level converter should be used on all pins used as inputs to the CC1101. This takes the form of six resistors used in pairs as voltage dividers (see Recipe 2.6).
Clearly to test out this recipe, you will need two Arduinos and two CC1101 modules each wired up as shown in Figure 19-11.
Testing the modules can get very confusing because the Arduino IDE can only have one port selected at a time. It’s much easier to find a second computer to use both for programming the transmitter and for running the Serial Monitor.
The library used for these examples should be downloaded as a ZIP file from https://github.com/simonmonk/CC1101_arduino by clicking on the Clone or download button and selecting Download ZIP. Save the ZIP file somewhere and then from the Sketch menu choose Sketch→Include Library→Add ZIP Library and select the ZIP you just downloaded.
The two example programs (one for transmit and one for receive) are the examples that accompany the library, but these can also be downloaded with the downloads for the book (see Recipe 10.2).
Here is the transmitter code (ch_19_cc1101_tx):
#include <ELECHOUSE_CC1101.h>constintn=61;bytebuffer[n]="";voidsetup(){Serial.begin(9600);Serial.println("Set line ending to New Line in Serial Monitor.");Serial.println("Enter Message");ELECHOUSE_cc1101.Init(F_433);// set frequency - F_433, F_868, F_965 MHz}voidloop(){if(Serial.available()){intlen=Serial.readBytesUntil('\n',buffer,n);buffer[len]='\0';Serial.println((char*)buffer);ELECHOUSE_cc1101.SendData(buffer,len);}}
The maximum packet size is 64 bytes and buffer is used to contain the data to be sent, which can by anything you can pack into a byte array. In this case, short text messages.
In the setup function, the communication frequency is set. The Serial Monitor first reminds you to turn line endings on in the Serial Monitor. When you send a message the contents of the message are written into buffer and SendData then used to transmit the message you typed.
The corresponding receiver code can be found in ch_19_cc1101_tx and is listed here:
#include <ELECHOUSE_CC1101.h>constintn=61;voidsetup(){Serial.begin(9600);Serial.println("Rx");ELECHOUSE_cc1101.Init(F_433);// set frequency - F_433, F_868, F_965 MHzELECHOUSE_cc1101.SetReceive();}bytebuffer[61]={0};voidloop(){if(ELECHOUSE_cc1101.CheckReceiveFlag()){intlen=ELECHOUSE_cc1101.ReceiveData(buffer);buffer[len]='\0';Serial.println((char*)buffer);ELECHOUSE_cc1101.SetReceive();}}
This sketch uses CheckReceiveFlag to monitor Arduino pin 2 for the CC1101 to indicate that a new message has arrived. When a message does arrive, it is read into buffer and then displayed in the Serial Monitor. Figures 19-12 and 19-13 show the Serial Monitors of the transmitter and receiver, respectively.
You can find the datasheet for the CC1101 IC here: http://bit.ly/2ltuxK9.
The library used here is modified from that of elechouse.com that also sells CC1101 modules: http://bit.ly/2n3lnQK.
Using a solderless breadboard (Figure 20-1) is a great way to temporarily build an electronic design because you can easily swap out different components without having to desolder (Recipe 20.6). Once the design is right it can be transferred either to a prototyping board (Recipe 20.2) or a circuit board of your own design (Recipe 20.3).
Breadboards are available in many shapes and sizes. I recommend having a good supply of 400-point breadboards (often called half-breadboards) as these are a great size to accommodate a couple of chips and a whole load of components. For those situations where you need more prototyping area breadboards can be clipped together.
Figure 20-2 shows how a 400-point breadboard is constructed of rows of five holes, all connected together by a clip. Note that there is a break in connectivity between “abcde” and “fghij.”
The “supply rails” in pairs down the sides of the board are all connected together and can be used for any purpose, but generally the ones marked in blue or with a “–” next to them are used for ground and the red ones marked with a “+” are used for the positive supply.
The rows and columns of the breadboard are labeled with numbers and letters, making it easier to transfer the designs to a more permanent design using Permaproto or Monk Makes Protoboard. These are general-purpose circuit boards with the same layout as breadboards.
Figure 20-3 shows the two-transistor oscillator from Recipe 16.2 built on a breadboard.
Through-hole component leads are pushed into holes on the breadboard and connected to other component leads either by being in the same breadboard row, or by using male-to-male jumper wires to link one part of the board to another.
There is a bit of craft involved in the mental conversion of a schematic to a breadboard layout. Figure 20-4 shows the schematic layout for Recipe 16.2 and Figure 20-5 the one corresponding to the breadboard layout (also shown in Figure 20-3).
When transferring a schematic to a breadboard, I start with the key components and the ones whose legs won’t bend very far. Usually this means starting with any ICs, but in this case, it means the transistors, which I have placed on opposite halves of the breadboard, mirroring the schematic.
Then I add the other components and jumper wires. There is no hard and fast method for this layout, and of course, being solderless, it’s very easy to change things around if you run out of room.
Figure 20-5 was drawn using an open source software tool called Fritzing. This tool produces great-looking diagrams and also allows you to view the same circuit as a schematic, breadboard, or circuit board design, allowing you to use the same software right through from prototyping to circuit board.
When it comes to connecting a breadboard to an Arduino or Raspberry Pi, you can use male-to-male or male-to-female jumper wires, respectively. Figure 20-6 shows Recipe 12.12 on a breadboard connected to a Raspberry Pi.
Figure 20-7 shows an Arduino Micro on a solderless breadboard. This is one of several models of Arduino including the “mini” and “nano” models that are “breadboard friendly.”
The breadboard shown in Figure 20-3 is likely to have proper electronic engineers holding their heads in their hands and gritting their teeth. The problem with it is that it is all too easy for a component lead to touch another lead that it shouldn’t or simply fall out. This type of arrangement requires care to make sure nothing is touching that shouldn’t be but is fine while you are getting something working. For a halfway house before you move to a soldered prototype, you can take a neater approach and use solid-core wire trimmed to just the right length to lie flat on the breadboard instead of using jumper wires. You can also trim all the component legs so that they are just the right lengths, but this can make them difficult to reuse in your next design.
For more information on Fritzing see http://fritzing.org or my book Fritzing for Inventors, TAB DIY, 2015.
When you are ready to transfer your design to a soldered prototype follow Recipe 20.2.
Use a prototyping board or protoboard such as the Adafruit Permaproto or the Monk Makes Protoboard and simply transfer the components from their positions on the breadboard to the same locations on the protoboard.
Figure 20-8 shows the starting point for this process of transferring the design from a breadboard to a Monk Makes Protoboard. The details of the design are not important, but for those interested, it is an energy monitor using a particle photon Arduino-like board, a current sensor, and an AC transformer. Note that the breadboard itself is attached to a Monk Makes Protoboard to allow use of the screw terminal and audio-type socket to connect the current sensor and AC transformer to the prototype.
The components can then be moved from the breadboard one at a time, making note of the lead’s row and column coordinates and soldering them onto the Monk Makes Protoboard as shown in Figure 20-9. Finally, Figure 20-10 shows the completed board and the bare breadboard ready for your next project.
Other useful prototyping boards are available including Permaproto boards from Adafruit that are designed to be attached by a ribbon connector to a Raspberry Pi.
When it comes to Arduino, the Arduino Protoshield is a great way to build something and then plug it as a whole board into the top of an Arduino Uno. Figure 20-11 shows a Protoshield with an LED cube project built onto it. The Protoshield is then attached to an Arduino.
Another popular method for making soldered prototypes is to use stripboard. Stripboard (Figure 20-12 and Figure 20-13) is arranged with copper tracks in rows and can be cut to whatever size you need for your project. Breaks in the track are made using a tool called a “spot cutter” or by using a drill bit rotated by hand just enough to cut the copper.
Perfboard (i.e., perforated board) is like stripboard, but without the copper strips on the back. All connections are made by bending the component leads or lengths of solid-core wire.
Protoboard, which is a variation on perfboard with a separate pad behind each hole, is also available.
For Permaproto see: https://www.adafruit.com/product/571.
For Monk Makes Protoboard see: https://www.monkmakes.com/pb/
The LED cube project is taken from my book The TAB Book of Arduino Projects, TAB DIY, 2015.
While the solution to this recipe cannot fit into one recipe, you can start by using circuit board design software such as CadSoft EAGLE to draw the schematic for your boards and then layout a circuit board. You can then send away the design files (known as Gerbers) to a circuit board fabrication provider.
Designing a simple circuit board is well within the reach of the amateur. If you restrict yourself to two copper layers, then you can use one of many CAD (computer-aided design) packages for circuit board design.
Perhaps the most popular CAD system is EAGLE CAD (Figure 20-14), which is not open source, but there is a free version for noncommercial projects. One advantage of using EAGLE CAD is that it has been adopted by the open source hardware movement as their CAD system of choice and there are many OSH designs for which the EAGLE design files are available for download, which you can adapt to your own needs. EAGLE is not an intuitive piece of software. If you have used any other circuit board design software, you may be able to find your way around unaided, but typically you will need to follow a few tutorials step-by-step before it really starts to make sense.
Nearly all the schematic diagrams in this book were drawn with EAGLE and once you are familiar with all its quirks, you will probably grow to enjoy using it.
For open source enthusiasts KiCad is a fully featured open source equivalent to EAGLE, and it can import some EAGLE file formats. Like EAGLE, don’t expect to have a finished board design ten minutes after downloading the software.
DesignSpark is a free-ish CAD system that is gaining in popularity and is relatively easy to use, but it does inflict adverts on users.
If you have a really simple circuit board design to make that uses fairly common components, then Fritzing will take you to circuit board design via schematic and breadboard and is easy to use. However, if you run into parts that are not included with Fritzing (and you probably will) you may well have to make your own parts, which is a little tricky and requires you to have some skill editing multilayer SVG files.
All of the CAD options described will give you the option to export Gerber design files. You can then use an online circuit board service that will let you upload a ZIP file containing the design, and in a week or two, send you back a small batch of boards. The minimum is usually 10 for as little as a dollar a board for small boards.
The circuit board services are changing all the time. I have used PCBWay, ITEAD Studio, and Seeed Studio for circuit board manufacture without any problems.
It used to be worth making your own circuit boards. In fact, I still have all the equipment for this tucked away in a box that I don’t expect ever to open. Photo etching your own circuit boards does not need to be expensive; you can make your own UV exposure box with UV LEDs easily enough, but you will also need noxious chemicals that do not keep once mixed and are difficult to dispose of responsibly. The end results are also generally inferior to the circuit boards a professional service will produce for you. So my advice is to plan ahead a little and have your circuit boards produced professionally.
For a guide to EAGLE CAD see: Make Your Own PCBs with EAGLE: From Schematic Designs to Finished Boards, TAB DIY, 2014.
The KiKad website is here: http://kicad-pcb.org/.
You can find out about DesignSpark here: https://www.rs-online.com/designspark/pcb-software.
I also have also written a guide to using Fritzing called Fritzing for Inventors: Take Your Electronics Project from Prototype to Product, TAB DIY, 2015.
Make the junction of the component lead and the solder pad hot for a second or two before applying the solder, as shown in Figure 20-15.
In more detail, to make a good solder joint, you should:
Soldering irons get hot—very hot—and can inflict nasty burns, so be careful. Safety glasses are a good idea as occasionally specks of solder can fly off if flicked by a lead, or even from boiling flux, and if your eyes are close to the thing you are soldering (which is quite likely) you could damage your eyes.
It is also a good idea to use a fume extractor (these do not need to be expensive; see Appendix A) to take away the noxious fumes released as the flux in the solder burns. This is not really something you want in your lungs.
Due to various international regulations that have been put in place, lead (the element Pb) is rapidly being phased out of use in circuit board manufacture. Most solder is now unleaded. Unfortunately, unleaded solder has a higher melting point and is generally a bit more difficult to use than the leaded variety. You can still buy leaded solder and many people keep a reel of “the good stuff.”
If you are using small components, then use a thin multicore rosin solder. I use 0.7mm.
You will find some good video tutorials for soldering on YouTube, and SparkFun has a great video on how to solder here: http://bit.ly/2mDxVyD.
I also recommend the book Learn to Solder by Brian Jepson, Maker Media, 2012.
If you are making a one-off, or just a few prototypes, consider soldering by hand. Unless you are very skilled, the results will not be great, but you should be able to make a functional prototype this way.
Soldering by hand is a great deal easier if you stick to SMD resistors and capacitors that are 0603 or larger and ICs with a pin spacing of 50 mils (1.27mm) or wider as found in SOIC packages.
Most components are available in a variety of different package sizes.
When soldering SMDs you will need to hold the part down (I use tweezers) while you solder each pin to a pad. As with through-hole soldering, heat the pin and pad for a second or so before touching the solder onto the pad and pin, flowing the solder into the joint.
When soldering the first pin, it’s best to put a tiny blob of solder on one pad (Figure 20-16) and then solder the first pin by just heating and pressing the pin onto the pad (Figure 20-17). You should find that once one pin is soldered, you don’t need to hold the device in place (Figure 20-18). When you have soldered all the other pins, it’s a good idea to circle back to the first pin and just flow a bit of solder into it to make sure it’s well soldered.
An alternative to using a soldering iron is to use solder paste and a hot-air gun. Here the procedure is to first place a little solder paste onto the component pads (Figure 20-19). Place the component onto the pads and hold it down with the tip of the tweezers while you heat it up with the hot-air gun (Figure 20-20).
If you have a reflow oven, like the homemade one shown in Figure 20-21, then you start as you would when using a hot-air gun, placing solder paste onto each pad. This task can be made easier by using a stencil, which most circuit board manufacturers will provide during circuit board manufacture for an extra cost.
Having applied the solder paste, place the components (they will stick to the solder paste). Then “cook” the board to melt the solder paste. A sophisticated reflow oven will have profiles you can set for different types of solder paste. It is surprising what you can get away with using a homemade oven. Mine is made from a converted toaster oven with a temperature probe fitted. A bit of trial and error will eventually get things right, but, purely as an example, my procedure for using lead solder paste (which has a lower melting temperature) is:
Your procedure will no doubt be different, but when you’ve found the magic formula for your setup, it should work every time.
Modified toaster ovens are potentially very dangerous (they have the nickname “fire starters” for good reason). Both when making modifications to the oven and when using it you must know exactly what you are doing and the risks involved. If you are not absolutely sure about what you’re doing, do not be tempted to make your own.
A homemade oven should not be left unattended for a moment while in use.
For soldering through-hole components, see Recipe 20.6.
Desoldering is generally a lot harder than soldering. Unless the component you want to desolder is valuable, you can make your life easier by not worrying about destroying it to get it off the board.
For through-hole two-lead components like resistors, I use the following procedure:
Desoldering DIL ICs is a lot more difficult, but again, if you don’t mind sacrificing the IC, you can chop off its pins and desolder each one separately. Removing the IC as a whole is also possible. Starting with the desoldering braid, get the IC as clean of solder as possible and then push a screwdriver under one end of the IC and gently lever it off, swapping sides with the screwdriver to gradually work the IC out.
Desoldering SMDs is much easier. Just hold a hot-air gun over the component and it will probably just blow away after a while.
Desoldering components is time consuming and you often end up damaging the circuit board pads or the component being removed. Sometimes it’s quicker just to throw it in the trash and start again.
To solder through-hole devices, see Recipe 20.4 and for SMDs Recipe 20.5.
Determine the power the device will need to continuously dissipate and decide the maximum temperature (Tmax) you want the device to reach (less than its absolute maximum in the datasheet). Then use the following formula to find the thermal resistance the heatsink (RØheatsink) will need to provide:
Here, Tambiant is the ambient temperature and RØpackage is the thermal resistance of the component package (1.5° C/W for a TO220 power transistor).
As an example, the datasheet for a TIP120 states that the maximum temperature is 150°C so let’s stay well under this with a Tmax of 130°C. Let’s assume the TIP120 is expected to be used in a circuit where it will generate 10W of heat.
Let’s also assume the ambient temperature of the project’s enclosure is 30°C (very dependent on ventilation).
Plugging these numbers into the formula, we have:
Searching through the heatsink listings in a component catalog, you can find heatsinks with thermal resistances of 8.5C/W or better.
Having done the calculations, test the temperature rise of the device for real and in its final enclosure, as the degree of ventilation in the enclosure will make a big difference. If need be, a fan on the heatsink will increase the heat dissipation considerably.
Heatsinks are available in a great variety of shapes and sizes. Figure 20-23 shows a selection of them.
When attaching a device to a heatsink, you should smear a thin layer of heatsink compound (white paste) onto the device to greatly improve the heat transfer from the device to the heatsink.
For background on power, see Recipe 1.6.
The datasheet for the TIP120 is found here: http://bit.ly/2mHBQy6.
This chapter explains how to use some of the most common electronic tools and test equipment. This includes both instruments for measurement such as multimeters and oscilloscopes and also simulation software that can be useful during design, especially when dealing with analog electronics.
To correctly use a lab power supply, follow these steps:
Aside from a multimeter, the lab power supply is probably the most useful piece of test equipment you can own. Owning one will save you vast amounts of time in the long run because you won’t have to hunt around for batteries and cobble together power supplies and reduce the chance of accidental destruction of components when prototyping.
Figure 21-1 shows a typical lab power supply capable of supplying up to 22V at 5A.
The top line of the display shows the voltage and the bottom, the current. When the output is off, the voltage knob allows you to set the voltage. The current knob sets the maximum current the circuit will be allowed to draw. If the circuit exceeds this, the power supply will automatically decrease the voltage until the current is below the set maximum. In this way, the power supply can be used as:
In addition to a single-output power supply like the one shown in Figure 21-1 dual-output power supplies are also available. These are very useful for analog circuits that require a split-voltage supply.
For information on building your power supplies of various sorts, see Chapter 7.
If you have an autoranging multimeter, simply set the meter to DC voltage and connect the probes across the voltage source.
If you have a multimeter where the range is set manually, determine the maximum voltage you expect to see and set the meter to the range whose maximum is above that value. Then connect the probe leads across the point in the circuit you want to measure.
Once you have established that the voltage is not too high for the range you selected, you can reduce the voltage range for better precision.
Figure 21-2 shows a typical medium-range digital multimeter (DMM).
Although an autoranging multimeter might seem to be superior to a multimeter where the range has to be set, in practice, it can be an advantage to think about what reading you are expecting to see before you take the reading (manually setting the range forces you to do this).
Even very low-cost DMMs generally provide better precision and accuracy than an analog meter. The principle advantage of an analog meter is that you may get a few more clues about what you are measuring if, for example, the tip of the meter’s needle jitters slightly to indicate noise, or you can see the rate of change of voltage as the speed of the meter moving in one direction or another. Some DMMs try to give you the best of both worlds by including an “analog” bargraph-type display in addition to the digital display.
For measuring AC voltage, see Recipe 21.3.
Follow the same procedure as Recipe 21.2 except set the multimeter range to AC volts rather than DC volts.
Since you are measuring AC you will get the same polarity of reading no matter how the leads are placed onto the circuit.
If you are planning to measure high-voltage AC ensure your meter probes are rated for high voltage. Also see Recipe 21.12.
Most DMMs will provide only an approximation of the RMS (root mean square) voltage by rectifying and smoothing it. Higher-end multimeters often include the feature “true RMS.”
For measuring DC voltages, see Recipe 21.2.
To use a multimeter to measure current:
DMMs measure the current flowing by measuring the voltage across a very low-value resistor. This is why you generally have to shift the probe leads to a different socket when measuring current.
If you leave the leads of the multimeter in their current measuring sockets and then go to measure voltage, you will effectively short-out the voltage you are trying to measure. This may damage the circuit or blow a fuse inside the multimeter.
To prevent this, always swap the leads back to their voltage-measuring positions when you are finished measuring current.
If you do blow the fuse in your multimeter, you should be able to open up your multimeter’s case and change the fuse.
To measure voltage, DC, and AC, see Recipe 21.2 and Recipe 21.3, respectively.
Most bench power supplies (Recipe 21.1) will also include an ammeter to tell you how much current is being drawn.
Disconnect the wire so that it is not in use and then use the continuity setting on your multimeter and connect the probes to each end of the thing you want to test.
If you are testing a long multicore cable (i.e., in situ and too long for the multimeter leads to reach both ends), you can connect the separate cores together at one end of the cable and test for continuity at the other, as shown in Figure 21-4.
After DC voltage, continuity is probably the setting you are most likely to use on your multimeter. It is particularly useful if your multimeter makes a beeping noise when the resistance is low enough to indicate continuity. This allows you to move the test probes around without having to look at the multimeter’s screen.
Recipe 21.2 provides an introduction to multimeters.
Nearly all multimeters will have several resistance ranges, and many will have a few capacitance ranges as well.
To use these ranges, simply select the range and attach the component to the test leads. You may find that as with measuring current, the test leads have to be inserted into different sockets on the multimeter when using these measurement ranges.
Some DMMs will offer inductance and frequency ranges, and specialized meters are available for measuring resistance, capacitance, and inductance more accurately than the average DMM can.
Some of these will actually allow you to just attach test leads to any component and the meter will first identify it and then measure its properties. Amazingly, such meters are available on eBay as a kit to assemble yourself for around $10.
When measuring component values, do not be seduced into thinking you are making a very accurate measurement of a component value because of the precision of the result. A reading of 1.23µF may still have a measurement of ±10%, so check the specification for your meter.
Recipe 21.2 provides an introduction to multimeters.
Disconnect the circuit and then use a resistor in parallel with the capacitor to discharge the capacitor until the voltage across it has reached a safe level as indicated by a multimeter set to its DC-voltage setting.
When discharging the capacitor, you can either connect the resistor using insulated crocodile clips, or if access is good enough, bend the resistor leads to the correct gap and then hold the resistor with pliers, carefully touching the capacitor leads as shown in Figure 21-5.
Calculate the resistance and the power rating of the resistor such that the capacitor discharges in a reasonable amount of time without the resistor becoming too hot.
The time constant (RC) is the time in seconds for the capacitor’s voltage to drop to 63.2% of its original value. For example, if you have a 100µF capacitor charged to 300V (you might find this in a photographic flashgun) and you want to discharge the capacitor to a safe 10V, a resistor of 10kΩ would have a time constant of 1 second. So holding it to the capacitor for 1 second would reduce the voltage to 190V, a further second to 120V, and so on. So, after 7 seconds, the voltage would be down to a safe 7.6V.
You can calculate the maximum power the resistor will dissipate as heat using:
which in this case would be 9W. That’s quite a physically big resistor, so failing to do a rough calculation and using a standard ¼W resistor is likely to end in a puff of smoke for the resistor.
Increasing the resistance of the resistor decreases the power requirement of the resistor but will take longer for the capacitor to discharge. It is a good idea to monitor the capacitor’s voltage with a multimeter while you discharge.
A capacitor charged to a high voltage is a dangerous thing, but a high-value capacitor even at low voltages can cause massive currents to flow if its terminals are short circuited and the capacitor has a low ESR.
For a calculation on the energy stored in a capacitor, see Recipe 3.7.
Use a voltage divider comprised of a ladder of equal-value resistors to reduce the voltage to be measured. You will need to take into account the effect that the voltage divider has on the voltage being measured and the input impedance of the multimeter. Also, make sure the resistors used are rated for a high enough voltage.
Figure 21-6 shows how you might measure a voltage of around 5kV using a multimeter with a maximum DC voltage measurement of 1000V and an imput impedance of 10MΩ.
The voltage divider will reduce the input voltage by a factor of 10, making the sums easier. Using 10 equal-value resistors (of 1% or better accuracy) is more likely to result in better accuracy of the system overall if the resistors are from the same batch. The closer the resistors are in value to each other the better the divider.
There are a few other things you need to consider. First, remember to calculate how much the chain of resistors will load the output of the high-voltage source. In this case, a load of 10MΩ across 10kV will result in current flowing at 1mA.
If you plan to measure high voltages, you will need special high-voltage leads that are extremely well insulated to prevent sparking across to your fingers. Your voltage divider should also be boxed and not easy to accidentally touch.
Also, see Recipe 21.12.
The heat power generated by each resistor will be 1kV * 1mA = 1W, which is significant. The temptation is to use higher-value resistors (say 10MΩ) to reduce the power and loading on the voltage source, but this will lead to the impedance of the multimeter becoming significant and acting as two similar-value resistors in parallel, making the reading almost useless.
A typical low-cost or medium-range multimeter will only have an input impedance of 10MΩ, which would result in the voltage reading being reduced by about 10% from the actual voltage.
You can determine the input impedance of your multimeter using the schematic in Figure 21-7.
To determine the input impedance of your multimeter (Z in Figure 21-7):
For example, with a value of R1 of 10MΩ and a 10V supply, my meter gave a Vm reading of 4.7V. Plugging the numbers in you get:
If you plan to measure high voltages on a regular basis, buy a specialist high-voltage voltmeter. In addition to having a very high voltage range, these instruments also usually have very high input impedance and do not load the circuit under test to the extent that the voltage being measured is appreciably altered.
You can also use the preceding method using very high-value resistors if you buy a high-quality multimeter with a buffered input that gives the multimeter an input impedance in the hundreds of MΩ or even GΩ range.
For more information on using a resistor as a voltage divider, see Recipe 2.6.
For regular DC-voltage measurement, see Recipe 21.2.
Figure 21-8 shows a typical low-cost oscilloscope displaying a 1kHz 5V test signal available from a terminal on the front of the oscilloscope.
To look at a signal on an oscilloscope:
Every model of oscilloscope is a little different, so you will need to consult the manual for yours to find the controls used in the preceding instructions.
Most oscilloscopes, including the one shown in Figure 21-8, have two channels that allow you to display two signals at the same time as well as a host of other features such as automatic measurement of frequency and signal amplitude.
When choosing an oscilloscope to buy, you can spend from a few hundred dollars to many thousands of dollars. You pay more for higher frequency range, better displays, and more advanced features. A basic 20MHz oscilloscope like the one shown in Figure 21-8 is a perfectly good starting point and has served me well for many years.
In addition to standalone oscilloscopes, you can also buy “PC scopes” that do not have a screen but rather rely on a USB connection to the PC running the oscilloscope software. As with standalone oscilloscopes, PC scopes are available at all prices and qualities. I prefer a standalone device as it’s always there on my workbench and I don’t have to wait for it to boot up, but many people find the extra features that often come with a PC scope and the bigger and better display of a computer monitor outweigh any disadvantages.
For more information on getting the most from your oscilloscope, get to know the manual really thoroughly. You may find all sorts of features that are not immediately obvious from the controls on the front.
Use a function generator (a.k.a. a signal generator).
The function generator shown in Figure 21-9 is a typical low-cost function generator capable of generating two independent sine, square, or triangle waveforms of up to 20 MHz.
To use the function generator:
If you have a single-supply amplifier or other circuit, if the input signal is swinging negative on each cycle, you may damage the circuit you are testing.
Signal generators with digital controls, like the one shown in Figure 21-9, assume a full AC signal and a DC offset have to be explicitly set.
Figure 21-10 shows the oscilloscope trace for a 10kHz sinewave with an amplitude of 2V peak-to-peak and a DC offset of 2.5V generated by the function.
If you are on a budget, you can make your own oscillator as shown in Recipe 16.5.
Use circuit-simulator software.
A free online circuit simulator is a great way to get started with circuit simulation. The PartSim is one such easy-to-use simulator. Sign up for a PartSim account and then start drawing your schematic in the simulator. Figure 21-11 shows the schematic for the simple RC filter from Recipe 16.3.
In addition to drawing R1 and C1, you can also specify an AC-voltage source to drive it. In this case, as the parameter in Figure 21-11 suggests, the test signal will be a 5V square wave (pulse) with rise and fall times of 1µs, a pulse length of 15µs, and an overall period of 30µs. This corresponds roughly to the 32.7kHz carrier signal of Recipe 16.3.
When you click the Run button you will be prompted to enter some parameters for a simulation as shown in Figure 21-12.
There are various types of simulations that can be run, but in this case we are interested in the “Transient Response.” The Start and Stop times determine how long the simulation will run and the Time Step is the step between each calculated value in the simulation.
When you click Run, you will see a new tab appear in the window with the name “transient response” that shows the result of the simulation as shown in Figure 21-13.
You can see that the output is indeed greatly attenuated by the RC filter.
Simulation is very useful in analog design, not least because it tells you how the circuit should behave, whereas a signal generator and oscilloscope will tell you how just one prototype behaves. A physical prototype has the problem that there may be a fault in its construction or components that causes it to behave differently when you make a second prototype. Simulation will tell you what to expect in a reliable and consistent manner.
In addition to idealized components like resistors, capacitors, and perfect op-amps, simulators like PartSim also have a huge array of “models” for actual components, including specific op-amp models.
PartSim is based on the open source SPICE simulation software; learn more at: http://bwrcs.eecs.berkeley.edu/Classes/IcBook/SPICE/.
Assume that coming into contact with a high voltage will kill you.
Although a little hyperbolic, this statement is a good thing to keep at the front of your mind when working with high voltages. Frankly anything above 50V should scare you. So AC with its fatal combination of high voltage and high availability of current should scare you a lot.
Here are some rules I stick to when working on AC:
According to the American Burn Association:
In the United States, on average of 400 people die from electrocution and 4,400 are injured each year because of electrical hazards.
In addition to the risk of a current flowing through your heart and stopping it, burns caused by your body effectively acting as a heating element as well as arcing sparks are risks associated with high voltages.
For the full American Burn Association report, see: http://www.ameriburn.org/Preven/ElectricalSafetyEducator’sGuide.pdf.
The following tables will help you to find the parts used in this book. Where possible, I have listed product codes for suppliers.
There are now many electronic component suppliers that cater to the maker and electronics hobbyist. Some of the most popular are listed in Table A-1.
| Supplier | Website | Notes |
|---|---|---|
|
Adafruit |
Good for modules |
|
|
DigiKey |
Wide range of components |
|
|
MakerShed |
Good for modules, kits, and tools |
|
|
MCM Electronics |
Wide range of components |
|
|
Mouser |
Wide range of components |
|
|
SeeedStudio |
Interesting low-cost modules |
|
|
SparkFun |
Good for modules |
|
| MonkMakes | http://www.monkmakes.com | Electronic Kits for Raspberry Pi, etc. |
| Pimoroni | Raspberry Pi and Arduino | |
| Polulu | https://www.pololu.com/ | Great for motor controllers and robots |
|
CPC |
UK-based, wide range of components |
|
|
Farnell |
International, wide range of components |
|
|
Maplin |
UK-based, bricks and mortar, Raspberry Pi and Arduino |
|
|
Proto-pic |
UK-based, stock SparkFun, and Adafruit modules |
The other great source for components is eBay.
Searching for components can be time consuming and difficult. The Octopart component search engine can be very helpful for tracking down parts.
Many of the hardware projects in this book use jumper wires of various sorts. Male-to-female leads (to connect the Raspberry Pi GPIO connector to a breadboard) and male-to-male (to make connections on the breadboard) are particularly useful. Female-to-female are occasionally useful for connecting modules directly to GPIO pins. You rarely need leads longer than 3 inches (75mm). Table A-2 lists some jumper wire and breadboard specifications, along with their suppliers.
A handy way to get started with breadboard, jumper wires, and some components to get you started is to buy a starter kit like the Hacking Electronics Kit or Electronics Starter Kit for Raspberry Pi by MonkMakes.com.
| Description | Suppliers |
|---|---|
|
M-M jumper wires |
SparkFun: PRT-08431, Adafruit: 759, DigiKey: PRT-08431-ND |
|
M-F jumper wires |
SparkFun: PRT-09140, Adafruit: 825, DigiKey: PRT-09140-ND |
|
F-F jumper wires |
SparkFun: PRT-08430, Adafruit: 794, DigiKey: PRT-08430-ND |
|
Half-sized breadboard |
SparkFun: PRT-09567 Adafruit: 64, DigiKey: 377-2094-ND |
| Raspberry Leaf (26 pin) | Adafruit: 1772 |
| Raspberry Leaf (40 pin) | Adafruit: 2196 |
| Electronics Starter Kit for Raspberry Pi | Amazon, monkmakes.com |
| Monk Makes Protoboard | Amazon, monkmakes.com/pb |
| Adafruit PermaProto for Pi (half breadboard) | Adafruit: 1148 |
| Adafruit PermaProto for Pi (full breadboard) | Adafruit: 1135 |
| Adafruit PermaProto HAT | Adafruit: 2314, DigiKey: 1528-1370-ND |
| DC barrel jack to screw terminal adapter (female) | Adafruit: 368, DigiKey: 1528-1386-ND |
Table A-3 lists resistors used in this cookbook and some suppliers.
| 10Ω 0.25W resistor | Mouser: 293-10-RC, DigiKey: 10QBK-ND |
| 22Ω 0.25W resistor | Mouser: 293-22-RC, DigiKey: 22QBK-ND |
| 100Ω 0.25W resistor | Mouser: 293-100-RC, DigiKey: 100QBK-ND |
| 120Ω 0.25W resistor | Mouser: 293-120-RC, DigiKey: 120QBK-ND |
| 150Ω 0.25W resistor | Mouser: 293-150-RC, DigiKey: 150QBK-ND |
|
270Ω 0.25W resistor |
Mouser: 293-270-RC, DigiKey: 270QBK-ND |
| 330Ω 0.25W resistor | Mouser: 293-330-RC, DigiKey: 330QBK-ND |
|
470Ω 0.25W resistor |
Mouser: 293-470-RC, DigiKey: 470QBK-ND |
|
1kΩ 0.25W resistor |
Mouser: 293-1k-RC, DigiKey: 1.0kQBK-ND |
|
3.3kΩ 0.25W resistor |
Mouser: 293-3.3k-RC, DigiKey: 3.3kQBK-ND |
|
4.7kΩ 0.25W resistor |
Mouser: 293-4.7k-RC, DigiKey: 4.7kQBK-ND |
| 10kΩ 0.25W resistor | Mouser: 293-10k-RC, DigiKey: 10kQBK-ND |
| 22kΩ 0.25W resistor | Mouser: 293-22k-RC, DigiKey: 22kQBK-ND |
| 33kΩ 0.25W resistor | Mouser: 293-33k-RC, DigiKey: 33kQBK-ND |
| 100kΩ 0.25W resistor | Mouser: 293-100k-RC, DigiKey: 100kQBK-ND |
| 180kΩ 0.25W resistor | Mouser: 293-180k-RC, DigiKey: 180kQBK-ND |
| 1MΩ 0.25W resistor | Mouser: 293-1M-RC, DigiKey: 1.0MQBK-ND |
| 1.8MΩ 0.25W resistor | Mouser: 293-1.8M-RC, DigiKey: 1.8MQBK-ND |
|
10 kΩ trimpot |
Adafruit: 356, SparkFun: COM-09806, Mouser: 652-3362F-1-103LF, DigiKey: 3386P-103TLF-ND |
|
Photoresistor |
Adafruit: 161, SparkFun: SEN-09088, DigiKey: NSL-5152-ND |
| Thermistor T0 of 1k Beta 3800 NTC | Mouser: 871-B57164K102J (note Beta is 3730), DigiKey: 495-75312-ND |
Table A-4 lists resistors and capacitors used in this cookbook and some suppliers.
| 1nF 50V | DigiKey: BC2659CT-ND, Mouser: 594-K102J15C0GF5TH5 |
|
10nF 50V |
DigiKey: BC2662CT-ND, Mouser: 594-K103K15X7RF5UL2 |
| 10nF 1000V | DigiKey: 1255PH-ND, Mouser: 81-RDER73A103K3M1H3A |
| 100nF 50V | DigiKey: 399-4151-ND, Mouser: 594-K104K15X7RF53L2 |
| 100nF 400V | DigiKey: EF4104-ND, Mouser: 581-SR758C104KAATR1 |
| 220nF 50V | DigiKey: BC2678CT-ND, Mouser: 594-K224K20X7RF5TH5 |
| 330nF 50V | DigiKey: 399-9882-1-ND, Mouser: 80-C330C334K5R |
| 680nF 50V | DigiKey: 445-8519-ND, Mouser: 81-RCER71H684K2M1H3A |
| 1µF 16V | DigiKey: 445-8614-ND, Mouser: 539-SN010M025ST |
| 4.7µF 16V | DigiKey: 493-10248-1-ND, Mouser: 647-UMA1C4R7MCD2 |
| 10µF 16V | DigiKey: 493-10245-1-ND, Mouser: 667-ECE-A1CKS100 |
| 100µF 16V | DigiKey: P16379CT-ND, Mouser: 598-107CKS016M |
| 220µF 25V | DigiKey: 493-6082-ND, Mouser: 667-EEU-FM1E221 |
| 470µF 35V | DigiKey: 493-12724-1-ND, Mouser: 667-ECA-1VM471 |
| 1000µF 25V | DigiKey: 493-12690-1-ND, Mouser: 667-EEU-FC1E102L |
| 390nH 100mA | DigiKey: 445-1010-1-ND, Mouser: 542-9230-10-RC |
| 4.7µH 250mA | DigiKey: 495-5567-1-ND, Mouser: 70-IR04RU4R7K |
| 22uH 3A Inductor | DigiKey: 495-5590-1-ND, Mouser: 580-12RS223C |
| 33uH 3A Inductor | DigiKey: 495-5705-1-ND, Mouser: 963-LHL13NB330K |
Table A-5 lists transistors and diodes used in this cookbook and some suppliers.
|
FQP30N06L N-channel logic-level MOSFET transistor |
Mouser: 512-FQP30N06L, SparkFun: COM-10213, DigiKey: FQP30N06L-ND |
| FQP27P06 P-channel MOSFET transistor | SparkFun: COM-10349, Mouser: 512-FQP27P06, DigiKey: FQP27P06-ND |
|
2N3904 NPN bipolar transistor |
SparkFun: COM-00521, Adafruit: 756, Mouser: 512-2N3904BU, DigiKey: 2N3904TAFSCT-ND |
| 2N3906 PNP bipolar transistor | SparkFun: COM-00522, Mouser: 512-2N3906TA, DigiKey: 2N3906-APCT-ND |
| TIP120 Darlington transistor | Adafruit: 976, CPC: SC10999, Mouser: 511-TIP120, DigiKey: TIP120-ND |
| 2N7000 MOSFET transistor | Mouser: 512-2N7000, CPC: SC06951, DigiKey: 2N7000TACT-ND |
| STGF3NC120HD IGBT | Mouser: 511-STGF3NC120HD, DigiKey: 497-4353-5-ND |
| IRG4PC30UPBF IGBT | Mouser: 942-IRG4PC30UPBF |
|
1N4001 diode |
Mouser: 512-1N4001, SparkFun: COM-08589, Adafruit: 755, DigiKey: 1N4001DICT-ND |
|
1N4004 diode |
Mouser: 512-1N4004, DigiKey: 1N4004FSCT-ND |
| 1N4007 diode (1000V) | Mouser: 821-1N4007, DigiKey: 1N4007FSCT-ND |
| 1N4148 diode | Mouser: 512-1N4148, DigiKey: 1N4148FS-ND |
| 1N5819 Schottky diode |
Mouser: 512-1N5819, DigiKey: 1N5819FSCT-ND |
| 1N5919 5.6V Zener diode | Mouser: 863-1N5919BG, DigiKey: 1N5919BGOS-ND |
| BT136 TRIAC | Mouser: 583-BT136, DigiKey: 568-12097-5-ND |
Figure A-1 shows the pinouts for the transistors listed in this section.
Table A-6 lists ICs used throughout this cookbook and some suppliers. These are listed in alphabetical order by part name.
| 74HC00 quad NAND | DigiKey: 296-1563-5-ND, Mouser: 595-SN74HC00N |
| 74HC4017 counter decoder | DigiKey: 296-25989-5-ND, Mouser: 595-CD74HC4017E |
| 74HC4094 shift register | DigiKey: 296-26002-5-ND , Mouser: 595-CD74HC4094E |
| 74HC590 counter | DigiKey: 296-1599-5-ND, Mouser: 595-SN74HC590AN |
| CD4047 oscillator | DigiKey: 296-2053-5-ND, Mouser: 595-CD4047BEE4 |
|
DS18B20 temperature sensor |
SparkFun: SEN-00245, Adafruit: 374, Mouser: 700-DS18B20, CPC: SC10426, DigiKey: DS18B20+-ND |
|
L293D motor driver |
SparkFun: COM-00315, Adafruit: 807, Mouser: 511-L293D, CPC: SC10241, DigiKey: 497-2936-5-ND |
| LM2596-5V switcher | DigiKey: LM2596T-5.0/NOPB-ND, Mouser: |
| LM311 comparator | DigiKey: 296-1389-5-ND, Mouser: 926-LM311N/NOPB |
| LM317 adjustable voltage regulator | DigiKey: LM317AHVT-ND , Mouser: 595-LM317KCSE3 |
| LM321 op-amp | DigiKey: LM321MFX/NOPBCT-ND, Mouser: 926-LM321MF/NOPB |
| LM741 op-amp | DigiKey: LM741CNNS/NOPB-ND, Mouser: 926-LM741CN/NOPB |
|
LM7805 voltage regulator |
SparkFun: COM-00107, Adafruit: 2164, Mouser: 511-L7805CV, CPC: SC10586, DigiKey:497-1443-5-ND |
| LM78L12 voltage regulator | DigiKey: LM78L12ACZFS-ND, Mouser: 512-LM78L12ACZ |
| LM79L12 voltage regulator | DigiKey: LM79L12ACZ/NOPB-ND, Mouser: 926-LM79L12ACZ/NOPB |
| MAX2606 VCO | DigiKey: MAX2606EUT+TCT-ND , Mouser: 700-MAX2606EUTT |
|
MCP3008 eight-channel ADC IC |
Adafruit: 856, Mouser: 579-MCP3008-I/P, CPC: SC12789, DigiKey: MCP3008-I/P-ND |
| MCP73831 LiPo charger IC | DigiKey: MCP73831T-2DCI/OTCT-ND, Mouser: 579-MCP73831T5ACIOT |
| NE555 timer | SparkFun: COM-09273, DigiKey: 296-1411-5-ND, Mouser: 595-NE555P |
| OPA365 op-amp | DigiKey: 296-20645-1-ND, Mouser: 595-OPA365AIDBVR |
| TDA7052 1W power amp | DigiKey: 568-1138-5-ND, Mouser: 771-TDA7052ATN2112 |
| TLV2770 op-amp | DigiKey: 296-1897-5-ND, Mouser: 595-TLV2770IP |
| TPA3122D2 15W power amp | DigiKey: 296-23375-5-ND , Mouser: 595-TPA3122D2N |
|
TMP36 temperature sensor |
SparkFun: SEN-10988, Adafruit: 165, Mouser: 584-TMP36GT9Z, CPC: SC10437, DigiKey: TMP36GT9Z-ND |
| TPS61070 boost converter | DigiKey: 296-17151-1-ND, Mouser: 595-TPS61070DDCR |
|
ULN2803 Darlington driver IC |
SparkFun: COM-00312, Adafruit: 970, Mouser: 511-ULN2803A, CPC: SC08607, DigiKey: 497-2356-5-ND |
| WS2812 pixel chip | DigiKey: 28085-ND |
| MOC3032 opto-isolator | DigiKey: MOC3032M-ND, Mouser: 512-MOC3032M |
Figure A-2 shows the pinouts for the ICs listed in this section.
Table A-7 lists opto-electronic components used throughout this cookbook and some suppliers.
|
5mm red LED |
SparkFun: COM-09590, Adafruit: 299, Mouser: 630-HLMP-3301, DigiKey: 160-1853-ND |
|
RGB common cathode LED |
SparkFun: COM-11120, Mouser: 713-104990023, eBay |
|
TSOP38238 IR sensor |
SparkFun: SEN-10266, Adafruit: 157 |
| 4-digit 7-segment common cathode LED display | DigiKey: 67-1450-ND |
Table A-8 lists the modules used in this cookbook and other modules I like.
|
Arduino Uno |
SparkFun: DEV-11021, Adafruit: 50, CPC: A000066, DigiKey: 1050-1024-ND |
| Raspberry Pi3 | Adafruit: 3055, DigiKey: 1690-1000-ND |
|
Level converter, four-way |
SparkFun: BOB-11978, Adafruit: 757 |
|
Level converter, eight-way |
Adafruit: 395 |
|
LiPo boost converter/charger |
SparkFun: PRT-11231 |
|
PowerSwitch tail |
Adafruit: 268 |
| Monk Makes ServoSix board | monkmakes.com, Amazon |
|
16-channel servocontroller |
Adafruit: 815 |
|
Motor driver 1A dual |
SparkFun: ROB-09457 |
|
RasPiRobot board V3 |
Adafruit: 1940, Amazon |
|
PIR motion detector |
Adafruit: 189 |
|
4x7-segment LED with I2C backpack |
Adafruit: 878 |
|
Bicolor LED square-pixel matrix with I2C backpack |
Adafruit: 902 |
|
16 x 2 HD44780 compatible LCD module |
SparkFun: LCD-00255, Adafruit: 181 |
| SSD1306-based 0.96 or 1.2in OLED display | eBay |
| Stepper motor HAT | Adafruit: 2348 |
| 16-channel PWM HAT | Adafruit: 2327 |
| Squid Button | monkmakes.com, Amazon |
| Raspberry Squid RGB LED | monkmakes.com, Amazon |
| I2C OLED display 128x64 pixels | eBay |
| Adafruit Lipo charger module | Adafruit: 1905 |
| SparkFun LiPo charger module | SparkFun: PRT-10217 |
| CC1101 RF transceiver module | eBay |
Table A-9 lists miscellaneous tools and components used in this cookbook and some suppliers.
|
1200mAh LiPo battery |
Adafruit: 258 |
|
5V relay |
SparkFun: COM-00100 |
|
Standard servomotor |
SparkFun: ROB-09065, Adafruit: 1449 |
| 9g mini servomotor | Adafruit: 169 |
|
5V 1A power supply |
Adafruit: 276 |
|
Low power 6V DC motor |
Adafruit: 711 |
|
0.1-inch header pins |
SparkFun: PRT-00116, Adafruit: 392 |
|
5V 5-pin unipolar stepper motor |
Adafruit: 858 |
|
12V, 4-pin bipolar stepper motor |
Adafruit: 324 |
|
Tactile push switch |
SparkFun: COM-00097, Adafruit: 504 |
|
Miniature slide switch |
SparkFun: COM-09609, Adafruit: 805 |
|
Rotary encoder (quadrature) |
Adafruit: 377 |
|
4x3 keypad |
SparkFun: COM-08653 |
|
Piezo buzzer |
SparkFun: COM-07950, Adafruit: 160 |
| Reed switch | Adafruit: 375 |
| Loudspeaker 8Ω 1W | Adafruit: 1313 |
There are many choices here. I would always say start with low-cost equipment and upgrade as and when you feel the need. After all, if you were learning the violin, it would be foolish to start with a Stradivarius!
The items listed in Table A-10 are similar to those I use every day and serve as a guide to help you get started. You should shop around; there are some great bargains to be had.
|
Basic multimeter |
Monk Makes Hacking Electronics Kit, eBay |
| Better multimeter (Tenma 72-7725) | Amazon, eBay |
| Entry-level oscilloscope | Adafruit: 681 |
| Bench power supply | DigiKey: BK1550-220V-ND |
| Good soldering station | SparkFun: TOL-11704 |
| Fume extractor | eBay |
| Thermal heatsink compound | eBay |
Figure B-1 shows the pinout for the Arduino Uno R3.
Figure B-2 shows the pinout for the Arduino Pro Mini.
Figure C-1 shows the pinouts for the current 40-pin GPIO Raspberry Pi.
If you have an Raspberry Pi, it is most likely the model B rev. 2 board shown in Figure C-2.
The very first released version of the Raspberry Pi model B (rev. 1) has some minor pinout differences from the rev. 2 that followed. This is the only version of the Raspberry Pi that is not compatible with later pinouts. The incompatible pins that changed are highlighted in bold in Figure C-3.
Table D-1 lists the most common units used in electronics along with the typical ranges of those units you might find in practice.
| Property | Unit | Typical range |
|---|---|---|
| Current | A (Ampere) | 100nA to 100A |
| Voltage | V (Volt) | 1mV to 1000V |
| Resistance | Ω (Ohm) | 10mΩ to 20MΩ |
| Energy | J (Joule) | 1J to 1MJ |
| Watt | W (Watt) | 1mW to 10kW |
| Capacitance | F (Farad) | 10pF to 10F |
| Inductance | H (Henry) | |
| Frequency | Hz (Hertz) |
sound 20Hz to 20kHz radio 3kHz to 300GHz |
Table D-2 shows the unit prefixes applied to electronic and other units. You will sometimes find R used in place of Ω and u in place of µ.
| Prefix | Multiplier | Scientific |
|---|---|---|
| p (pico) | 1/1,000,000,000,000 | 10E-12 |
| n (nano) | 1/1,000,000,000 | 10E-9 |
| µ (micro) | 1/1,000,000 | 10E-6 |
| m (milli) | 1/1,000 | 10E-3 |
| k (kilo) | 1,000 | 10E3 |
| M (mega) | 1,000,000 | 10E6 |
| G (giga) | 1,000,000,000 | 10E9 |
The animal on the cover of Electronics Cookbook is an elephantnose fish (Gnathonemus petersii). This species is native to West and Central Africa, where it favors muddy and heavily-vegetated areas of rivers. Its Latin name petersii most likely refers to German naturalist Wilhelm Peters.
The elephantnose fish is oblong-shaped and typically dark brown or black in color. Its “trunk”—the signature feature from which the species’s common name is derived—is not actually a nose, but an extension of the mouth that is covered in electroreceptors. Gnathonemus petersii produces a weak electric field that is used to probe for food, navigate through murky waters, and detect prey. It also lends itself to communicating with other fish and finding mates.
Many of the animals on O’Reilly covers are endangered; all of them are important to the world. To learn more about how you can help, go to animals.oreilly.com.
The cover image is from Lydekker’s Royal Natural History. The cover fonts are URW Typewriter and Guardian Sans. The text font is Adobe Minion Pro; the heading font is Adobe Myriad Condensed; and the code font is Dalton Maag’s Ubuntu Mono.

Practical Electronic Recipes
with Arduino and Raspberry Pi
Copyright © 2017 Simon Monk. All rights reserved.
Printed in the United States of America.
Published by O’Reilly Media, Inc., 1005 Gravenstein Highway North, Sebastopol, CA 95472.
O’Reilly books may be purchased for educational, business, or sales promotional use. Online editions are also available for most titles (http://oreilly.com/safari). For more information, contact our corporate/institutional sales department: 800-998-9938 or corporate@oreilly.com.
See http://oreilly.com/catalog/errata.csp?isbn=9781491953402 for release details.
The O’Reilly logo is a registered trademark of O’Reilly Media, Inc. Electronics Cookbook, the cover image of an elephantnose fish, and related trade dress are trademarks of O’Reilly Media, Inc.
While the publisher and the author have used good faith efforts to ensure that the information and instructions contained in this work are accurate, the publisher and the author disclaim all responsibility for errors or omissions, including without limitation responsibility for damages resulting from the use of or reliance on this work. Use of the information and instructions contained in this work is at your own risk. If any code samples or other technology this work contains or describes is subject to open source licenses or the intellectual property rights of others, it is your responsibility to ensure that your use thereof complies with such licenses and/or rights.
978-1-491-95340-2
[LSI]
Traditional wisdom requires people using electronics to have at least an EE degree before they can do anything useful, but in this book the whole subject of electronics is given the highly respected O’Reilly Cookbook treatment and is broken down into recipes. These recipes make it possible for the reader to access the book at random, following the recipe that solves their problem and learning as much or as little about the theory as they are comfortable with.
While it is impossible to cover in one volume everything in a complex and wide-ranging subject like electronics, I have tried to select recipes that seem to come up most frequently when I talk to other makers, hobbyists, and inventors.
If you are into electronics or want to get into electronics, then this is the book that will help you get more from your hobby. The book is full of built-and-tested recipes that you can trust to do just what you need them to do, no matter what your level of expertise.
If you are new to electronics then this book will serve as a guide to get you started; if you are an experienced electronics maker, it will act as a useful reference.
This book has been gestating for a while. I believe that the original concept came from no less a person than Tim O’Reilly himself. The idea was to fill the gap in the market between books like the Arduino Cookbook and the Raspberry Pi Cookbook and heavyweight electronics textbooks.
In other words, to cover more of the fundamentals of electronics and topics peripheral to the use of microcontrollers that often get neglected, except in heavyweight electronic tomes. Topics such as how to construct various types of power supply, using the right transistor for switching, using analog and digital ICs, as well as how to construct projects and prototypes and use test equipment.
Boards like the Arduino and Raspberry Pi have lured whole new generations of makers, hobbyists, and inventors into the world of electronics. Components and tools are now low cost and within the reach of more people than at any time in history. Hackspaces and Fab Labs have electronic workstations where you can use tools to realize your projects.
The free availability of information including detailed designs means that you can learn from and adapt other people’s work for your own specific needs.
Many people who start with electronics as a hobby progress to formal education in electronic engineering, or just jump straight to product design as an inventor and entrepreneur. After all, if you have access to a computer and a few tools and components, you can build a working prototype of your great invention and then find someone to manufacture it for you, all financed with the help of crowdfunding. The barrier of entry to the electronics business is at an all-time low.
As a “cookbook” you can dive in and use any recipe, rather than read the book in order. Where you have a recipe that relies on some knowledge or skills from another recipe, there will be a link back to the prerequisite recipe.
The recipes are arranged in chapters, with Chapters 1 to 6 providing more fundamental recipes, some concerning theory but mostly about different types of component (your recipe ingredients). These chapters are:
The next section of chapters looks at how the components introduced in the first section can be used together in various recipes covering pretty much anything electronic that you might like to design.
The final section of the book contains recipes for construction and the use of tools.
The book also includes appendices that list all the parts used in the book along with useful suppliers and provide pinouts for devices including the Arduino and Raspberry Pi.
There are many wonderful resources available for the electronics enthusiast.
If you are looking for project ideas then sites like Hackaday and Instructables are a great source of inspiration.
When it comes to getting help with a project, you will often get great advice from the many experienced and knowledgable people that hang out on the following forums. Remember to search the forum before asking your question, in case it has come up before (usually it has) and always explain your question clearly, or “experts” can get impatient with you.
The following typographical conventions are used in this book:
Indicates new terms, URLs, email addresses, filenames, and file extensions.
Constant widthUsed for program listings, as well as within paragraphs to refer to program elements such as variable or function names, databases, data types, environment variables, statements, and keywords.
Constant width boldShows commands or other text that should be typed literally by the user.
Constant width italicShows text that should be replaced with user-supplied values or by values determined by context.
This element signifies a tip or suggestion.
This element indicates a warning or caution.
Supplemental material (code examples, exercises, etc.) is available for download at https://github.com/simonmonk/electronics_cookbook.
This book is here to help you get your job done. In general, if example code is offered with this book, you may use it in your programs and documentation. You do not need to contact us for permission unless you’re reproducing a significant portion of the code. For example, writing a program that uses several chunks of code from this book does not require permission. Selling or distributing a CD-ROM of examples from O’Reilly books does require permission. Answering a question by citing this book and quoting example code does not require permission. Incorporating a significant amount of example code from this book into your product’s documentation does require permission.
We appreciate, but do not require, attribution. An attribution usually includes the title, author, publisher, and ISBN. For example: “Electronics Cookbook by Simon Monk (O’Reilly). Copyright 2017 Simon Monk, 978-1-491-95340-2.”
If you feel your use of code examples falls outside fair use or the permission given above, feel free to contact us at permissions@oreilly.com.
Safari (formerly Safari Books Online) is a membership-based training and reference platform for enterprise, government, educators, and individuals.
Members have access to thousands of books, training videos, Learning Paths, interactive tutorials, and curated playlists from over 250 publishers, including O’Reilly Media, Harvard Business Review, Prentice Hall Professional, Addison-Wesley Professional, Microsoft Press, Sams, Que, Peachpit Press, Adobe, Focal Press, Cisco Press, John Wiley & Sons, Syngress, Morgan Kaufmann, IBM Redbooks, Packt, Adobe Press, FT Press, Apress, Manning, New Riders, McGraw-Hill, Jones & Bartlett, and Course Technology, among others.
For more information, please visit http://oreilly.com/safari.
Please address comments and questions concerning this book to the publisher:
We have a web page for this book, where we list errata, examples, and any additional information. You can access this page at http://bit.ly/electronics-cookbook.
To comment or ask technical questions about this book, send email to bookquestions@oreilly.com.
For more information about our books, courses, conferences, and news, see our website at http://www.oreilly.com.
Find us on Facebook: http://facebook.com/oreilly
Follow us on Twitter: http://twitter.com/oreillymedia
Watch us on YouTube: http://www.youtube.com/oreillymedia
Thanks to Duncan Amos, David Whale, and Mike Bassett for their technical reviews of the book and the many useful comments that they provided to help make this book as good as it could be.
I’d also like to thank Afroman for permission to use his great FM transmitter design and the guys at Digi-Key for their help in compiling parts codes.
As always, it’s been a pleasure working with the professionals at O’Reilly, in particular Jeff Bleiel, Heather Scherer, and of course, Brian Jepson.
Although this book is fundamentally about practice rather than theory, there are a few theoretical aspects of electronics that are almost impossible to avoid.
In particular, if you understand the relationship between voltage, current, and resistance many other things will make a lot more sense.
Similarly, the relationship between power, voltage, and current crops up time and time again.
As the word current suggests, the meaning of current in electronics is close to that of the current in a river. You could think of the strength of the current in a pipe as being the amount of water passing a point in the pipe every second. This might be measured in so many gallons per second.
In electronics, current is the amount of charge carried by electrons passing a point in a wire per second (Figure 1-1). The unit of current is the ampere, abbreviated as amp or as unit symbol A.
For a list of units and unit prefixes such as mA, see Appendix D.
To learn more about current in a circuit, see Recipe 1.4.
In Recipe 1.1 you read how current is the rate of flow of charge. That current will not flow without something influencing it. In a water pipe, that might be because one end of the pipe is higher than the other.
To understand voltage, it can be useful to think of it as being similar to height in a system of water pipes. Just like height, it is relative, so the height of a pipe above sea level does not determine how fast the water flows through a pipe, but rather how much higher one end of the pipe is than the other (Figure 1-2).
Voltage might refer to the voltage across a wire (from one end to the other) and in other situations, it might refer to the voltage from one terminal of a battery to another. The common feature is that for voltage to make any sense, it must refer to two points; the higher voltage is the positive voltage, marked with a +.
It is the difference in voltage that makes a current flow in a wire. If there is no difference in voltage between one end of a wire and another then no current will flow.
The unit of voltage is the volt. An AA battery has about 1.5V across its terminals. An Arduino operates at 5V, while a Raspberry Pi operates at 3.3V, although it requires a 5V supply that it reduces to 3.3V.
Sometimes it seems like voltage is used to refer to a single point in an electronic circuit rather than a difference between two points. In such cases the voltage then means the difference between the voltage at one point in the circuit and ground. Ground (usually abbreviated as GND) is a local reference voltage against which all other voltages in the circuit are measured. This is, if you like, 0V.
To learn more about voltages, see Recipe 1.5.
Use Ohm’s Law.
Ohm’s Law states that the current flowing through a wire or electronic component (I) will be the voltage across that wire or component (V) divided by the resistance of the component (R). In other words:
If it is the voltage that you want to calculate, then this formula can be rearranged as:
And, if you know the current flowing through a resistor and the voltage across the resistor, you can calculate the resistance using:
Resistance is the ability of a substance to resist the flow of current. A wire should have low resistance, because you do not usually want the electricity flowing through the wire to be unnecessarily impeded. The thicker the wire, the less its resistance for a given length. So a few feet of thin wire that you might find connecting a battery to a lightbulb (or more likely LED) in a flashlight might have a resistance of perhaps 0.1Ω to 1Ω, whereas the same length of thick AC outlet cable for a kettle may have a resistance of only a couple of milliohms (mΩ).
It is extremely common to want to limit the amount of current flowing through part of a circuit by adding some resistance in the form of a special component called a resistor.
Figure 1-3 shows a resistor (zig-zag line) and indicates the current flowing through it (I) and the voltage across it (V).
Let’s say that we were to connect a 1.5V battery to a 100Ω resistor as shown in Figure 1-4. The Greek letter Ω (omega) is used as shorthand for the unit of resistance (the “Ohm”).
Using Ohm’s Law, the current is the voltage across the resistor divided by the resistance of the resistor (we can assume that the wires have a resistance of zero).
So, I = 1.5 / 100 = 0.015 A or 15mA.
To understand what happens to current flowing through resistors and wires in a circuit, see Recipe 1.4.
To understand the relationship between current, voltage, and power, see Recipe 1.6.
Use Kirchhoff’s Current Law.
Stated simply, Kichhoff’s Current Law says that at any point on a circuit, the current flowing into that point must equal the current flowing out.
For example, in Figure 1-5 two resistors are in parallel and supplied with a voltage from a battery (note the schematic symbol for a battery on the left of Figure 1-5).
At point X, a current of I will be flowing into point X from the battery, but there are two branches out of X. If the resistors are of equal value then each branch will have half the current flowing through it.
At point Y, the two paths recombine and so the two currents of I/2 flowing into Y will be combined to produce a current of I flowing out of Y.
For Kirchhoff’s Voltage Law, see Recipe 1.5.
For further discussion on resistors in parallel, see Recipe 2.5.
Use Kirchhoff’s Voltage Law.
This law states that all the voltages between various points around a circuit will add up to zero.
Figure 1-6 shows two resistors in series with a battery. It is assumed that the two resistors are of equal value.
At first glance it is not clear how Kirchhoff’s Voltage Law applies until you look at the polarity of the voltage. On the left, the battery supplies V volts, which is equal in magnitude, but opposite in direction (and hence sign) to the two voltages V/2 across each resistor.
Another way to look at this is that V must be balanced by the two voltages V/2. In other words, V = V/2 + V/2 or V – (V/2 + V/2) = 0.
This arrangement of a pair of resistors is also used to scale voltages down (see Recipe 2.6).
For Kirchhoff’s Current Law, see Recipe 1.4.
In electronics, power is the rate of conversion of electrical energy to some other form of energy (usually heat). It is measured in Joules of energy per second, which is also known as a watt (W).
When you wire up a resistor as shown back in Figure 1-4 of Recipe 1.3 the resistor will generate heat and if it’s a significant amount of heat then the resistor will get hot. You can calculate the amount of power converted to heat using the formula:
P = I x V
In other words, the power in watts is the voltage across the resistor (in volts) multiplied by the current flowing through it in amps. In the example of Figure 1-4 where the voltage across the resistor is 1.5V and the current through it was calculated as 15mA, the heat power generated will be 1.5V x 15mA = 22.5mW.
If you know the voltage across the resistor and the resistance of the resistor, then you can combine Ohm’s Law and P=IV and use the formula:
With V=1.5V and R of 100Ω the power is 1.5V x 1.5V / 100Ω = 22.5mW.
For Ohm’s Law see Recipe 1.3.
In all the recipes up to this point, DC is assumed. The voltage is constant and generally what you would expect a battery to supply.
AC is what is supplied by wall outlets, and although it can be reduced to lower voltages (see Recipe 3.9) it is generally of a high (and dangerous) voltage. In the US, this means 110V and in most of the rest of the world 220V or 240V.
What puts the alternating in alternating current is the fact that the direction of current flow in AC reverses many times per second. Figure 1-7 shows how the voltage varies in a US AC wall outlet.
The first thing to notice is that the voltage follows the shape of a sine wave, gently increasing until it exceeds 150V then heading down past 0V to around –150V and then back up again, taking about 16.6 thousandths of a second (milliseconds, or ms) to complete one full cycle.
The relationship between the period of AC (time taken for one complete cycle) and the frequency of the AC (number of cycles per second) is:
The unit of frequency is the Hertz (abbreviated as Hz) so you can see that the AC shown in Figure 1-7 has a period of 16.6ms, which is 0.0166 seconds. So you can calculate the frequency as:
You may be wondering why AC from an outlet is described as 110V when it actually manages to swing over a range of over 300V from peak to peak. The answer is that the 110V figure is the equivalent DC voltage that would be capable of providing the same amount of power. This is called the RMS (root mean square) voltage and is the peak voltage divided by the square root of 2 (which is roughly 1.41). So, in the preceding example, the peak voltage of 155V when divided by 1.41 gives a result of roughly 110V RMS.
You will find more information on using AC in Chapter 7.
Resistors are used in almost every electronic circuit, come in a huge variety of shapes and sizes, and are available in a range of values that spans milliohms (thousandths of an ohm) to mega ohms (millions of ohms).
Ohm, the unit of resistance, is usually abbreviated as the Greek letter omega (Ω), although you will sometimes see the letter R used instead. For example, 100Ω and 100R both mean a resistor with a resistance of 100 ohms.
On a through-hole resistor (a resistor with leads) that has colored stripes on it, use the resistor color code.
If your resistor has stripes in the same positions as Figure 2-1 then the three stripes together on the left determine the resistor’s value and the single stripe on the right determines the accuracy of the value.
Each color has a value as listed in Table 2-1.
|
Black |
0 |
|
Brown |
1 |
|
Red |
2 |
|
Orange |
3 |
|
Yellow |
4 |
|
Green |
5 |
|
Blue |
6 |
|
Violet |
7 |
|
Gray |
8 |
|
White |
9 |
|
Gold |
1/10 |
|
Silver |
1/100 |
For a three-stripe resistor such as this, the first two stripes determine the basic value (say 27 in Figure 2-1) and the third stripe determines the number of zeros to add to the end. In the example of Figure 2-1, the value of a resistor with stripes red, purple, and brown is 270Ω. I said before that this stripe indicates the number of zeros, but actually, to be more accurate, it is a multiplier. If it has a value of gold, then this means ⅒ of the value indicated by the first two stripes. So brown, black, and gold would indicate a 1Ω resistor.
The stripe on its own specifies the tolerance of the resistor. Silver (rare these days) indicates ±10%, gold ±5%, and brown ±1%.
If your resistor has stripes as shown in Figure 2-2 then the value of the resistor is specified with an extra digit of precision. In this case, the first three stripes determine the basic value (in the case of Figure 2-2, 270) and the final digit the number of zeros to add (in this case, 0). This resistor is also 270Ω.
For low-value resistors, gold is used as a multiplier of 0.1 and silver of 0.01. A 1Ω four-stripe resistor would have value stripes of brown, black, black, and silver (100 x 0.01).
Through-hole capacitors also have value labels similar to SMT resistors (see Recipe 3.3).
The ±1% E96 series includes all the base values of the E24 series, but has four times as many values. However, it is very rare to need such precise values of resistor.
If your resistor is to limit current to some other component that might be damaged, perhaps limiting the power to an LED (Recipe 4.4) or into the base of a bipolar transistor (Recipe 5.1), then pick the next largest value of resistor from the E24 series.
For example, if your calculations tell you that the resistor should be a 239Ω resistor, then pick a 240Ω resistor from the E24 series.
In reality, you may decide to limit yourself even further to avoid having to gradually collect every conceivable value of resistor, especially as they are often sold in packs of 100. I generally keep the following resistor values in stock: 10Ω, 100Ω, 270Ω, 470Ω, 1k, 3.3k, 4.7k, 10k, 100k, and 1M.
For full details on all of the resistor series available, see http://www.logwell.com/tech/components/resistor_values.html.
A variable resistor, a.k.a. a pot or potentiometer, is made from a resistive track and a slider that varies its position along the track. By varying the position of the slider you can vary the resistance between the slider and either of the terminals at the ends of the track. The most common pots are rotary like the one shown in Figure 2-3.
Pots come in a large variety of shapes and sizes. Figure 2-4 shows a selection of pots.
The two pots on the left of Figure 2-4 are called trimmers or trimpots. These devices are designed to be turned using a screwdriver or by twiddling the tiny knob between the thumb and forefinger.
The next pot is a pretty standard device with a threaded barrel that allows the pot to be fixed into a hole. The shaft can be cut to the length required before fixing a knob to it.
There is a dual-gang pot in the middle of Figure 2-4. This is actually two pots with a common shaft and is often employed in stereo volume controls. After that is a similar looking device that combines a pot with an on/off switch. Finally, on the right is a sliding type of pot, the kind that you might find on a mixing desk.
Pots are available with two types of tracks. Linear tracks have a close to linear resistance across the whole range of the pot. So, at the half-way point the resistance will be half of the full range.
Pots with a logarithmic track increase in resistance as a function of the log of the slider position rather than in proportion to the position. This makes them more suitable to volume controls as human perception of loudness is logarithmic. Unless you are making a volume control for an audio amplifier, you probably want a linear pot.
To connect a pot to an Arduino or Raspberry Pi, see Recipe 12.9.
A potentiometer lends itself to being a variable voltage divider (see Recipe 2.6).
The overall resistance of a number of resistors in series is just the sum of the separate resistances.
Figure 2-5 shows two resistors in series. The current flows through one resistor and then the second. As a pair, the resistors will be equivalent to a single resistor of 200Ω.
The heating power of each resistor will be
.
If you used a single resistor of 200Ω then the power would be:
So, by using two resistors, you can double the power.
You may be wondering why you would ever want to use two resistors in series when you could just use one. Power dissipation may be one reason, if you cannot find resistors of sufficient power.
But there are other situations, such as the one shown in Figure 2-6, where you use a variable resistor (pot) with a fixed resistor to make sure that the combination’s resistance does not fall below the value of the fixed resistor.
Resistors in series are often used to form a voltage divider (see Recipe 2.6).
The combined resistance of a number of resistors in parallel is the inverse of the sum of the inverses of the resistors. That is, if there are two resistors R1 and R2 in parallel, then the overall resistance is given by:
In the example shown in Figure 2-7 with two 100Ω resistors in parallel, the arrangement is equivalent to a single resistor of:
Intuitively, this makes perfect sense, because there are now two equally resistive paths through the resistors instead of one as would be the case with a single resistor.
In Figure 2-7 a single 50Ω resistor is equivalent to the two 100Ω resistors in parallel, but what implications does this have for the power ratings of the two resistors?
Intuitively, you would expect the total power dissipation of two 100Ω resistors to be the same as the two 50Ω resistors, but just to be sure let’s do the math.
For each 100Ω resistor, the power will be:
So the total for the two resistors will be 45mW, allowing you to use lower power and more common resistors.
Just as you’d expect, performing the calculation for the single 50Ω resistor you get:
See Recipe 2.4 for resistors in series.
Use two resistors in series as a voltage divider (also called potential divider). The word “potential” indicates the voltage has the potential to do work and make current flow.
Figure 2-8 shows a pair of resistors being used as a voltage divider.
The output voltage (Vout) will be a fraction of the input voltage (Vin) according to the formula:
For example, if R1 is 470Ω, R2 is 270Ω, and Vin is 5V:
Note that if R1 and R2 are equal then the voltage is divided by 2.
A pot naturally forms a potential divider as you can think of it as two resistors in series whose overall resistance adds up to the same value, but the proportion of the resistance of R1 to R2 varies as you turn the knob. This is just how a pot is used in a volume control.
It may be tempting to think of a voltage divider as useful for reducing voltages in power supplies. However, this is not the case, because as soon as you try to use the output of the voltage divider to power something (a load), it is as if another resistor is being put in parallel with R2. This effectively reduces the resistance of the bottom half of the voltage divider and therefore also reduces the output voltage. This will only work if R1 and R2 are much lower than the resistance of the load. This makes them great for reducing signal levels, but of no use for high-power circuits.
See Chapter 7 for various techniques for reducing voltages in power supplies.
For level shifting with a voltage divider, see Recipe 10.17.
Calculate the power (Recipe 1.6) your resistor will be converting into heat and pick a resistor with a power rating comfortably greater than this value.
For example, if you have a 10Ω resistor connected directly to the terminals of a 1.5V battery, then the power that the resistor converts to heat can be calculated as:
This means that a standard ¼W resistor will be OK, but you may wish to take the next step up to ½W.
The most common power rating of resistor used by hobbyists is the ¼W (250mW) resistor. These resistors are not so tiny that they are hard to handle or the leads too thin to make good contact in breadboard (Recipe 20.1) yet they are capable of handling enough power for most uses, such as limiting current to LEDs (Recipe 14.1) or used as voltage dividers for low current (Recipe 2.6).
Other common power ratings for through-hole resistors with leads are ½W, 1W, 2W, 5W, 10W, and even higher power resistors.
Figure 2-9 shows a selection of resistors of different power ratings.
When it comes to the tiny surface-mount “chip resistors” that are surface mounted onto circuit boards, power ratings start much lower.
To understand power, see Recipe 1.6.
Use a photoresistor.
A photoresistor (Figure 2-10) is a resistor in a clear plastic package whose resistance varies depending on the amount of light falling on it. The more brightly the photoresistor is illuminated, the lower the resistance.
A typical photoresistor might have a resistance in direct sunlight of 1kΩ increasing to several MΩ in total darkness.
Photoresistors are often used in a voltage-divider arrangement (Recipe 2.6) with a fixed-value resistor to convert the resistance of the photoresistor into a voltage that can then be used with a microcontroller (Recipe 12.6) or comparator (Recipe 17.10).
You will find more details on using a photoresistor in Recipe 12.6.
One method is to use a thermistor. Other ways can be found in Recipe 12.10 and Recipe 12.11.
All resistors are slightly sensitive to changes in temperature. However, thermistors (Figure 2-11) are resistors whose resistance is very sensitive to changes in temperature. As with photoresistors (Recipe 2.8), they are often used in a voltage divider (Recipe 2.6) to convert the resistance to a voltage reading that is more convenient.
There are two types of thermistors. NTC (negative temperature coefficient) thermistors are the more common type and their resistance decreases as the temperature increases. PTC (positive temperature coefficient) thermistors have a resistance that increases as the temperature increases.
In addition to being used to measure temperature (see Recipe 12.7) PTC thermistors are also used to limit current. As the current through the thermistor increases, the resistor heats up and thus its resistance increases, reducing the current.
For practical circuits that use a thermistor to measure temperature, see Recipe 12.7 and Recipe 12.8.
Wires all have resistance. A thick copper wire will have a much lower resistance than the same length of a much thinner wire. As someone once said, “the great thing about standards are that there are always lots to choose from.” Nowhere is this more true than for wire thicknesses or gauges. One of the most common standards is AWG (American Wire Gauge) mostly used in the US, and the SWG (Standard Wire Gauge) mostly used in the UK and most logically just the diameter of the wire in mm.
Nearly all wiring used in electronics is made of copper. If you strip the insulation off a wire and it looks silver-colored, then it’s probably still copper, but copper that has been “tinned” to stop it from oxidizing and make it easier to solder.
Table 2-2 shows some commonly used wire gauges along with their resistances in Ω per foot and meter for copper wiring.
| AWG | Diameter (mm) | mΩ/m | mΩ/foot | Max. Current (A) | Notes |
|---|---|---|---|---|---|
| 30 | 0.255 | 339 | 103 | 0.14 | |
| 28 | 0.376 | 213 | 64.9 | 0.27 | |
| 24 | 0.559 | 84.2 | 25.7 | 0.58 | Solid-core hookup wire |
| 19 | 0.95 | 26.4 | 8.05 | 1.8 | General-purpose multicore wire |
| 15 | 1.8 | 10.4 | 3.18 | 4.7 | Thick multicore wire |
The larger the AWG number the thicker the wire. Wires thinner than 24AWG are most likely to be thin enameled wire designed for winding transformers and indictors, like the wire shown in Figure 2-12.
Solid-core wire is made of a single strand of copper insulated in plastic (Figure 2-13). It is useful with solderless breadboards (Recipe 20.1) but should not be used in situations where it is likely to be flexed as it will break through metal fatigue if bent back and forth. I always have this wire in at least three colors so that I can use black for negative, red for positive, and other colors for nonpower connections.
For general-purpose wire where some movement is likely, use multicore wire made up of a number of strands of wire twisted about each other and encased in plastic insulation. Again, it’s useful to have a selection of colors.
The currents listed in Table 2-2 are only suggestions. The actual current that each gauge of wire can carry without getting too hot depends on many factors, including how well ventilated the project’s case is and whether the wires are all grouped together with a whole load of other wires all getting warm. So treat Table 2-2 as a guide.
When you buy wire, the maximum temperature of the insulation will usually be specified. This is not just because of internal heating of the wire but also for situations where the insulation is to be used in hot environments such as ovens or furnaces.
If you are looking for wires to carry high voltages then you will need a good insulation layer. Again, wires will normally have a breakdown voltage specified for the insulation.
For a table comparing wire gauges, see http://bit.ly/2lOyPIh.
For the current-handling capabilities of wire by gauge, see http://bit.ly/2mbgZS8.
When it comes to digital electronics, capacitors are almost a matter of insurance, providing short-term stores of charge that improve the reliability of circuits. As such their use is often simply a matter of following the recommendations in the IC’s datasheet without the need to do any math.
However, when it comes to analog electronics the use of capacitors becomes much more varied. Their ability to store small amounts of charge for a short period of time can be used to set the frequency of oscillators (see Recipe 16.5). They can be used to smooth the ripples for a power supply (see Recipe 7.2) or to couple two audio circuits without transferring the DC part of the signal (see Recipe 17.9).
In fact, capacitors will be used throughout this book in all sorts of ways, so it’s important to understand how they work, how to select the right capacitor, and how to use it.
Inductors are not as common as capacitors, but they are widely used in certain roles, particularly in power supplies (see Chapter 7).
Use a capacitor.
In construction, capacitors are just two conductive surfaces separated by an insulating layer (Figure 3-1).
In fact, the insulating layer between the conductive surfaces of the capacitor can just be air, although a capacitor using an air gap will be of very low value. In fact, the value of the capacitor depends on the area of the conducting plates, how close they are together, and how good an insulator separates them. So the greater the area of the plates and the smaller the distance between them the greater the capacitance (the more charge it can store).
Individual electrons do not flow through a capacitor, but those on one side of the capacitor influence those on the other. If you apply a voltage source like a battery to a capacitor, then the plate of the capacitor connected to the positive supply of the battery will accumulate positive charge and the electric field this generates will create a negative charge of equal magnitude on the opposite plate.
In water terms, you can think of a capacitor as an elastic membrane in a pipe (Figure 3-2) that does not allow water to pass all the way through the pipe, but will stretch, allowing the capacitor to be charged. If the capacitor is stretched too far then the elastic membrane will rupture. This is why exceeding the maximum voltage of a capacitor is likely to destroy it.
When you apply a voltage across a capacitor it will almost instantly charge to that voltage. But if you charge it through a resistor then it will take time to become full of charge. Figure 3-3 shows how a capacitor can be charged or discharged through the use of the switches S1 and S2.
When you close switch S1, C1 will charge through R1 until C1 reaches the battery voltage. Open S1 again and the now charged capacitor will retain its charge. Eventually the capacitor will lose its charge through self-discharge.
If you now close S2, C1 will now discharge through R2 and LED1, which will light brightly at first and then more dimly as C1 is discharged.
If you want to experiment with the schematic diagram of Figure 3-3, then build up the breadboard diagram shown in Figure 3-4. For an introduction to breadboard, see Recipe 20.1. Use 1kΩ resistors and a 100µF capacitor.
Press the button labeled CHARGE for a second or two to charge the capacitor then release the button and press the DISCHARGE button. The LED should glow brightly for a second or so and then dim until it extinguishes after a second or so.
If you were to monitor the voltage across the capacitor while it was first being charged and then discharged, you would see something similar to Figure 3-5.
In Figure 3-5 the square-shaped waveform is the voltage applied to the capacitor through a 1kΩ resistor. For the first 400ms this is 9V. But as you can see the voltage across the capacitor does not increase linearly, but rather increases faster at first and then gradually tails off as the voltage across the capacitor gets closer to the battery voltage.
Similarly, when the capacitor discharges, the voltage decreases sharply at first and then starts to tail off.
So, if a capacitor stores electrical energy, you may be wondering how this differs from a rechargeable battery. Well, in fact a special type of very high capacitance capacitor called a supercapacitor is sometimes used in place of a rechargeable battery for applications that require a very rapid storage and release of energy. The differences between a capacitor and a battery include:
For information on using a solderless breadboard, see Recipe 20.1.
The voltage curves of Figure 3-5 were created using a circuit simulator (Recipe 21.11). You can experiment with this simulation online using PartSim at http://bit.ly/2mrtrhs.
Unless your application needs capacitors with special features, the following rule of thumb applies.
In most cases, for capacitors between 1pF and 1nF use a disc capacitor (Figure 3-6a). For capacitors between 1nF and 1µF use a multilayer ceramic capacitor (MLC; Figure 3-6b) and for capacitors above 1µF use an aluminum electrolytic capacitor (Figure 3-6c). The rightmost capacitor is a tantulum electrolytic capacitor.
Although disc ceramic, MLC, and aluminum electrolytic capacitors are the most commonly used types of capacitor, there are other types:
Capacitors are less reliable than resistors. Exceed the voltage rating and you are likely to damage the insulating layer. Electrolytic capacitors use an electrolyte contained in an aluminum can that creates a very thin layer of oxide as the insulator. These are especially prone to failure due to overvoltage, or overtemperature, or just age. If vintage HiFi equipment fails, it is usually the large electrolytic capacitors in the power supplies that are the cause of the failure. In addition, if an electrolytic capacitor does fail then it can spray out the electrolyte in a somewhat messy manner.
In addition to the actual capacitance of a capacitor, there are a number of other factors to consider when selecting a device. Of critical importance is the voltage rating. Unless you are creating something that uses high voltages, this is not usually a problem with smaller value capacitors, as they are generally rated at least 50V. However, as soon as you get into the range of electrolytics then you will be in a trade-off between capacitor size and voltage. Electrolytic capacitors are commonly available in voltage ratings of 6.3V, 10V, 25V, 30V, 40V, 50V, 63V, 100V, 160V, 200V, 250V, 400V, and 450V. It is unusual to find electrolytic capacitors with a higher voltage rating than 500V.
The temperature rating becomes important when the capacitors are being rapidly charged and discharged, as a capacitor will always have an internal resistance called its equivalent series resistance (ESR) that causes heating during charging and discharging.
Small-value MLC capacitors generally have a very low ESR of little more than the resistance caused by their leads. This allows them to charge and discharge extremely quickly. A high-value electrolytic capacitor might have an ESR of a few hundred mΩ. This both limits the speed at which the capacitors can charge and discharge and causes a heating effect.
For the use of electrolytic capacitors to smooth out voltage ripple from power supplies, see Recipe 7.4.
Small, low-value SMD capacitors are generally unmarked, and so you should label them as soon as you buy them.
Electrolytic capacitors usually have their capacitance value and voltage rating printed on the package. Polarized through-hole electrolytic capacitors are also usually supplied with the positive lead longer than the negative lead and the negative lead marked with a minus sign or a diamond symbol.
Most other capacitors use a numbering system similar to that of SMD resistors. The value is usually three digits and a letter. The first two digits are the base value and the third digit is the number of zeros to follow. The base value being the value in pF (pico Farad; see Appendix D).
For example, a 100pF capacitor would have the three digits 101 (a 1, a 0, followed by one further 0). A 100nF capacitor would be marked 104 (a 1, a 0, followed by four further 0s); that is, 100,000 pF or 100nF.
The letter after the digits indicates the tolerance (J, K, or M for ±5%, ±10%, and ±20%, respectively).
To read resistor color codes, see Recipe 2.1.
Looking at Figure 3-7, you can see two capacitors in parallel double up on the surface area of the conductive plates and therefore may correctly assume that the overall capacitance is the sum of the two capacitances.
It is actually quite common to place a number of capacitors in parallel to increase the overall capacitance. It is especially common when smoothing a high-power transformer-based power supply for, say, an audio amplifier where it is important to remove as much ripple from the power supply as possible (see Recipe 7.2).
In such systems it is common to use a number of different capacitors of different types and values in parallel to minimize the effects of ESR (see Recipe 3.2).
For capacitors in series, see Recipe 3.5.
It is unusual to connect capacitors in series. Occasionally, this will be done as part of a more complex circuit such as in Recipe 7.12.
For capacitors in parallel, see Recipe 3.4.
Supercapacitors are low-voltage capacitors that have extremely high capacitances. They are primarily used as energy-storage devices in situations that would otherwise use rechargeable batteries.
They can have values up into the hundreds of F (Farads). Note that the top of the capacitance range for an aluminum electrolytic is around 0.22F.
Low (comparatively) value supercapacitors of perhaps a few F are sometimes used as alternatives to rechargeable batteries or long-life lithium batteries to power ICs in standby mode to retain memory in static RAM that would otherwise be lost, or to power real-time clock (RTC) chips so a device using an RTC IC will keep the time if it’s powered off for a while.
Extremely high-value supercapacitors are available that offer an alternative to rechargeable batteries for larger capacity energy storage.
Supercapacitors with values of 500F or more can be bought for just a few dollars. The maximum voltage for a supercapacitor is 2.7V so, for higher voltage use, the capacitors can be placed in series with special protection circuitry to ensure the 2.7V limit is not exceeded as the bank of capacitors are charged.
Supercapacitors generally look like standard aluminum electrolytic capacitors. At present, their energy storage is still quite a long way from that of rechargeable batteries and because they are capacitors, the voltage decreases much more quickly than when discharging a battery.
See Recipe 3.7 to calculate the energy stored in super capacitors and normal capacitors.
The energy stored in a capacitor in J is calculated as:
Taking a medium-sized electrolytic of 470µF at 35V the energy stored would be:
which is not very much energy. Since the energy storage is proportional to the square of the voltage, the results for a capacitor of the same value but at 200V are much more impressive:
For a 500F 2.7V supercapacitor, the results are even more impressive:
By way of comparison, a single 1.5V AA battery of 2000mAH stores around:
For information on rechargeable batteries, see Recipe 8.3.
An inductor is, at its simplest, just a coil of wire. At DC, it behaves just like any length of wire and will have some resistance, but when AC flows through it, it starts to do something interesting.
A change in current in one direction in an inductor causes a change in voltage in the opposite direction. This effect is more marked the higher the frequency of the AC flowing through the inductor. The net result of this is that the higher the frequency of the AC, the more the inductor resists the flow of current. So as not to confuse this effect with ordinary resistance, it is called reactance but it still has units of Ω.
The reactance X of an inductor can be calculated by the formula:
Where f is the frequency of the AC (cycles per second) and L is the inductance of the inductor whose units are the Henry (H). This resistive effect does not generate heat like a resistor, but rather returns the energy to the circuit.
The inductance of an inductor will depend on the number of turns of wire as well as what the wire is wrapped around. So, very low-value inductors may be just a couple of turns of wire without any core (called air-core inductors). Higher value inductors will generally use an iron or more likely ferrite core. Ferrite is a magnetic ceramic material.
The current-carrying capability of an inductor generally depends on the thickness of the wire used in the coil.
Inductors are used in switched mode power supplies (SMPS) where they are pulsed at a high frequency (see Recipe 7.8 and Recipe 7.9). They are also used extensively in radio-frequency electronics, where they are often combined with a capacitor to form a tuned circuit (see Chapter 19).
A type of inductor called a choke is designed to let DC pass while blocking the AC part of a signal. This prevents unwanted radio-frequency noise from infiltrating a circuit. You will often find a USB lead has a lump in it near one end. This is a ferrite choke, which is just a cylinder of ferrite material that encloses the cables and increases the inductance of the wire to a level where it can suppress high-frequency noise.
For more information on the use of inductors in SMPSs, see Recipe 7.8 and Recipe 7.9.
See Recipe 3.9 for more information on transformers.
A transformer is essentially two or more inductor coils wrapped onto a single core. Figure 3-8 shows the schematic diagram for a transformer that also gives a clue as to how it works.
A transformer has primary coils and secondary coils. Figure 3-8 shows one of each. The primary coil is driven by AC, say the 110V from an AC outlet, and the secondary is connected to the load.
The voltage at the secondary is determined by the ratio of the number of turns on the primary to the number of turns on the secondary. Thus if the primary has 1000 turns and the secondary just 100, then the AC voltage will be reduced by a factor of 10.
Figure 3-9 shows a selection of transformers. As you can see they come in a wide range of sizes.
In Figure 3-9 there is a small high-frequency transformer on the left that was taken from a disposable flash camera where it was used to step up pulsed DC (almost AC) from a 1.5V battery to the 400V needed by a Xenon flash tube.
The type of transformer shown in the center is commonly used to step-down 110V AC to a low voltage, say 6V or 9V.
The transformer on the right is also designed to step-down AC outlet voltages to lower voltages. It is called a torroidal transformer and the primary and secondary coils are wrapped around a single torroidal former (donut shaped arrangement of iron layers), on top of each other. These transformers are often used in HiFi equipment where the noise found in most SMPSs is considered too high for high-end HiFi amplifiers.
It used to be that if you wanted to power a low-voltage DC appliance such as a radio receiver from an AC outlet, then you would first use a transformer to drop the 100V AC at 60Hz to, say, 9V. You would then rectify and smooth the low-voltage AC into DC.
These days, an SMPS (see Recipe 7.8) is normally used as transformers are expensive and heavy items with iron and long lengths of copper-winding wire. However, transformers are still used in SMPS but operate at a very much higher frequency than 60Hz. Operating at a high frequency (often 100s of kHz) allows the transformers to be much smaller and lighter than low-frequency transformers while retaining good efficiency.
This video shows a torroidal transformer winding machine in action: https://youtu.be/82PpCzM2CUg.
Recipe 7.1 describes how to use a transformer to convert one AC voltage to another.
The first diodes to be used in electronics were cat’s whisker detectors used in crystal radios. These comprised a crystal of a semiconductor material (often lead sulphide or silicon). The cat’s whisker is simply a bare wire that is held in an adjustable bracket that touches the semiconductor crystal. By carefully moving the whisker around, at certain points of contact the arrangement would act as a diode, only allowing current to flow in one direction. This property is needed in a simple radio receiver to detect the radio signal so that it can be heard (see Chapter 19).
Today diodes are much easier to use and come in all sorts of shapes and sizes.
A diode is a component that only allows current to flow through it in one direction. It’s a kind of one-way valve if you want to think of it in terms of water running through pipes, which of course is a simplification. In reality the diode offers very low resistance in one direction and very high resistance in the other. In other words, the one-way valve restricts the flow a tiny bit when open and also leaks slightly when closed. But most of the time, thinking of a diode as a one-way valve for electrical current works just fine.
There are lots of specialized types of diodes, but let’s start with the most common and basic diode, the rectifier diode. Figure 4-1 shows such a diode in a circuit with a battery and resistor.
In this case, the diode allows flow of current and is considered forward-biased. The two leads of the diode are called the anode (abbreviated as “a”) and cathode (abbreviated rather confusingly as “k”). For a diode to be forward-biased, the anode needs to be at a higher voltage than the cathode, as shown in Figure 4-1.
One interesting property of a forward-biased diode is that unlike a resistor, the voltage across it does not vary in proportion to the current flowing through it. Instead, the voltage remains almost constant, no matter how much current flows through it. This varies depending on the type of diode, but is generally about 0.5V.
In the case of Figure 4-1, we can calculate that the current flowing through the resistor will be:
This is only 0.5mA less than if the diode were to be replaced with wire.
In Figure 4-2 the diode is facing the other direction. It is reverse-biased and consequently almost no current will flow through the resistor.
The diode’s one-way effect can be used to convert AC (Recipe 1.7) into DC. Figure 4-3 shows the effect of a diode on an AC voltage source.
This effect is called rectification (see Recipe 7.2). The negative part of the cycle is unused. This still isn’t true DC because even though the voltage never becomes negative it still swings from 0V up to a maximum and back down rather than remain constant. The next stage would be to add a capacitor in parallel with the load resistor that would smooth out the signal to a flat and almost constant DC voltage.
For information on using diodes in power supplies, see Recipe 7.2 and Recipe 7.3.
Figure 4-4 shows different types of diodes. Generally, the bigger the diode package, the greater its power-handling capability. Most diodes are a black plastic cylinder with a line at one end that points to the cathode (the end that should be more negative for forward-biased operation).
The diode on the left of Figure 4-4 is an SMD. The through-hole diodes to the right get larger, the higher the current rating.
There are many different types of diodes. Unlike resistors that are bought as a particular value resistor (say, 1kΩ) diodes are identified by the manufacturer’s part number.
Some of the most commonly used rectifier diodes are listed in Table 4-1.
| Part Number | Typical Forward Voltage | Maximum Current | DC Blocking Voltage | Recovery Time |
|---|---|---|---|---|
| 1N4001 | 0.6V | 1A | 50V | 30µs |
| 1N4004 | 0.6V | 1A | 400V | 30µs |
| 1N4148 | 0.6V | 200mA | 100V | 4ns |
| 1N5819 | 0.3V | 1A | 40V | 10ns |
The forward voltage, often abbreviated as Vf, is the voltage across the diode when forward-biased. The DC-blocking voltage is the reverse-biased voltage that if exceeded may destroy the diode.
The recovery time of a diode refers to how quickly the diode can switch from forward-biased conducting to reverse-biased blocking. This is not instantaneous in any diode and in some applications fast switching is needed.
The 1N5819 diode is called a Schottky diode. These types of diodes have much lower forward voltage and generate less heat.
You can find the datasheet for the 1N4000 family of diodes here: http://bit.ly/2lOtD71.
When forward-biased, Zener diodes behave just like regular diodes and conduct. At low voltages, when reverse-biased they have high resistance just like normal diodes. However, when the reverse-biased voltage exceeds a certain level (called the breakdown voltage), the diodes suddenly conduct as if they were forward-biased.
In fact, regular diodes do the same thing as Zener diodes but at a high voltage and not a voltage that is carefully controlled. The difference with a Zener diode is that the diode is deliberately designed for this breakdown to occur at a certain voltage (say, 5V) and for the Zener diode to be undamaged by such a “breakdown.”
Zener diodes are useful for providing a reference voltage (see the schematic in Figure 4-5). Note the slightly different component symbol for a Zener diode with the little arms on the cathode.
The resistor R limits the current flowing through the Zener diode. This current is always assumed to be much greater than the current flowing into a load across the diode.
This circuit is only well suited to providing a voltage reference. A voltage reference provides a stable voltage but with hardly any load current; for example, when the circuit is used with a transistor as in Recipe 7.4. So a resistor value of, say, 1kΩ would, if Vin was 12V, allow a current of:
The output voltage will remain roughly 5V whatever Vin is as long as it’s greater than 5V. To understand how this happens, imagine that the voltage across the Zener diode is less than its 5V breakdown voltage. The Zener’s resistance will therefore be high and so the voltage across it due to the voltage divider effect of R and the Zener will be higher than the breakdown voltage. But wait, since the breakdown voltage is exceeded it will conduct, bringing the Vout down to 5V. If it falls below that, the diode will turn off and the Vout will increase again.
Zener diodes are also used to protect sensitive electronics from high-voltage spikes due to static discharge or incorrectly connected equipment. Figure 4-6 shows how an input to an amplifier not expected to exceed ±10V can be protected from both high positive and negative voltages. When the input voltage is within the allowed range the Zener will be high resistance and not interfere with the input signal, but as soon as the voltage is exceeded in either direction the Zener will conduct the excess voltage to ground.
Although you would generally use a voltage-regulator IC (see Recipe 7.4), you can use a Zener diode combined with a transistor to act as a voltage regulator.
LEDs are like regular diodes in that when reverse-biased they block the flow of current, but when forward-biased they emit light.
The forward voltage of an LED is more than the usual 0.5V of a rectifier and depends on the color of the LED. Generally a standard red LED will have a forward voltage of about 1.6V.
Figure 4-7 shows an LED in series with a resistor. The resistor is necessary to prevent too much current from flowing through the LED and damaging it.
An LED used as an illuminator will generally emit some light at 1mA but usually needs about 20mA for optimum brightness. The LED’s datasheet will tell you its optimal and maximum forward currents.
As an example, if in Figure 6-5 the voltage source is a 9V battery and the LED has a forward voltage of 1.6V, you can calculate the resistor value needed using Ohm’s Law:
370Ω is not a common resistor value (see Recipe 2.2) so you could pick a 360Ω resistor, in which case the current would be:
which would be just fine.
Finding suitable resistor values for LEDs to limit the current is such a common task that there is really no need to go through these calculations all the time. In Recipe 14.1 you will find a practical recipe for rule-of-thumb selection of current-limiting resistors.
For information on driving different types of LED, see Chapter 14.
Use a photodiode. You can also use a photoresistor (Recipe 2.8) or a phototransistor (Recipe 5.7).
A photodiode is a diode that is sensitive to light. A photodiode usually has a transparent window, but photodiodes designed for infrared use have a black plastic case. The black plastic case is transparent to IR and usefully stops the photodiode from being sensitive to visible light.
Photodiodes can be treated as little tiny photovoltaic solar cells. When illuminated they generate a small current. Figure 4-8 shows how you can use a photodiode with a resistor to produce a small voltage that you could then use in your circuits.
In this circuit, the voltage when illuminated brightly might only be 100mV.
The resistor is necessary so that the small current from the photodiode is converted into a voltage (V=IR). Otherwise, any voltage that you measure will be depend on the resistance (called impedance when not from a resistor) of whatever is measuring the voltage. So, for example, a multimeter with an input impedance of 10MΩ would provide a completely different (and lower) reading than a multimeter with a 100MΩ input impedance.
R1 makes the voltage consistent. The impedance of whatever is connected to the output needs to be much higher in value than R1. If this is an op-amp (see Chapter 17) then the input impedance is likely to be hundreds of MΩ and so will not alter the output voltage appreciably. The smaller you make R1, the lower the output voltage will be, so it’s a matter of striking a balance.
Better sensitivity can be achieved by using the photodiode in a photoconductive mode with a voltage source (Figure 4-9).
Photoresistors (Recipe 12.6) and phototransistors (Recipe 5.7) tend to be used more than photodiodes as they are more sensitive.
Transistors are used to control the flow of a current. In digital electronics this control takes the form of an on/off action, with the transistor acting as an electronic switch.
Transistors are also used in analog electronics where they can be used to amplify signals in a linear manner. However, these days, a better (cheaper and more reliable) way to do this is to use an integrated circuit (chip) that combines lots of transistors and other components into a single convenient package.
This chapter does not cover all types of transistors or semiconductor devices, but instead focuses on the most common ones, which are generally low in cost and easy to use. There are other exotic devices like the unijunction transistors and SCRs (silicon-controlled rectifiers) that used to be popular, but are now seldom used.
The other thing deliberately left out of this cookbook is the usual theory of how semiconductors like diodes and transistors work. If you are interested in the physics of electronics, there are many books and useful resources on semiconductor theory, but just to make use of transistors, you do not really need to know about holes, electrons, and doping N and P regions.
This chapter will concentrate on the use of transistors in their digital role. You will find information on using transistors for analog circuits in Chapter 16.
In this chapter, you will encounter a wide variety of transistors. Appendix A includes pinouts for the transistors used in this chapter and throughout the book.
Use a low-cost bipolar junction transistor (BJT).
BJTs like the 2N3904 cost just a few cents and are often used with a microcontroller output pin from an Arduino or Raspberry Pi to increase the current the pin can control.
Figure 5-1 shows the schematic symbol for a BJT alongside one of the most popular models of this kind of transistor, the 2N3904. The 2N3904 is in a black plastic package called a TO-92 and you will find that many different low-power transistor models come supplied in the TO-92 package.
The transistor is usually shown with a circle around it, but sometimes just the symbol inside the circle is used.
The three connections to the transistor in Figure 5-1 are from top to bottom:
The main current flowing into the collector and out of the emitter is controlled by a much smaller current flowing into the base and out of the emitter. The ratio of the base current to the collector current is called the current gain of the transistor and is typically somewhere between 100 and 400. So for a transistor with a gain of 100, a 1mA current flowing from base to emitter will allow a current of up to 100mA to flow from collector to emitter.
To get a feel for how such a transistor could be used as a switch, build the circuit shown in Figure 5-2 using the breadboard layout shown in Figure 5-3. For help getting started with breadboard tutorial, see Recipe 20.1.
The push switch will turn the LED on when its pressed. Although this could be achieved much more easily by just putting the switch in series with the LED and R2, the important point is that the switch is supplying current to the transistor through R1. A quick calculation shows that the maximum current that could possibly flow through R1 and the base is:
In reality the current is less than this, because we are ignoring the 0.6V between the base and emitter of the transistor. If you want to be more precise, then the current is actually:
This tiny current flowing through the base is controlling a much bigger current of roughly (assuming Vf of LED 1.8V):
Just like a diode, when the BJT is in use there will be an almost constant voltage drop of around 0.5V to 1V between the base and emitter connections of the transistor.
A resistor limiting the current that can flow into the base of the transistor (R1 in Figure 5-2) is essential, because if too much current flows through the base then the transistor will overheat and eventually die in a puff of smoke.
Because the base of a transistor only requries a small current to control a much bigger current, it is tempting to think of the base as having a built-in resistance to a large current flowing. This is not the case, since it will draw a self-destructively large current as soon as its base voltage exceeds 0.6V or so. So, always use a base resistor like R1.
The BJT transistor described earlier is the most common and is an NPN type of transistor (negative positive negative). This is not a case of the transistor being indecisive, but relates to the fact that the transistor is made up like a sandwich with N-type (negative) semiconductor as the bread and P-type (positive) semiconductor as the filling. If you want to know what this means and understand the physics of semiconductors, then take a look at https://en.wikipedia.org/wiki/Bipolar_junction_transistor.
There is another less commonly used type of BJT called a PNP (positive negative positive) transistor. The filling in this semiconductor sandwich is negatively doped. This means that everything is flipped around. In Figure 5-2 the load (LED and resistor) is connected to the positive end of the power supply and switched on the negative side to ground. If you were to use a PNP transistor the circuit would look like Figure 5-4. You can find out more about using PNP transistors in Recipe 11.2.
If the gain of your transistor is not enough, you may need to consider a Darlington transistor (Recipe 5.2) or MOSFET (Recipe 5.3).
If, on the other hand, you need to switch a high-power load then you should consider a power MOSFET (Recipe 5.3) or IGBT (Recipe 5.4).
You can find the datasheet for the popular low-power BJT, the 2N3904, here: http://www.farnell.com/datasheets/1686115.pdf.
Use a Darlington transistor.
A regular BJT will typically only have a gain (ratio of base current to collector current) of perhaps 100. A lot of the time, this will be sufficient, but sometimes more gain is required. A convenient way of achieving this is to use a Darlington transistor, which will typically have a gain of 10,000 or more.
A Darlington transistor is actually made up of two regular BJTs in one package as shown in Figure 5-5. Two common Darlington transistors are shown next to the schematic symbol. The smaller one is the MPSA14 and the larger the TIP120. See Recipe 5.5 for more information on these transistors.
The overall current gain of the pair of transistors in this arrangement is the gain of the first transistor multiplied by the gain of the second. It’s easy to see why this is the case, as the base of the second transistor is supplied with current from the collector of the first.
Although you can use a Darlington transistor in designs just as if it were a single BJT, one effect of arranging the transistors like this is that there are now two voltage drops between the base and emitter. The Darlington transistor behaves like a regular NPN BJT with an exceptionally high gain but a base-emitter voltage drop of twice that of a normal BJT.
A popular and useful Darlington transistor is the TIP120. This is a high-power device that can handle a collector current of up to 5A.
You can find the datasheet for the TIP120 here: http://bit.ly/2mHBQy6 and the MPSA14 here: http://bit.ly/2mI1vXF.
MOSFETs (metal-oxide semiconductor field effect transistors) do not have an emitter, base, and collector, but rather a source, gate, and drain. Like BJTs, MOSFETs come in two flavors: N-channel and P-channel. It is the N-channel that is most used and will be described in this recipe. Figure 5-6 shows the schematic symbol for an N-channel MOSFET with a couple of common MOSFETs next to it. The larger transistor (in a package called TO-220) is an FQP30N06 transistor capable of switching 30A at 60V. The hole in the TO-220 package is used to bolt it to a heatsink, something that is only necessary when switching high currents. The small transistor on the right is the 2N7000, which is good for 500mA at 60V.
Rather than multiply a current in the way that a BJT does, there is no electrical connection between the gate and other connections of the MOSFET. The gate is separated from the other connections by an insulating layer. If the gate-drain voltage exceeds the threshold voltage of the MOSFET, then the MOSFET conducts and a large current can flow between the drain and source connections of the MOSFET. The threshold voltage varies between 2V and 10V. MOSFETs designed to work with digital outputs from a microcontroller such as an Arduino or Raspberry Pi are called logic-level MOSFETs and have a gate-threshold voltage guaranteed to be below 3V.
If you look at the datasheet for a MOSFET you will see that it specifies on and off resistances for the transistor. An on resistance might be as low as a few mΩ and the off resistance many MΩ. This means that MOSFETs can switch much higher currents than BJTs before they start to get hot.
You can calculate the heat power generated by the MOSFET using the current flowing through it and its on resistance using the following formula. For more information on power, see Recipe 1.6.
The schematic and breadboard layout used in Recipe 5.1 needs a little modification to be used to experiment with a MOSFET. The variable resistor is now used to set the gate voltage from 0V to the battery voltage. The revised schematic and breadboard layouts are shown in Figures 5-7 and 5-8, respectively.
With the trimpot’s knob at the 0V end of its track, the LED will not be lit. As the gate voltage increases to about 2V the LED will start to light and when the gate voltage gets to about 2.5V the LED should be fully on.
Try disconnecting the end of the lead going to the slider of the pot and touch it to the positive supply from the battery. This should turn the LED on, and it should stay on even after you take the lead from the gate away from the positive supply. This is because there is sufficient charge sitting on the gate of the MOSFET to keep its gate voltage above the threshold. As soon as you touch the gate to ground, the charge will be conducted away to ground and the LED will extinguish.
Since MOSFETs are voltage- rather than current-controlled devices you might be surprised to find that under some circumstances you do have to consider the current flowing into the gate. That is because the gate acts like one terminal of a capacitor. This capacitor has to charge and discharge and so when pulsed at high frequency the gate current can become significant. Using a current-limiting resistor to the gate will prevent too much current from flowing.
Another difference between using a MOSFET and a BJT is that if the gate connection is left floating, then the MOSFET can turn on when you aren’t expecting it. This can be prevented by connecting a resistor between the gate and source of the MOSFET.
To use MOSFETs with a microcontroller output, see Recipe 11.3.
To use a MOSFET for polarity protection, see Recipe 7.17.
For level shifting using a MOSFET, see Recipe 10.17.
For the use of heatsinks, see Recipe 20.7.
An IGBT (insulated gate bipolar transistor) is an exotic type of transistor found in high-power, high-voltage switching applications. They are fast switching, and generally are particularly well specified when it come to operating voltage. Switching voltages of 1000V are not uncommon.
A BJT has base, emitter, and collector; a MOSFET has a gate, source, and drain; and an IGBT combines the two, having a gate, emitter, and collector. Figure 5-9 shows the schematic symbol for an IGBT alongside two IGBTs. The smaller of the two (STGF3NC120HD) is capable of switching 7A at 1.2kV and the even bigger one (IRG4PC30UPBF) 23A at 600V.
IGBTs are voltage-controlled devices just like a MOSFET, but the switching side of the transistor behaves just like a BJT. The gate of an IGBT will have a threshold voltage just like a MOSFET.
IGBTs are sometimes used in the same role as high-power MOSFETs but have the advantage over MOSFETs of being able to switch higher voltages at equally large currents.
For information on BJTs see Recipe 5.1 and for MOSFETS see Recipe 5.3.
You can find the datasheet for the STGF3NC120HD here: http://bit.ly/2msNM6v.
The IRG4PC30UPBF datasheet is here: http://bit.ly/2msXTb9.
Stick to a basic set of go-to transistors for most applications until you have more unusual requirements and then find something that fits the bill.
A good set of go-to transistors is shown in Table 5-1.
| Transistor | Type | Package | Max. Current | Max. Volts |
|---|---|---|---|---|
| 2N3904 | Bipolar | TO-92 | 200mA | 40V |
| 2N7000 | MOSFET | TO-92 | 200mA | 60V |
| MPSA14 | Darlington | TO-92 | 500mA | 30V |
| TIP120 | Darlington | TO-220 | 5A | 60V |
| FQP30N06L | MOSFET | TO-220 | 30A | 60V |
When shopping for an FQP30N06L, make sure the MOSFET is the “L” (for logic) version, with “L” on the end of the part name; otherwise, the gate-threshold voltage requirement may be too high to connect the gate of the transistor to a microcontroller output especially if it is operating at 3.3V.
The MPSA14 is actually a pretty universally useful device for currents up to 1A, although at that current there is a voltage drop of nearly 3V and the device gets up to a temperature of 120°C! At 500mA, the voltage drop is a more reasonable 1.8V and the temperature 60°C.
To summarize, if you only need to switch around 100mA then a 2N3904 will work just fine. If you need up to 500mA, use an MPSA14. Above that, the FQP30N06L is probably the best choice, unless price is a consideration, because the TIP120 is considerably cheaper.
Reasons for straying from the transistors listed in Table 5-1 include:
For information on BJTs see Recipe 5.1, for MOSFETs Recipe 5.3, and for IGBTs Recipe 5.4.
To decide on a transistor for switching with an Arduino or Raspberry Pi, see Recipe 11.5.
Once you start to push transistors beyond a light load, you will find that they start to get hot. If they get too hot they will burn out and be permanently destroyed. To avoid this, either use a transistor with greater current-handling capability or fix a heatsink to it (Recipe 20.7).
TRIAC (TRIode for alternating current) is a semiconductor-switching device designed specifically to switch AC.
BJT and MOSFETs are not useful for switching AC. They can only do that if you split the positive and negative halves of the cycle and switch each with a separate transistor. It is far better to use a TRIAC that can be thought of as a switchable pair of back-to-back diodes.
Figure 5-10 shows how a TRIAC might be used to switch a high AC load using a small current switch. A circuit like this is often used so that a small low-power mechanical switch can be used to switch a large AC current.
The 110V or 220V AC that you find in your home kills thousands of people every year. It can burn you and it can stop your heart, so please do not attempt to build the circuits described here unless you are absolutely sure that you can do so safely.
Also, see Recipe 21.12.
When the switch is pressed a small current (tens of milliamps) flows into the gate of the TRIAC. The TRIAC conducts and will continue conducting until the AC crosses zero volts again. This has the benefit that the power is switched off at low power when the voltage is close to zero, reducing the power surges and electrical noise that would otherwise occur if switching inductive loads like motors.
However, the load could still be switched on at any point in the circuit, generating considerable noise. Zero-crossing circuits (see Recipe 5.9) are used to wait until the next zero crossing of the AC before turning the load on, reducing electrical noise further.
See Recipe 1.7 on AC.
For information on solid-state relays using TRIACs, see Recipe 11.10.
TRIACs are usually supplied in TO-220 packages. For pinouts, see Appendix A.
A phototransistor is essentially a regular BJT with a translucent top surface that allows light to reach the actual silicon of the transistor. Figure 5-11 shows how you can use a phototransistor to produce an output voltage that varies as the level of light falling on the transistor changes.
When the photoresistor is brightly illuminated, it will turn on and conduct, pulling the output voltage toward 0V. In complete darkness, the transistor will be completely off and the output voltage will rise to the supply voltage of 5V.
Some phototransistors look like regular transistors with three pins and a clear top and others (like the TEPT5600 used in Figure 5-11) come in LED-like packages with pins for the emitter and collector, but no pin for the base. For phototransistors that look like LEDs, the longer pin is usually the emitter. Phototransistors are nearly always NPN devices.
As a light-sensing element, the phototransistor is more sensitive than a photodiode and responds more quickly than a photoresistor. Phototransistors have the advantage over photoresistors that they are manufactured using cadmium sulphide and some countries have trade restrictions on devices containing this material.
The output of the circuit of Figure 5-11 can be directly connected to an Arduino’s analog input (Recipe 10.12) to take light readings as an alternative to using a photoresistor (Recipe 12.3 and Recipe 12.6).
For the TEPT5600 datasheet, see http://bit.ly/2m8vhS0.
Use an opto-coupler, which consists of an LED and phototransistor sealed in a single lightproof package.
Figure 5-12 shows how an opto-coupler can be used. When a voltage is applied across the + and – terminals, a current flows through the LED and it lights, illuminating the phototransistor and turning on the transistor. This brings the output down to close to 0V. When the LED is not powered, the transistor is off and R1 pulls the output up to 5V.
The important point is that the lefthand side of the circuit has no electrical connection to the righthand side. The link is purely optical.
When the sensing transistor is a TRIAC (see Recipe 5.6) the device is known as an opto-isolator rather than opto-coupler and the low-power TRIAC inside the opto-isolator can be used to switch AC using a more powerful TRIAC as shown in Figure 5-13. This circuit is often called an SSR (solid-state relay) as it performs much the same role as a relay would in AC switching, but without the need for any moving parts.
You should not work with high voltages unless you are completely sure that you can do so safely and understand the risks. See Recipe 21.12 for more information on working with high voltages.
R1 is used to limit the current flowing into the gate of the opto-isolator and R2 keeps the TRIAC MT1 turned off until the TRIAC in the opto-isolator is turned on by light falling on it because of the LED being energized. R3 and C1 form a filter to reduce the RF noise that would otherwise be generated by the switching. Note that R3 and C1 must both be rated to cope with the peak AC voltage (use 400V devices).
The MOC3032 package also contains a zero-crossing switch that stops the TRIAC from turning on until the AC crosses 0V. This greatly reduces the interference generated by the switching circuit.
For SSRs use opto-isolators, see Recipe 11.10.
For the MOS3032 datasheet, see http://www.farnell.com/datasheets/2151740.pdf.
For relays that also isolate the control side from the power side, see Recipe 6.4.
ICs will be involved in almost every project you are likely to work on. Be it a microcontroller or special-purpose chip for motor control or a radio receiver or audio amplifier, there is probably a chip for it. There is little point in building a circuit out of transistors and other components if there is a single IC that will do the job. You will find many different sorts of IC scattered throughout this book.
ICs come in many different shapes and sizes. Figure 5-14 shows a selection of them.
ICs can have as few as three pins or hundreds of pins. You will often find that the same basic IC is available in different packages, both SMD and through-hole packages. This can be very useful if you plan to prototype your design using a solderless breadboard before manufacturing using SMD components.
Another way of using SMDs on a solderless breadboard is to use a “breakout board” that allows you to solder the SMD onto a board and then plug that board into the breadboard. There is an example of this shown in Figure 18-5.
ICs are identified by their part number, which is often difficult to read, so it’s a good idea to label the bag the IC comes in.
ICs with more than three pins will have a little dot next to pin 1. If there is no dot, then there will be a notch that indicates the top of the IC. The pin numbering then moves down the IC to the bottom continuing with the bottom pin of the righthand side. For some example IC pinouts, see Appendix A.
You can find a list of the ICs used in this book in “Integrated Circuits”.
Mechanical switches allow the flow of current to be turned on and off by flipping a toggle from one position to another or by pressing a button. They are so simple that they require little in the way of explanation other than to describe the various types of switches available and to highlight their limitations.
Relays long predate transistors as a means of using a small current to switch to a much bigger one. However, their flexibility and separation of the control side from the switching side mean that they are still in use today.
Switches generally work by mechanically bringing together two metal contacts. Figure 6-1 shows how this might work.
When the push button is pressed, it presses the sprung metal contact at the top to the fixed contact in the base of the switch.
There are several things that can make switching less straightforward than you might expect:
For these reasons switches have a maximum voltage and current, and there are often separate maximums for switching AC and DC.
For a discussion of the various types of switch, see Recipe 6.2.
Figure 6-2 shows a selection of switches.
The switches from left to right are:
If you are designing a project, then you are probably most likely to be using a microcontroller of some sort, in which case a simple push switch is all that is required. Even if you have a situation where you might want to use a switch to select between two options, chances are you would use a pair of push switches and some feedback as to which is selected in a display.
Slide and toggle switches have mostly been relegated to the role of switching power on and off to the project, although you will occasionally find them on circuit boards as “selector” switches.
Toggles (and other switches) are available in many different switching configurations. Some of those described include DPDT, SPDT, SPST, and SPST. These letters stand for:
A DPDT switch is double pole, double throw. The word pole refers to the number of separate switch elements that are controlled from the one mechanical lever. So, a double-pole switch can switch two things on and off together. A single-throw switch can only open or close a contact (or two contacts if it is a double pole). However, a double-throw switch can make the common contact be connected to one of two other contacts. Figure 6-3 shows some of these configurations.
As seen in Figure 6-3 when drawing a schematic with a double-pole switch, it is common to draw the switch as two switches (S1a and S1b) and connect them with a dotted line to show that they are linked mechanically.
The matter is further complicated because you can have three poles or more on a switch, and double-throw switches are sometimes sprung, and do not stay in one or both of these positions. They may also have a center-off position where the common contact is not connected to any other contact.
Another kind of switch that you may encounter is the rotary switch. This has a knob that can be set to a number of positions. If you have a multimeter, then this is the kind of switch that you will use to select the range. Such switches are not often used. Rotary encoders coupled with a microcontroller (Recipe 12.2) are the more modern way of making a selection using a control knob that you turn.
To use switches with an Arduino or Raspberry Pi, see Recipe 12.1.
A reed switch is made up of a pair of contacts running parallel to each other that are close but not touching. The contacts are enclosed in a glass capsule and when a magnet is brought close to the contacts they are drawn together, closing the switch.
Figure 6-4 shows a reed switch with and without a magnet next to it.
Reed switches are often found in intruder alarms on doors and windows. A fixed magnet is attached to the door and the reed switch to the door frame. When the door is opened, the magnet moves away from the reed switch, triggering the alarm.
Reed switches are also found in reed relays but are rarely used these days.
An electromechanical relay has two parts, a coil that acts as an electromagnet and switch contacts that close when the coil is energized. Figure 6-5 shows a relay, along with the pinout of the relay and a photo of an actual relay.
Although somewhat old-fashioned, relays are still in use today. They are equally happy switching AC or DC and are easily interfaced to a microcontroller.
If you take a relay apart, you will probably see something like Figure 6-6.
Here you can clearly see the coil that forms the electromagnet that when energized will move the contacts seen at the top.
The electromagnet of a relay is a big coil of wire and when released will produce a voltage spike that should be snubbed using a diode (see Recipe 11.9).
See Recipe 11.9 for information on using a relay with an Arduino or Raspberry Pi.
Today SSRs are often used in place of electromechanical relays (see Recipe 11.10).
Anything electronic needs a source of power. This may be as simple as a battery, but often will involve reducing high-voltage AC to the normal 1–12V DC that most electronics use.
Sometimes you need to generate higher voltages from a low-voltage battery. This may be stepping up the supply from a single 1.5V AA battery to a 6 or 9V, or it may be to generate much higher voltages for applications such as the 400V to 1.5kV supply needed by Geiger-Müller tubes.
The ultimate high-voltage power supply is a solid-state Tesla coil (see Recipe 7.15).
This is the first chapter where you will encounter a fair selection of ICs. When using an IC that you are not familiar with, your first port of call should be its datasheet. It will not only tell you how to avoid destroying it (by making sure you do not exceed its maximum ratings) but will also tell you how it behaves and if you are lucky will often include “reference designs” that are complete circuits that use the chip in a practical situation. These designs are developed by the chip manufacturer to show you how to use the IC, and many of the recipes in this chapter start from such reference designs.
If the datasheet for the IC does not include such useful designs, then the next thing to search for is “application notes” for the IC. This will often expand the rather terse and scientific-looking datasheet into practical circuits using the IC.
Use a transformer (see Recipe 3.9).
When buying a transformer designed for 60Hz AC, you will often find the windings in an arrangement something like the one shown in Figure 7-1.
This has two identical primary coils and two identical secondary coils, all wound on the same former (laminated iron frame). This allows some flexibility in how the transformer is used. For example, US electricity is 110V whereas much of the world uses 220V AC. If you are designing a product and need the same low-voltage AC output whether the input is 100V or 220V, then two primary coils allow you to do this if you power the primaries in parallel for 110V and series for 220V.
The dual secondaries provide similar flexibility to wire in series for double the output voltage.
Transformers are only rated to handle a certain amount of power. The resistance of the windings causes them to heat as current flows through them, and if things get too hot the insulation on the wire will break down and the transformer will fail.
A transformer will normally be rated as so many VA (volt amps). For most loads connected to a transformer 1VA is the same as 1Watt, but if large inductive loads like motors are being driven, then the current and voltage become out of phase and the apparent power will be lower than the VA rating.
For an introduction to transformers, see Recipe 3.9.
Reducing the AC voltage is often the first step in making an unregulated power supply, which is the topic of Recipe 7.2.
Use an AC step-down transformer (see Recipe 7.1) and then rectify and smooth the output.
Figure 7-2 shows one schematic for the simplest method of achieving this.
The output voltage in Figure 7-2 is shown as 9V. This will be 1.42 (square root of 2) of the stated output voltage of the transformer.
The diode D rectifies the low-voltage AC from the transformer (see Recipe 4.1). The capacitor C then smooths this out to a constant DC that theoretically will be the peak voltage from the cathode of the diode. The diode will prevent the capacitor from discharging back through the transformer and so once it is at the peak voltage it will stay there.
The schematic of Figure 7-2 is missing any kind of load. The capacitor is being charged to the peak voltage, but nothing is using that charge. When you add a load to the output as shown in Figure 7-3 the capacitor will still be receiving its kicks of voltage from the diode and transformer, but now it will be discharging through the load at the same time.
When using power supplies you will hear the use of the word “load,” which is the thing that is being powered by the power supply. When thinking about how the power supply will operate, you can just think of this load as a resistance. In Figure 7-3 the load is represented by R.
The characteristic voltage drop during each cycle due to the load discharging C is called the ripple voltage.
The size of this ripple voltage can be calculated from the load current and also from the size of the capacitor according to this formula:
where I is the current in amps, f is the AC frequency (60Hz), and C is the capacitance in Farads.
As an example, if the load current is 100mA, a 1000µF capacitor would reduce the ripple voltage to:
Notice that the ripple voltage is proportional to the load current, so in the preceding example, a current of 1A would result in a ripple voltage of 8.3V!
This state of affairs can be improved by using a full-wave rectifier as described in Recipe 7.3, which effectively doubles the frequency f in the preceding formula, halving the ripple voltage.
For full-wave rectification, see Recipe 7.3.
The half-wave rectification of Recipe 7.2 is not very efficient. You want to reduce the ripple voltage by using full-wave rectification.
There are two solutions to this:
Figure 7-4 shows how you can make use of both the positive and negative halves of the AC cycle.
The secondary windings are in serial, with the central connection between the windings becoming the ground of the DC output. When the end of the winding connected to D1 is at its maximum, the end of the winding connected to D2 will be at its minimum (greatest negative value). D1 and D2 will take it in turn to provide positive voltage to the capacitor and the whole AC cycle can contribute to charging the capacitor. Figure 7-5 shows the full-wave rectified output before it is smoothed by the capacitor. It is as if the negative cycles are being reversed.
If you only have a single secondary winding, then you can still achieve full-wave rectification by using an arrangement of four diodes called a bridge rectifier. Figure 7-6 shows an unregulated DC power supply using a bridge rectifier.
To understand how this works, imagine that point A is positive and B is negative. This will allow current to flow from A through D2 to charge the capacitor. If there is a load on the power supply, then the current from the negative side of the DC output will be able to flow back through D4 to B.
When the AC cycle flips polarity and it is B that is positive and A negative, then the positive DC output is supplied through D3 and returns to A through D1.
In Recipe 7.2 you saw how the ripple voltage halves if you use full-wave rectification rather than half-wave. The ripple voltage can be reduced by using very large capacitors, but in most circumstances it is better to use a regulated power supply as described in Recipe 7.4 or a switched mode power supply (SMPS), as discussed in Recipe 7.8.
You can buy a bridge rectifier as a single component that contains the four diodes wired up in a bridge configuration. This simplifies the wiring of your power supply as the bridge rectifier will have four terminals: two marked with a ~ to indicate AC input as well as + and – terminals for the rectified output.
To learn about half-wave rectification, see Recipe 4.1 and Recipe 7.2.
Use a linear voltage regulator IC after your unregulated DC power supply.
Figure 7-7 shows such a circuit. As you can see, the first stage of the project is just an unregulated power supply.
A linear voltage regulator IC such as the very common 7805 regulator has three pins:
In the case of the 7805, the output voltage is fixed at 5V, so as long as the input voltage is above about 7V the output will not have any significant ripple voltage (because the regulator chip needs about 2V more than its output voltage of 5V to successfully regulate the voltage).
At first sight, since C1 and C2 are in parallel, it is not immediately obvious why you would need both. However, the reason is that C1 will be a large electrolytic capacitor (470µF or more) and C2 will be a smaller MLC (typically 330nF) with a low ESR that should be positioned as close as possible to the voltage regulator. C2 along with C3, which is typically 100nF, are required by the voltage regulator IC to ensure that the regulation remains stable.
In selecting values for C2 and C3, it is best to consult the datasheet for the voltage-regulator IC that you are using. This will normally specify values for the capacitors as well as tell you other important properties of the voltage regulator such as:
Some linear voltage regulators are described as low-dropout (LDO). These have a much smaller dropout voltage than the 2V of the 7805. Some only need as little as 150mV more at the input than the output. If the input voltage of the regulator does fall below the dropout voltage, the output voltage will gradually decrease as the input voltage decreases. These regulators such as the LM2937, which has a dropout of 0.5V, are great if your input voltage is unavoidably close to the desired output. Perhaps you have a 6V battery and require a 5V output. Keeping the input voltage close to the output voltage also helps to reduce the heat generated by the regulator.
Voltage regulators are available in various packages from tiny surface-mount devices to larger packages such as the TO-220 package of the 7805, which are designed to be bolted to a heatsink for higher current use.
Most voltage regulators including the 7805 have protection circuitry that monitors the device’s temperature and if it gets too hot, it drops the output voltage and therefore limits the output current so that the device is not destroyed by the heat. Voltage regulators also have a mounting hole designed to be attached to a heatsink. This is not needed for low currents, but as the current gets higher a heatsink (see Recipe 20.7) will become necessary.
The 05 part of the 7805 refers to the output voltage and, as you might expect, you can also find 7806, 7809, 7812, and other voltages up to 24V. There is also a parallel 79XX range of negative voltage regulators should you need to provide regulated positive and negative power supplies as you do for some analog applications.
The 78LXX range of regulators are a lower-power (and smaller package) version of the 78XX regulators.
You can find the datasheet for the 7805 here: https://www.fairchildsemi.com/datasheets/LM/LM7805.pdf.
These days, most regulated AC-to-DC power supplies use SMPS design (Recipe 7.8).
Use an adjustable voltage regulator like the LM317.
Figure 7-8 shows a typical schematic for a variable output voltage regulator using the LM317.
The output voltage of the LM317 varies according to the formula:
This only holds true as long as R2 is relatively low resistance (less than 10kΩ).
So, if R1 is 270Ω and R2 is a 2kΩ pot, then at one end of the pot’s travel, the output voltage will be:
When the pot’s knob is rotated fully the other way, the output voltage will be:
As R2 increases, the output voltage also increases, but as with a fixed-output regulator, the regulator requires some spare voltage to do the regulating with. In the case of the LM317, this is about 1.5V less than the input voltage.
Adjustable voltage regulators like the LM317 are available in a number of different-sized packages and able to handle different amounts of current before their temperature-protection circuitry kicks in to prevent damage to the IC.
You can find the datasheet for the LM317 here: http://www.ti.com/lit/ds/symlink/lm317.pdf.
To use an LM317 as a current regulator, see Recipe 7.7.
Use a fixed linear voltage regulator as shown in Figure 7-9.
New batteries have a voltage that often starts a little higher than the rated voltage (perhaps 9.5V for a 9V battery). This voltage drops as the battery is used. A 9V battery will quickly fall to 8V and will probably only provide useful power until it falls to perhaps 7.5V as it’s almost completely empty.
A voltage regulator can be used to provide constant output voltage during the lifetime of the battery and also to reduce voltage to a specific voltage needed for a microcontroller (usually 3.3V or 5V).
Unlike the transformer-based DC supply of Recipe 7.4 a battery does not suffer from ripple voltage, so the capacitor at the input to the voltage regulator can be omitted. However, the capacitor at the output is still needed in most applications as the load is likely to vary a lot and could cause instability in the regulator.
For more information on batteries, see Chapter 8.
Use an LM317 voltage regulator configured in constant-current mode as shown in Figure 7-10.
For the LM317 chip, the output current is set by the value of R1 using the formula:
So, to limit the current to a maximum of 100mA the resistor value would be chosen using:
This circuit will automatically raise and lower the output voltage to keep the current at the desired level.
To see this circuit limit the power to a high-power LED, see Recipe 14.2.
Use a switching voltage-regulator IC like the one in the schematic shown in Figure 7-11.
The LM2596 can provide a regulated power supply at 3A without needing a heatsink.
The FB (feedback) pin allows the regulator to monitor the output voltage and adjust the width of the pulses to keep the voltage constant. The EN (enable) pin can be used to turn the IC on and off.
Linear regulators as described in Recipe 7.4, Recipe 7.5, and Recipe 7.6 suffer from the disadvantage that they simply burn off the excess voltage as heat, which means they get hot and also waste energy.
Switching regulator designs such as the buck regulator shown in Figure 7-11 operate at 85% efficiency almost independently of the input voltage. By comparison, a linear regulator with a high input voltage and a low output voltage may only have an efficiency of perhaps 20 to 60%.
In a similar manner to PWM (see Recipe 10.8) a buck converter uses a transistor to switch power to an inductor that stores the energy of each pulse at a high frequency (150kHz for the LM2596). The longer the pulse the higher the output voltage. A feed-back mechanism changes the pulse length in response to the output voltage, ensuring a constant output.
It makes little sense to design a switching power supply from discrete components when there are ICs like the LM2596 that will do the whole thing so well.
There are many switching voltage-regulator ICs available and generally their datasheet will include a well-designed application circuit and sometimes even a circuit board layout.
If you are making a one-off project, then it is worth considering buying a ready-made switching-regulator module, either from eBay or suppliers like Adadruit and Sparkfun that specialize in modules.
You can find the datasheet for the LM2596 here: http://bit.ly/2lOLtHc.
Use a boost-converter IC as the basis for a design like the one shown in Figure 7-12.
This design will produce an output voltage of 5V from an input voltage of between 0.9V and 5V at 90% efficiency.
The SW (switch) output of the IC is used to send pulses of current through the inductor L1 generating high-voltage spikes that charge C1. The output VOUT is monitored through the FB (feedback) pin via the voltage divider formed by R1 and R2 that sets the output voltage.
The potential divider formed by R1 and R2 sets the output voltage. The value of R2 should be fixed at 180kΩ and the value of R1 calculated using the formula:
There are many similar boost-converter ICs available. In all cases, read the datasheet carefully as it will include a reference design and guides for finding the correct values for external components.
The datasheet for the TPS61070 can be found here: http://www.ti.com/lit/ds/symlink/tps61070.pdf.
Use an inverter. These devices use an oscillator to drive a transformer and generate high-voltage AC from low-voltage DC.
An inverter generates high-voltage AC, high enough voltage and current to stop your heart. So, do not attempt to make an inverter unless you are absolutely certain you have the knowledge and skills to do so safely.
Generating 110V from a low-voltage source (say a 12V car battery) is in theory very simple, but unless you really want to make such a thing yourself, it is generally cheaper and safer to buy a ready-made inverter product.
For more information on working with high voltages, see Recipe 21.12.
If you really do wish to make yourself an inverter, Figure 7-13 shows a typical schematic.
This design uses the CD4047 timer IC as an oscillator. This IC provides a similar function to the much more famous 555 timer (see Recipe 7.13, Recipe 7.14, and several recipes in Chapter 16) but has the advantage that it has both normal and inverted outputs. These two ouputs each drive an NPN Darlington power transistor to energize one half of the primary coil in turn.
The transformer used here is the kind used in recipes such as Recipe 7.1 to step down an AC voltage, but in this case, it will be used to step the voltage up. The windings that would normally be used as the secondary side of the transformer will be driven by the transistors and the output from the transformer will be taken from the coil that would normally have been connected to AC.
To drive the circuit from 12V DC at 60Hz to produce a 110V AC output you need a transformer with a 12-0-12V secondary and a 110V primary.
The power to the CD4047 is supplied through a 100Ω resistor (R5) and a 100µF decoupling capacitor (C3; see Recipe 15.1) across the IC’s power supply. These reduce noise on the power supply to the CD4047.
Figure 7-14 shows the inverter built on a breadboard. This arrangement is fine as a first prototype, but in practice the design would be better built onto a circuit board and the power transistors attached to sizeable heatsinks (Recipe 20.7). It would also be wise to include a fuse in the 12V supply line to limit the current to a value that the transistors can handle, otherwise the transistors could overheat and die.
The transformer used is a toroidal type that I had available, but any type of transformer can be used.
For information on using a 4047 IC see its datasheet.
To learn about fuses, see Recipe 7.16.
To build circuits using a solderless breadboard, see Recipe 20.1.
See Recipe 3.9 for more information on transformers.
You want to power your project from 110V or 220V AC supply efficiently, without using a large transformer like the one used in Recipe 7.2.
Designing SMPSs intended for high-voltage use is a specialized and potentially dangerous activity. Aside from the always present danger of electric shock, a poorly designed SMPS can easily overheat and become a fire hazard.
For these reasons, I strongly suggest that when you need to power a project from AC, use a ready-made commercial SMPS “wall wart” power adapter and fit a DC barrel jack socket to your project. These sealed adapters are readily available and made in such quantities that they will almost certainly be cheaper to buy than to make.
It is interesting to see how these power supplies work. Figure 7-15 shows how such a power supply can achieve the same power output of a transformer-based design (Recipe 7.2) with perhaps ⅒th of the weight.
The high-voltage AC input is rectified and smoothed to produce high-voltage DC in the same way as Recipe 7.2 but without using a transformer first. This DC is then “chopped” or switched at high frequency (often around 60kHz) into a series of short pulses that then feed an output transformer that steps down the high-frequency AC. The resulting low-voltage AC is then rectified and filtered into low-voltage DC. Because the transformer operates at such a high frequency, it can be made much smaller and lighter than a 60Hz transformer.
Voltage regulation is achieved by feedback from the DC output to the controller that alters the width of the pulses being chopped that in turn alters the DC output voltage.
To keep the DC output isolated from the high-voltage AC, the feedback path to the controller uses an opto-isolator (Recipe 5.8).
This might seem like a lot of extra complexity, but the size, weight, and cost advantages of reducing the transformer size is enough to make SMPSs worthwhile.
Although there are ICs that do a lot of the work of an SMPS, they still require quite a few external components such as an opto-isolator and a high-frequency transformer.
Another advantage of SMPSs over transformer-based power supplies is that they can generally accept input voltages from 80–240V, and if the input voltage is higher, you just end up with shorter pulses to generate the same output voltage.
For the old-fashioned transformer-based approach to AC to low-voltage DC conversion, see Recipe 7.2.
For more information on transformers see Recipe 3.9 and for opto-isolators see Recipe 5.8.
This is a job for the very elegant voltage-multiplier circuit, which uses a ladder of diodes and capacitors to increase the voltage without the use of inductors. It can be built in multiple stages to increase the voltage by different multiples. The schematic of Figure 7-16 shows a four-stage voltage multiplier that will multiply the AC voltage by 4.
To understand how this circuit works, consider what happens at the peak positive and negative value of the AC inputs. When the input is at its negative maximum, C1 will be charged through D1. On the next positive maximum, C1 will still be charged to the peak, but now, the input will be effectively added to C1. If we stopped there this would be a voltage doubler, but now C2 will charge from the next negative peak and so on until the output is at four times the peak input voltage.
The diodes should all be specified with a maximum voltage greater than the RMS AC input voltage times 1.4 (peak voltage). When selecting the capacitors (which should all be of the same value), you have a similar problem to that of selecting a smoothing capacitor in Recipe 7.2. If there is no load on the output then you can use very low value capacitors, but as soon as you add a load, they will discharge through it creating a ripple. Given that you will want the capacitors to be nonpolarized (no electrolytics here) and high-voltage, then you are likely to use something like 10nF capacitors rated for the same maximum voltage as the diodes for a low-current load such as a Geiger–Müller tube.
This kind of circuit is often used in high-voltage applications to multiply an initially high voltage up to even higher voltages.
For an example of using this kind of voltage multiplier in a power supply for a Geiger–Müller tube, see Recipe 7.14.
For background information on diodes and capacitors, see Recipe 4.1 and Recipe 3.1, respectively, and for background on AC see Recipe 1.7.
This circuit can generate voltages approaching 1000V. Although this is at low current, it will still give you a nasty jolt and could have disastrous consequences if you have a pacemaker or heart problems, so please be careful if you decide to make this recipe.
This is especially true if you reuse the transformer from the flash unit of a disposable camera, as these units have a large capacitor charged to 400V or more that can really hurt. So discharge the capacitor first (Recipe 21.7).
Use a version of the inverter circuit of Recipe 7.10 to drive a small high-frequency transformer. Figure 7-17 shows the schematic for the power supply. Note that D1 and C4 should both be rated at 1000V.
The 555 timer is designed to provide a frequency of between 7kHz and 48kHz controlled using the variable resistor R3. The Darlington transistor provides pulsed current to the transformer, the output of which is rectified and smoothed.
Altering the frequency will alter the output voltage. With a high-voltage multimeter (1000V DC) adjust the variable resistor until the maximum voltage is found. For my transformer this took place at a frequency of 35kHz.
Figure 7-18 shows the project built on two pieces of breadboard. The left breadboard has the 555 oscillator and the righthand board the transistor and high-voltage part of the design.
As you can see, the high-frequency transformer is tiny. The device I used is marked DT5A and is scavenged from the flash unit of an old disposable camera.
To check the output voltage, you will need a voltmeter with a 1000V DC range. Modern digital multimeters generally have an input impedance of around 10MΩ. At 1000V that means that a load current of 1kV / 10MΩ = 100nA. This does not sound like much, but for a low-current circuit like Figure 7-17, this loading may well reduce the voltage being measured. Increasing the value of C4, perhaps by putting a couple of capacitors of the same value in parallel with the original C4, should tell you if the multimeter is having an effect.
To measure high voltages reliably, you can use a specialist high-voltage meter with a very high input impedance, but these are expensive.
See Recipe 7.14 for a version of this design that adds a three-stage voltage multiplier to increase the output voltage.
For information on using the 555 timer, see Recipe 16.6.
For information on measuring high voltages, see Recipe 21.8.
To build circuits using a solderless breadboard, see Recipe 20.1.
The 450V output of Recipe 7.13 is not enough—you need 1.2–1.6kV for a Geiger–Müller tube that detects alpha radiation.
Add a three-stage voltage multiplier to the schematic of Recipe 7.13. The result of this is shown in Figure 7-19.
The diodes, C4, C5, and C6, can all still be rated at 1kV since the voltage across each should still be under 1kV.
As with the design of Recipe 7.13 the output of this design is likely to contain a few volts of unwanted noise.
For a version of this design without the voltage multiplier, see Recipe 7.13.
One common and safe design for a Tesla coil uses a homemade transformer. Figure 7-20 shows the completed Tesla coil illuminating an LED from a distance of half an inch and Figure 7-21 shows the power supply built on the breadboard.
Figure 7-22 shows the schematic for the project that uses a self-oscillating design based around a transformer and transistor.
The transformer for this design is made from a length of 2-inch plastic pipe onto which around 300 turns of 34 SWG (30 AWG) enameled copper wire are wound next to each other. The primary is made up of just three turns of plastic insulated multicore wire.
This circuit is called a solid-state flyback converter (sometimes called a slayer exciter). The top end of the transformer secondary is not directly connected to anything, but with the top end of the coil connected to something with a large area (such as the copper ball I used) there is a small stray capacitance to ground. The top surface of the large area could be a metal plate or various other arrangements, as long as it’s made from a large conducting area without too many sharp points to encourage discharge.
When power is first applied to the circuit, the transistor will turn on through R1, resulting in a large current flowing through the three turns of the transformer primary. This induces current to flow through the secondary, creating a potential difference due to the stray capacitance. Although small, this capacitance is sufficient to reduce the voltage on the bottom end of the secondary (and base of the transistor) to such an extent that the transistor turns off. The LED ensures that the base never falls more than 1.8V (the forward voltage of the LED) below ground. Because the transistor turns off, the magnetic field collapses and R1 reasserts its influence over the transistor’s base to turn the transistor back on and so the cycle continues.
If you get the connections of the primary the wrong way around, or even just the geometry of the secondary wrong, there is a chance the transformer will turn on but oscillation fail to start, which will rapidly destroy the transistor. If all is well, LED1 will light. A lab power supply with current limiting is very useful in this situation (see Recipe 21.1).
Holding a second LED close to the high-voltage end of the secondary will cause it to light. By holding one lead of the LED, you will be providing a weak path to ground.
A quick way to increase the power of the circuit is to place several transistors in parallel (all three pins). By using four 2N3904s I was able to generate enough voltage to cause the gas in a compact florescent lamp to ionize, lighting the lamp from a range of almost a foot.
For information on prototyping with a solderless breadboard, see Recipe 20.1.
You can see this Tesla coil in action at https://youtu.be/-DEpQH7KMj4.
For other types of high-voltage power supply, see Recipe 7.13 and Recipe 7.14. The “joule thief” circuit (Recipe 8.7) operates in a similar way to this design.
To see a miniature Tesla coil design in action using a ferrite core rather than an open tube, visit https://www.youtube.com/watch?v=iMoDAspGPPc. The design here uses the same schematic as in Figure 7-22.
If you search the internet for Tesla coil, you will find some incredible builds.
Use a fuse. Figure 7-23 shows a selection of fuses.
Fuses can be broadly classified as one-shot traditional fuses or polyfuses. As the name suggests, one-shot fuses can only be used once. When their current or temperature limits have been exceeded and they have blown, that’s it, they must be discarded. For this reason they are generally attached to electronics using a fuse holder, so they can be replaced easily.
Polyfuses (a.k.a. resettable fuses) do not blow, but when the current through them increases above their limit value, their resistance increases, only resetting when the current returns to zero and they have cooled down. This means they can be permanently attached to a circuit. You will often find them used in places like USB ports, where you need to protect computer ports against overcurrent by misbehaving peripherals. Polyfuses use the same technology as PTC thermistors (see Recipe 2.9).
In modern circuit design, and especially for low-voltage and relatively low-current use, polyfuses are the best approach. However, for AC applications and other high-current situations, where overcurrent will only happen if something is seriously wrong, then traditional single-use fuses are the safest option because they require manual intervention before the power can be reapplied to the downstream circuit.
If a single-use fuse blows, then work out why it blew before replacing it. The most likely cause of overcurrent is a short circuit, either from wires touching that should not be touching, or a component failing that causes some part of the circuit to draw more current than it should.
There are a number of different single-use fuses:
To test a fuse, see Recipe 21.5.
For a circuit to produce a constant current, see Recipe 7.7.
To protect a circuit against accidental polarity reversal, see Recipe 7.17.
Many ICs and circuits designed with discrete transistors will be destroyed by overcurrent and hence heating if the power is applied with the wrong polarity.
If you don’t care about a small voltage drop of 0.5V to 1V, then use a single diode from the positive battery terminal to the positive supply of your circuit (see Figure 7-24).
Remember to select a diode that can handle the current that you expect the circuit to draw.
If you can’t afford to lose a volt through the diode but are losing 0.2–0.3V, then use a Schottky diode in place of the regular diode.
If even 0.3V is too much to lose, then use an P-channel MOSFET as shown in the circuit in Figure 7-25.
With the correct polarity, the P-channel MOSFET’s gate-drain voltage will be high enough to keep the MOSFET on. Since MOSFETs with extremely low on-resistances are available, there will be very little voltage drop across the MOSFET to the load. The circuit only works for battery-supply voltages over the gate-threshold voltage, or the MOSFET will not turn on.
When the polarity is reversed, the MOSFET will be firmly off, preventing any significant current from flowing into the load circuit.
Remember that the link between the gate and other connections of the MOSFET is capacitative and so no current can leak through the gate to the negative terminal of the battery.
Although almost by tradition people tend to prefer to switch and use polarity protection on the positive supply, you can also do the same trick with an N-channel MOSFET on the negative battery supply as shown in Figure 7-26.
It’s a good idea to include polarity protection in any battery-powered project, even with a 9V battery that has a clip that only goes one way around, because it is all too easy to touch the wrong contacts together.
Using a MOSFET is probably the cheapest way to protect a design, as it can cope with several amps and will generally be smaller and cheaper than a diode with the same properties, especially in surface-mount technology.
To use fuses to protect a circuit against overcurrent, see Recipe 7.16.
For background on diodes, see Chapter 4.
For more information on MOSFETs, see Recipe 5.3.
In Chapter 7 you learned about various ways of supplying low-voltage DC to your electronics designs from AC. In this chapter you will learn how to use various types of batteries and photovoltaic solar cells.
The capacity of a battery is specified in Ah (ampere hours) or mAh (milliampere hours). To calculate how many hours your battery will last, you need to divide this number by the current consumption of your project in A or mA.
For example, a 9V PP3 rechargeable battery typically has a capacity of about 200mAh. If you were to connect an LED with a suitable series resistor that limited the current to 20mA, the battery should be good for about:
The estimate of time you get using the preceding calculation is very much an estimate and all sorts of factors such as the age of the battery, the temperature, and the current will affect the actual battery life.
If you are using a number of batteries in serial (e.g., in a battery holder that contains 4xAA batteries), then you do not get to multiply the battery life by 4, because the same current will be flowing out of each battery (Figure 8-1).
From Kirchhoff’s Current Law (Recipe 1.4) we know the current flowing past any point in the circuit will be the same. Assuming an LED with a forward voltage of 1.8V the current will be around 9mA. Even though there is more than one battery cell, each cell will have 9mA flowing through it. A typical AA battery has a capacity of around 2000mAh and so we could expect this circuit to run for:
It is best to avoid putting batteries in parallel because none of the cells in the battery will be at exactly the same voltage and when you connect them together, the first thing that will happen is their voltages will equalize with the higher voltage batteries discharging into the lower voltage batteries. If the batteries are rechargeable, you may be okay if the voltage difference is very small, but for nonrechargeable batteries, this charging process can heat the batteries and be dangerous.
Batteries all have an internal resistance, very similar to the ESR of a capacitor (Recipe 3.2). This will cause heating as the battery discharges, which is why you cannot use a small 200mAh battery to supply 10A for 72 seconds. The internal resistance of the battery will both limit the current and cause the battery to heat up. Small batteries tend to have higher internal resistance than big batteries.
Most nonrechargeable batteries bought from a component supplier will specify the maximum continuous discharge current.
For information on choosing between different types of rechargeable batteries see Recipe 8.3 and for nonrechargeable batteries see Recipe 8.2.
To measure the current used by your project using a multimeter, see Recipe 21.4.
Decide what your minimum battery life for the product should be and calculate the capacity of the battery you need in mAh, then use Table 8-1 to select a battery.
If you need more volts than a single battery cell provides, then place several of the cells in series in a battery holder.
| Battery Type | Approx. Capacity (mAh) | Voltage (V) |
|---|---|---|
| Lithium Button Cell (e.g., CR2032) | 200 | 3 |
| Alkaline PP3 Battery | 500 | 9 |
| Lithium PP3 | 1,200 | 9 |
| AAA Alkaline | 800 | 1.5 |
| AA Alkaline | 2,000 | 1.5 |
| C Alkaline | 6,000 | 1.5 |
| D Alkaline | 15,000 | 1.5 |
Higher capacity nonrechargeable batteries are expensive and so C and D cells are found less and less often in favor of rechargeable LiPo battery packs (see Recipe 8.3).
You should also be wary of using exotic or unusual batteries. It’s generally a good idea to stick to universally available batteries like AA cells unless you need something smaller in which case AAA batteries will do.
Battery holders such as the 4 x AA battery holder shown in Figure 8-2 are readily available to hold 1, 2, 3, 4, 6, and 8 AA cells to make a battery pack capable of supplying 1.5, 3, 4.5, 6, 9, and 12V, respectively.
Perfect batteries would allow you to draw as large a current as you want. However, in reality batteries have a small resistance that will cause heating as the battery discharges. The higher the current the greater the heat produced. Smaller capacity batteries have a lower maximum discharge rate than larger batteries.
For information on rechargeable batteries, see Recipe 8.2.
Decide how long you would like your project to operate between charges and use Table 8-2 to choose a battery.
| Battery Type | Approx. Capacity (mAh) | Voltage (V) |
|---|---|---|
| NiMh button cell pack | 80 | 2.4-3.6 |
| NiMh AAA cell | 750 | 1.25 |
| NiMh AA cell | 2,000 | 1.25 |
| LC18650 LiPo cell | 2,000 to 8,000 | 3.7 |
| LiPo Flat cell | 50 to 8,000 | 3.7 |
| Sealed lead acid (SLA) | 600, 8,000 | 6 or 12 |
LiPo (lithium polymer) and the closely related lithium ion cells are the lightest and also now as cheap per mAh as older technologies such as MiMh, but they require care when charging and discharging or they can catch fire (see Recipe 8.6).
You will still find NiMh batteries in products like electric toothbrushes. They are heavier than LiPos of the same capacity but are easy to charge (see Recipe 8.4).
SLA batteries (sealed lead acid) are even heavier than NiMh cells but cope well with trickle charging and last for years. However, their use is on the decline in favor of lighter-weight LiPo batteries.
Many rechargeable batteries will specify safe charge and discharge rates in units of C. This refers to a ration of the battery’s nominal capacity. So, a 1Ah battery that says it can be discharged at 5C is capable of supplying 5A (5 x 1A). If the maximum charge current is specified as 2C the battery can be charged at 2A.
For a similar recipe but for nonrechargeable batteries, see Recipe 8.2.
You want to charge a NiMh or SLA battery while it’s connected to your circuit and you don’t need to charge it quickly.
Note that LiPo batteries should not be trickle charged in this way. Instead, see Recipe 8.6 on charging LiPo batteries.
Trickle charge the battery from a power supply using a resistor to limit the current. If you don’t know how the power supply works, then also include a diode in the circuit to prevent damage to the power supply when the power is turned off. Figure 8-3 shows the schematic for charging a 6V battery from a 12V supply.
A battery’s datasheet will specify the charging current to use for fast charging and in this case slow trickle charging in terms of C, where in this case, C is not capacitance but rather the capacity of the battery in mAh. So the datasheet for an AA rechargeable battery might say that it should be trickle charged at C/10 mA, meaning that if the battery is a 2000mAh AA cell, it can be trickle charged at 2000/10 = 200mA indefinitely without damaging the battery. Charging below 200mA will still result in the battery being charged, and in situations like battery backup (Recipe 8.5) charging at C/50 (40mA) is probably a good compromise between charging speed and power consumption of the circuit.
To charge at 40mA we just need to set the value of R. The voltage across R will be 12V – 6V – 0.5V = 5.5V. We know that the current is 40mA, so we can calculate R using Ohm’s Law as:
Using the standard resistor value of 120Ω will result in a slightly higher current of:
We also need to make sure the resistor has a sufficient power rating, which we can calculate as:
So, a ¼W resistor is probably OK, but ½W would not get as hot.
An alternative to using a resistor to limit the current is to use Recipe 7.7 to provide a constant charging current. This design is more complex and expensive, but will cope better with variations in the input voltage and the battery’s voltage changing as it charges.
Charging from a photovoltaic solar cell is very similar to trickle charging (see Recipe 9.1).
Use a battery of slightly lower voltage than the power adapter–supplied voltage and a pair of diodes in the arrangement shown in Figure 8-4.
The diodes ensure that the output is supplied from either the battery or the power supply, whichever has the higher voltage. Since you want the power supply to be providing the voltage most of the time, arrange for it to be a volt or more higher than the battery voltage (remember the battery voltage will drop as it discharges). In Figure 8-4, when the power supply is producing 10V, D1 will be forward-biased (conducting) and D2 reverse-biased. This reverse-biasing of D2 prevents any accidental charging of the battery (which may not be rechargeable). If the power supply were to turn off, D2 becomes forward-biased, providing the output voltage and D1 would become reverse-biased preventing any possible flow of current into the power supply that could damage it, especially if it is an SMPS design (Recipe 7.8).
When selecting a diode type for D1 and D2, you need to make sure it can handle the current that the output needs to provide. Although in most cases regular diodes like the 1N4xxx series are just fine, they will result in a forward-voltage drop of at least 0.5V. You can reduce this voltage drop by using Schottky diodes (Recipe 4.2).
The circuit of Figure 8-4 will work just fine for rechargeable or nonrechargeable batteries, but it will not charge the batteries. If using rechargeable batteries, you can modify the circuit slightly so that the power supply trickle charges the battery and supplies the output. Figure 8-5 shows the schematic for this. See Recipe 8.4 for the calculation for the charging resistor.
Now when the power supply is in charge some of the current from D1 will flow through R1 and charge the battery (D2 is reverse-biased and can effectively be ignored). When the power supply is off (0V) D2 becomes forward-biased and supplies power to the output. At this time, R1 becomes irrelevant as D2 will be conducting.
See Recipe 4.2 for help selecting the right diode.
For the basics of what diodes do, see Recipe 4.1.
Use a LiPo-charging IC designed specifically for the purpose of charging LiPo batteries. The schematic of Figure 8-6 is an example design using the MCP73831 IC.
Many consumer electronics use LiPo batteries (often charged from a USB connection) with chips like the MCP73831 and many are low cost (less than $1) and include all sorts of advanced features that make sure the LiPo cell is charged safely.
The MCP73831 only needs two capacitors and a resistor to make a complete LiPo-charging circuit. The LED and R2 provide a status indicator that shows that the battery is charging and can be omitted if you don’t need it.
The chip will automatically control the charge current, turning it to a safe trickle charge when the cell is fully charged. However, you can set the maximum charge current in amps (consult the datasheet for the LiPo cell that you plan to use) by means of R1, using the formula:
So, to charge at 500mA (the maximum allowed by the chip anyway) set R1 to 2kΩ.
As an alternative to using a design of your own to charge a LiPo cell, you can also buy ready-made LiPo charge modules such as the Adafruit 1905 and Sparkfun PRT-10217 (both use the MCP73831).
LiPo batteries have made the news in recent years because they will catch fire if abused. Using a charger chip like the MCP73831 in your circuits will help ensure your design is safe and reliable. For extra safety, you can add a thermal fuse (Recipe 7.16) to the supply to the charging circuit.
If you are looking for a lower-tech solution then consider using a NiMh or SLA battery instead.
Unlike NiMh or SLA batteries, LiPo batteries are not suited for charging in parallel. Each cell effectively has to be charged independently using special hardware. If your project cannot operate directly from the 3.7V of a LiPo cell and needs a bit more voltage, then it is generally easier to use a boost converter (Recipe 7.9) to generate the voltage you need.
You can find the datasheet for the MCP73831 here: http://bit.ly/2n2XUPP.
The novelty circuit known as a joule thief allows you to power an LED from an alkaline AA cell even when its voltage drops to around 0.6V.
A joule thief is actually a small self-oscillating boost converter (see Recipe 7.9) that requires just a transistor, resistor, and homemade transformer to drive an LED from a single 1.5V battery, even when the battery voltage drops as low as 0.6V. The circuit is shown in Figure 8-7.
The circuit is very similar in operation to the self-oscillating boost converter used in Recipe 7.15 except that the secondary winding has the same number of turns as the primary and is connected back to the base via a resistor rather than using parasitic (from the winding) capacitance.
Figure 8-8 shows a joule thief. This circuit is interesting because it is fun to make one and see just how long an AA battery can power an LED.
I made my transformer by winding 12 turns of 30 AWG (34 SWG) enameled copper wire, for each winding, around a tiny toroidal ferrite core. In reality, more or less of any ferrite core and even plastic insulated wire will work just fine.
The supply generates pulsed DC at a frequency of about 50kHz (depending on the transformer).
For more practical boost converters, see Recipe 7.9.
Recipe 7.15 uses a very similar circuit to this recipe.
For information on wire gauges, see Recipe 2.10.
Use a photovoltaic solar panel (Figure 9-1) to generate electricity to trickle charge a battery that then supplies your project. The leftmost panel in Figure 9-1 is reclaimed from a low-power solar LED on a stick that cost about $1.50.
Figure 9-2 shows the schematic for solar charging a battery.
Solar panels are made up of a number of solar cells wired together in series to increase the output voltage. You will need a solar panel with an output voltage that is greater than the battery voltage.
The diode D1 is essential to prevent current from flowing back through the solar panel and damaging it when the solar panel is not illuminated enough for its output voltage to exceed the battery voltage.
R1 sets the charging current in just the same way as trickle charging (Recipe 8.4). As with trickle charging, you can also use a current regulator such as the one described in Recipe 7.7.
The performance of the solar panel varies enormously with the amount of sunlight falling on it. A solar panel will produce useful amounts of power when in direct sunlight, but in shadow or on a cloudy day it is unlikely to produce any more than 1/20 of its direct sunlight performance.
If you are thinking of using a solar panel to power a project indoors, unless you plan to keep the project on a sunny window sill or your project uses microamps, then forget it. The size of panel that you will need will make the project huge.
Two key parameters specified for a solar panel are its nominal output voltage and its power output. Both these values require some explanation.
The power output of the panel in mW for a small panel and W for a larger panel, as stated in the specification for the panel, is the power output under ideal conditions. That is, pointing directly at the sun without clouds, haziness, or any other impairments. In Table 9-1 you see the results of practical tests on the solar panels shown in Figure 9-1. These tests were carried out in the early afternoon at my home (53° latitude). The “no direct sunlight” readings were made with the panel pointing at clear sky but away from direct sunlight. For details on how to take such measurements yourself, see Recipe 9.3.
| Nominal Power |
Dimensions (inches) |
Actual Output (direct sunlight) |
Actual Output (no direct sunlight) |
Guide Price (2016) |
|---|---|---|---|---|
| Unknown | 1x1 | 40mW | 1.4mW | $1 |
| 1W | 6x4 | 210mW | 8.4mW | $5 |
| 20W | 22x12 | 6.9W | 86mW | $40 |
Two things emerge from these measurements. First, the actual power output, even for the highest quality panel (the 20W panel), was actually almost ⅓ of its rated value. Secondly, when out of direct sunlight, the power output fell to almost 1/100 of the full-sunlight reading in the worst case. Now, while I’m sure the panels would do better at noon near the equator, that’s not where most of us live.
Similarly, the output voltage at suboptimal lighting levels is also not the same as the specified output voltage. Table 9-2 shows the no-load output voltage for the same solar panels.
| Nominal Output Voltage |
Actual Output (direct sunlight) |
Actual Output (no direct sunlight) |
|---|---|---|
| 2V | 2.2V | 1.9V |
| 6V | 10.6V | 9.7V |
| 12V | 21.3V | 18V |
The output voltage is higher than the nominal voltage so it can be used to charge a battery of nominal voltage.
To work out the power output of the solar panel that you need, see Recipe 9.3.
For the basics of trickle charging, see Recipe 8.4.
This solution will not give you an exact solar-panel power requirement and accompanying battery capacity, but it will at least give you a rough estimate to get you started with field testing.
Start by calculating the energy use of your project in Ws (joules) for a 24-hour period because a 24-hour day will include both the daylight and nighttime parts of the daily cycle. Calculating this current consumption is easy if the device is on all the time and the current consumption is constant. Let’s say we have a garden temperature sensor that uses WiFi and consumes a constant 70mA from its 5V power supply. The power consumption is therefore 70mA x 5V = 350mW. The energy consumption is 350mW times the number of seconds in 24 hours. That is, 350mW x 24 x 60 x 60 = 30,240J.
This means that we need a solar panel that can during a 24-hour period provide 30,240J of energy. You can calculate the required solar-panel power using the formula:
where E is the energy needed (30,240 in this example) and H is the average number of hours that the solar panel will be in direct sunlight. Let’s assume that you live in the tropics, have more or less no seasonal variation in day length, and 10 hours of sunlight a day. In that case you can calculate the power of the panel you need as:
So, in theory a 1W solar panel is fine for this particular situation.
If you think you might need the thermostat to keep working for three days without any solar charging (perhaps during a tropical storm) you will need a battery that can deliver 3 x 30,240 = 90,720J of energy.
The storage capacity in mAh (C) can be calculated using this formula:
This equation has made a number of optimistic assumptions. First, the tropical daylight pattern is likely to be markedly different from a wet maritime climate at high altitude. In that case, you may only be able to assume a much lower average. For example, according to US Climate Data, December in Seattle only averages 62 hours of sunshine in the entire month (2 hours a day). This would require a solar panel of five times the power of the tropical equivalent.
The equation also assumes that any voltage conversion that is needed between the output of the solar panel down to the battery voltage is 100% efficient. If you are using a switching regulator like Recipe 7.8 then you might get 80%, but a linear regulator will not be as good, maybe only 50% or lower.
Also, the battery you are charging or the circuit charging it may limit the maximum power that you are using from the solar panel to prevent damage to the battery by charging it with too high a current. This all needs to be taken into account. Using a higher power solar panel than your battery can keep up with will have the advantage that under lower light conditions you will still get some charging.
All in all, using the worst-case sunshine hours scenario for your location, you should probably use double the calculated solar-panel output power requirement as your starting point, before ordering any solar panels to start experimenting with.
In addition to assumptions about the generation side of things, the load side is also often a lot more complicated than a constant load current. It may be that a device has a constant standby current most of the time, but then is turned on by a user or as a result of a timed operation and uses considerably more current for a while, before going back to standby mode. In addition to manually logging the current consumption and making estimates of the energy usage over 24 hours, you can also use a logging multimeter that will make and store periodic readings of current consumption. The resulting data can be downloaded into a spreadsheet for further analysis.
A logging multimeter can also be a great way of assessing the real performance of a solar panel (see Recipe 9.3).
If you are making a solar-powered project, then it is always worth working out how to keep the power consumption to a minimum. For an Arduino or other microcontroller project this may mean making the microcontroller go into a low-power sleep most of the time, just waking periodically to check if anything needs to happen.
Of course, some projects (maybe a solar-powered water pump) don’t need a battery backup because they only need to operate when it’s sunny.
For information on measuring the actual power output of a solar panel, see Recipe 9.3.
For examples of this approach for powering an Arduino see Recipe 9.4 and for a Raspberry Pi see Recipe 9.5.
Using a load resistor attached to the solar panel, measure the voltage across the resistor and from this calculate the power output. Figure 9-3 shows this arrangement.
The output power of the solar panel P is calculated as:
So, if you use a 100Ω load resistance and the voltage is 5V, the output power of the solar panel is:
The value of the load resistor needs to be low enough that the maximum output power of the solar panel is not exceeded, otherwise the solar panel will not generate as much as it could. In other words, if the solar panel is a 12V panel, you will probably find that the no-load output voltage is up to 18V in bright sunlight. So, you really want a load resistor value that gives an output of about 12V. You can calculate the maximum value of resistor to use using:
So, if your solar panel claims to be 20W at 12V, an ideal resistor value would be:
Remember that the resistor will have to have a power rating sufficient to handle the full power output of the panel—in this case 20W.
In addition to simply taking readings under different circumstances (full sunlight, shade, etc.) you can also use a logging multimeter such as the one shown in Figure 9-4 to record the voltage across the load resistor at regular intervals.
This way, you can create a picture of what your panel is likely to generate in a day.
In Recipe 9.2 this measurement technique was used to assess the performance of some of my solar panels.
For information on using a voltmeter, see Recipe 21.2.
Use a 5V solar cellphone charger, like the one shown in Figure 9-5.
Unless you are designing a product, using a ready-made charger circuit is by far the easiest way of solar powering your Arduino.
An Arduino Uno uses around 50mA, so a 4Ah charger/battery like the one shown in Figure 9-5 will power the Arduino for around:
The Arduino Uno is not the most efficient of boards, when it comes to trying to minimize current consumption. It is more efficient to use an Arduino Pro Mini that has an external USB interface that you only need to connect when programming the Arduino. This can reduce your current consumption to 16mA. Using software to put the Arduino to sleep periodically can also greatly reduce current consumption.
For an introduction to Arduino, see Recipe 10.1.
To power your Raspberry Pi from solar, you will need a bigger solar panel than provided with ready-made phone boosters, as the Raspberry Pi is considerably more power hungry (see Recipe 9.5).
Use a 12V solar cell, charge controller, and SLA battery with a 12V to 5V power adapter.
This may sound excessive, but a Raspberry Pi with a WiFi adapter (WiFi is power hungry) can easily consume 600mA. If you add in a small 12V HDMI monitor, then you are likely to be drawing well over 1A.
Figure 9-6 shows a typical setup.
A ready-made charge controller generally has three pairs of screw terminals. One is attached to the solar panel, one to the battery, and one pair for the load, which in this case is a 12V to USB (5V) adapter commonly used as a phone car charger. Be sure to use one that can supply at least 1A.
To run the Raspberry Pi continuously, you will need a 20W or greater solar panel. The choice of battery size depends on how long you want your Pi to keep running after it goes dark, or is dull for a few days. See Recipe 9.2 for information on how to make that choice.
If you are planning to use your Raspberry Pi as a controller, you may want to consider whether it would be better to use an Arduino, which uses only ⅒ of the power, or if you need network connectivity, a Particle Photon or an ESP8266 module (see Recipe 10.6), both of which use less than 100mA.
To power an Arduino using solar energy, see Recipe 9.4.
There is a good chance that any electronics project that you embark on will involve the use of a microcontroller (in the form of an Arduino) or a single-board computer (SBC) like the Raspberry Pi. Our gadgets are becoming more intelligent, requiring a little computer brain to control them; they are also becoming more connected, often needing an interface to the internet.
A typical Maker’s electronics project these days will involve the use of a microcontroller or SBC with some electronics to switch things or sense value, or both. These extra electronics are attached to the microcontroller or SBC using its GPIO (general-purpose input/output) pins.
In this chapter the recipes mostly focus on the electronic side of interfacing with a microcontroller or SBC in general, but will also use the Arduino and Raspberry Pi as examples.
You want to understand just what an “Arduino” is and why it finds its way into so many electronics projects.
Figure 10-1 shows the most popular flavor of Arduino, the Arduino Uno R3.
An Arduino is not a microcontroller but instead a microcontroller interface board. It has a microcontroller chip on the board, but it also has a whole load of other components that provide:
An Arduino does not do anything until it has been programmed. That is, you have to use your computer to write some instructions in the programming language C that can control and read the GPIO pins. Special software, called the Arduino IDE, is provided to both write the programs and then upload them onto the Arduino using a USB cable. Figure 10-2 shows the Arduino IDE with the “Blink” program loaded and ready to transfer to your Arduino. As its name suggests, the Blink program simply makes the Arduino’s built-in LED blink on and off and is the starting point for most people’s Arduino adventures.
You can download the Arduino IDE from http://arduino.cc.
In this book, it will be assumed that you have experimented with Arduino and at least got as far as uploading a program onto it to make an LED blink. If you are new to programming or need a slower-paced introduction to Arduino, then see some of the book suggestions at the end of this recipe.
In addition to the GPIO pins that you will learn more about in Recipe 10.7 the Arduino also has peripheral interfaces for I2C (Recipe 14.9 and Recipe 14.10) and SPI devices (Recipe 19.4).
The Arduino is an extremely useful and reliable component to use in your designs, even if it is just while you are prototyping the project and will later build your own design with a microcontroller.
In addition to the Arduino Uno shown in Figure 10-1, there are many other types of Arduinos that are all programmed the same way. This means you can select an Arduino based on its price, size, and number of GPIO connections.
There are many excellent books written about Arduino that will help you fill in the background. Two I particularly recommend are:
The following is a list of some of the Arduino-related recipes in this book, outside of this chapter:
All the Arduino sketches and Python programs for Raspberry Pi for this book are downloadable from GitHub.
To use the Arduino sketches, download them from GitHub by cloning the directory if you are a git user, or use the Download Zip option behind the Clone or Download button on the GitHub page. You do not need to have a GitHub login to download the files.
Once extracted, the directory contains a directory called arduino with each of the Arduino sketches inside its own directory. Double-clicking on it will open the sketch in the Arduino IDE.
An alternative way to access the sketches is to copy the contents of the arduino directory that you downloaded from GitHub into your Arduino IDE’s sketches directory, which is found in your operating system’s Documents or My Documents (Windows) folder in a directory called Arduino. Then you will be able to open any of the sketches from the File→Sketchbook menu of the Arduino IDE.
To download the Python files for Raspberry Pi, see Recipe 10.4.
If you are looking for a primer to teach you Arduino C, then my book Programming Arduino: Getting Started with Sketches (TAB DIY, 2016) should help you out.
You want to understand just what a “Raspberry Pi” is and why it finds its way into so many electronics projects.
A Raspberry Pi (Figure 10-3) is an SBC running a version of Debian Linux (called Raspbian) as an operating system. You can plug in a keyboard, mouse, and monitor and use it to browse the internet just like a “normal” computer.
The Raspberry Pi is available in a number of different sizes, from the very low-cost Pi Zero up to the Model 3, which includes built-in WiFi.
The reason the Raspberry Pi has become popular for electronics projects is that, like the Arduino, it also has GPIO pins that you can connect to external electronics. What’s more, because the Raspberry Pi can be easily connected to the internet, you can also use it for all sorts of Internet of Things (IoT) projects.
When it comes to programming the Raspberry Pi, there are lots of options. In fact, all major programming languages are available to run on the Raspberry Pi, but the most popular language for electronics projects is probably Python, which is used in conjunction with the RPi.GPIO library.
While you need a computer to program an Arduino, to write programs for Raspberry Pi, you will use the Raspberry Pi itself.
To use a Raspberry Pi unattended, you will want to be able to make your program automatically run when the Raspberry Pi Boots up (Recipe 10.3).
My book The Raspberry Pi Cookbook by O’Reilly (2016) is a cookbook like this, but dedicated entirely to the Raspberry Pi.
If you are new to programming and need a gentle introduction to Python programming on the Raspberry Pi, you might want to consider my book Programming the Raspberry Pi: Getting Started with Python (TAB DIY, 2015).
Here is a list of some of the Raspberry Pi-related recipes in this book outside of this chapter:
All the Python programs for Raspberry Pi for this book can be found here: https://github.com/simonmonk/electronics_cookbook.
To use the programs, you can fetch them from GitHub directly onto your Raspberry Pi using the command:
$ git clone https://github.com/simonmonk/electronics_cookbook
This will also fetch all the Arduino sketches, but these can be ignored. You will find the Python programs in a directory called pi.
To run a program (e.g., blink.py) use the following command:
$ sudo python blink.py
Note that the sudo command is not required on the latest version of the Raspberry Pi’s operating system (Raspbian) so you may be able to just type:
$ python blink.py
Although I suggested ignoring the Arduino sketches earlier in this recipe, in reality you can download and install the Arduino IDE onto a Raspberry Pi and then use the Raspberry Pi to program the Arduino (see http://spellfoundry.com/sleepy-pi/setting-arduino-ide-raspbian/).
To access the Arduino code, see Recipe 10.2.
To set a Raspberry Pi Python program to automatically run on startup, see Recipe 10.5.
If you are looking for a primer to teach you Python with Raspberry Pi, my book Programming Raspberry Pi: Getting Started with Python (TAB DIY, 2015) should help you out.
Modify your rc.local file to run the program you want.
Edit the file /etc/rc.local by using the command:
$ sudo nano /etc/rc.local
Add the following line after the first block of comment lines that begin with #:
/usr/bin/python /home/pi/my_program.py &
It is important to include the & on the end of the command line so that it runs in the background; otherwise, your Raspberry Pi will not boot.
Be careful when you edit rc.local, or you may stop your Raspberry Pi from booting.
For general background on Raspberry Pi, see Recipe 10.3.
Table 10-1 lists some other popular boards (MC, microcontroller; SBC, single-board computer).
| Board | Type | Notes |
Arduino IDE Compatible |
Website |
|---|---|---|---|---|
| Digispark | MC | A tiny Arduino compatible with just a few GPIO pins that plugs straight into your computer’s USB port for programming. | Y | digistump.com |
| Adafruit Feather | MC | A small Arduino compatible with built-in LiPo battery charger and a range of wireless options. | Y | adafruit.com |
| NodeMCU | MC | A small, very low-cost board that can be easily converted to use the Arduino IDE. It has built-in WiFi. | Y | eBay |
| Particle Photon | MC | A small, low-cost Arduino compatible with built-in WiFi and IoT software built-in. | N | particle.io |
| Teensy3 | MC | A small, low-cost Arduino compatible. | Y | pjrc.com |
| BeagleBone Black | SBC | A Raspberry Pi alternative with more GPIO pins and analog inputs. | N/A | beagleboard.org |
| ODROID-XU4 | SBC | An 8-core 2GHZ South Korean monster SBC. | N/A | hardkernel.com |
Some of these boards are shown in Figure 10-4.
The Arduino IDE is a very flexible piece of software that can be easily extended to operate with unofficial Arduino-type boards. This means that you can stick to the Arduino IDE and the Arduino C programming language to program Arduino-like boards that may use a different processor or include useful addons such as WiFi, Bluetooth, or battery-charging hardware.
The Particle Photon deserves special mention, since although it uses a language that is based on Arduino C, you do not program it with the Arduino IDE, but rather with a web-based IDE. Deployment is then over the internet, allowing remote updating of applications. It also includes a very easy-to-use software framework for building IoT projects.
Other good boards to use where WiFi is required are any of the boards based on the ESP8266 modules, such as the NodeMCU and smaller modules like the ESP01. These can be programmed from the Arduino IDE. The ESP8266 boards are not as simple to use as the Photon but are extremely cheap.
For information on the Arduino see Recipe 10.1 and for the Raspberry Pi, see Recipe 10.3.
Microcontrollers and SBCs have GPIO pins that allow you to connect external electronics to them. Figure 10-5 shows the schematic for a typical GPIO pin within a microcontroller chip or SoC of a Raspberry Pi. The pin can function as either a digital input or digital output, under software control.
Referring to Figure 10-5, if the output enable control of the GPIO is set using software to be enabled, the pin functions as a digital output and the push-pull driver (Recipe 11.8) allows the GPIO pin to source or sink a few tens of milliamps.
If the push-pull driver is disabled, then the pin can function as a digital input. If the pull-up resistor enable control is set, then the transistor Q1 is enabled to allow the resistor to pull up the input to a default high. This is commonly used when connecting a switch to a digital input to prevent a floating input from oscillating between high and low (see Recipe 10.7).
The GPIO schematic of Figure 10-5 is typical of most Arduino pins. Some of the Arduino pins (marked A0 to A5) can be used as analog inputs and for those pins, the GPIO is also connected to ADC hardware inside the microcontroller chip.
Some GPIO pins have pull-down resistors as well as pull-up resistors, which can be turned on and off in the same way as pull-down resistors.
Table 10-1 compares the GPIO features of an Arduino and Raspberry Pi 3.
| Feature | Arduino Uno R3 | Raspberry Pi 3 |
|---|---|---|
| Operating voltage | 5V | 3.3V |
| Maximum individual output current | 40mA | 18mA |
| Maximum total current for all pins used as outputs | 400mA | Not specified |
| Internal pull-up resistors | Y | Y |
| Internal pull-down resistors | N | Y |
| Number of GPIOs | 18 | 26 |
| Analog inputs | 6 | None |
Figures 10-6 and 10-7 describe each of the accessible GPIO and power pins available on an Arduino and Raspberry Pi 3, respectively.
Some of the pins require a little more explanation:
Unlike an Arduino, the GPIO pins on a Raspberry Pi are not labeled. If you are going to be connecting things to the GPIO pins, it’s a good idea to get a hold of a GPIO template, such as the Raspberry Leaf (Adafruit 2196), that fits over the GPIO pins allowing you to identify them easily.
Most of the pins on a Raspberry Pi can be used as GPIO, but some have second functions:
If you have an older Raspberry Pi (before the model B+) it will only have 26 pins on the GPIO connector. These are the same as the top 26 pins (above the dashed line) of the 40-pin layout of newer Raspberry Pis shown in Figure 10-7.
For an introduction to Arduino see Recipe 10.1 and for Raspberry Pi see Recipe 10.3.
Many of the recipes in Chapters 11, 12, 13, and 14 use GPIO pins.
Use the pinMode function to set the pin to be an output and then use digitalWrite to turn the pin on and off. The following example program will make digital pin 13 (attached to the Arduino’s built-in LED) blink on and off:
constintledPin=13;voidsetup(){pinMode(ledPin,OUTPUT);}voidloop(){digitalWrite(ledPin,HIGH);// turn the LED ondelay(1000);// wait for a seconddigitalWrite(ledPin,LOW);// turn the LED offdelay(1000);// wait for a second}
The code for this sketch is available as part of the book downloads (Recipe 10.2). The sketch is called blink.
The program (or “sketch” as they are known in the Arduino world) starts by defining a constant for the pin connected to the LED called ledPin, which is given the value 13. If you change your mind and decide to make another pin blink, you only need to change 13 to that pin number in one place in the code.
The setup function is run just once after the Arduino is reset. The pinMode function then specifies that ledPin is to be an OUTPUT. It is perfectly possible to change a pin’s mode while the sketch is running. You can find a good example of this with Charlieplexing (see Recipe 14.6).
The loop function will be run repeatedly over and over again, and each time it is run, it will first set ledPin (pin 13) high, wait a second (1000 milliseconds) then set it low, then wait another second, and so on.
For digital outputs on a Raspberry Pi, see Recipe 10.9 and for digital inputs on an Arduino see Recipe 10.10.
For the current-handling capabilities of an Arduino digital output, see Recipe 10.7.
Use the RPi.GPIO library (included in Raspbian) with Python. The following example program will make GPIO pin 18 turn on and off once a second:
importRPi.GPIOasGPIOimporttimeGPIO.setmode(GPIO.BCM)led_pin=18GPIO.setup(led_pin,GPIO.OUT)try:whileTrue:GPIO.output(led_pin,True)# LED ontime.sleep(1)# delay 1 secondGPIO.output(led_pin,False)# LED offtime.sleep(1)# delay 1 secondfinally:("Cleaning up")GPIO.cleanup()
The code for this program is available as part of the book downloads (see Recipe 10.4). The file is called blink.py.
Unlike the Arduino, the Raspberry Pi does not have any user-controllable LEDs built in so to see this program in action see Recipe 14.1.
The code starts by importing the GPIO and time libraries. It then sets the GPIO pin identification mode to be BCM (Broadcom). This is a hangover from the early days of Raspberry Pi when two ways of identifying the pins were almost equally used. However, for historical reasons, you still need to include this line at the top of all your Python programs. Some internet and book resources still exist that use the pin positions on the connector rather than the pins’ name. If you find such a resource, it will tell you to use a pin mode of BOARD instead of BCM.
The variable led_pin refers to the GPIO pin to be blinked and the pin set to be an output.
The main program loop is contained inside a try/finally block. This is not strictly speaking essential and the program will run just fine without it, but by calling GPIO.cleanup() whenever the program exits, all the GPIO pins are put back into a safe input state so that accidental shorts of the pins will not cause any damage.
Inside the while loop, the pin is first turned on, then there is a delay of a second, then it is turned off, etc. The sleep function takes a time in seconds as a parameter that can also be less than a second using a decimal notation. For example, to delay for half a second you would use time.sleep(0.5).
The Arduino equivalent to this program can be found in Recipe 10.8.
For digital inputs on a Raspberry Pi, see Recipe 10.11.
Use the Arduino C digitalRead function. To see the result of the read, use the Arduino Serial Monitor. The following sketch illustrates this:
constintinputPin=7;voidsetup(){pinMode(inputPin,INPUT);Serial.begin(9600);}voidloop(){intreading=digitalRead(inputPin);Serial.println(reading);delay(500);}
You can find this sketch in the downloads for the book (see Recipe 10.2). It is called ch_10_digital_input.
The constant inputPin is defined as pin 7 and initialized to be an INPUT in the setup function.
The loop function first assigns the value resulting from carrying out a digitalRead on inputPin to the variable reading and then sends this value over the Arduino’s USB interface to the Serial Monitor. Finally, a delay of 500 milliseconds is added to slow things down to a manageable rate.
To open the Serial Monitor (Figure 10-8), click the rightmost icon on the Arduino IDE’s toolbar. This looks like a magnifying glass.
You should see a steady stream of numbers appear as shown in Figure 10-8. These should be predominantly 0s, but there may be occasional 1s. Try attaching a male-to-male jumper wire or short length of solid core wire to pin 7 of the Arduino (Figure 10-9). You should find that you get a selection of 1s and 0s. This is because you are acting as an antenna and the digital input is picking up electromagnetic noise (most likely “hum”). The digital input is “floating” and since it has a very high input impedance, it is very sensitive to noise.
Next, try attaching the floating end of the lead to one of the GND connections on the Arduino as shown in Figure 10-10. You should see that the output in the Serial Monitor is all 0s.
Finally, move the end of the wire that goes to GND to 5V and the Serial Monitor output should now be all 1s.
The Arduino Serial Monitor is one of the few ways to see what is going on inside your Arduino and is often used to see what’s going wrong in a sketch.
For digital inputs on a Raspberry Pi, see Recipe 10.11.
Use the RPi.GPIO library. The following example program reads GPIO23 every half second and prints out the result:
importRPi.GPIOasGPIOimporttimeGPIO.setmode(GPIO.BCM)input_pin=23GPIO.setup(input_pin,GPIO.IN)try:whileTrue:reading=GPIO.input(input_pin)(reading)time.sleep(0.5)finally:("Cleaning up")GPIO.cleanup()
The code for this program is available as part of the book downloads (see Recipe 10.4). The file is called ch_10_digital_input.py.
When you run the preceding program, you will see mostly 0s in the terminal:
$ sudo python ch_10_digital_input.py 0 0 0 0 0 0 0
With both this program and Recipe 10.10 you can connect a switch to the digital input (Recipe 12.1) or use a female-to-female jumper wire to connect GPIO23 to either GND or 3.3V.
For digital inputs on the Arduino, see Recipe 10.10.
Use the Arduino analogRead function and one of the Arduino pins A0 to A5 that can be used as analog inputs. The following example sketch writes the analog reading as a voltage to the Serial Monitor every half a second:
voidsetup(){pinMode(inputPin,INPUT);Serial.begin(9600);}constintinputPinA0;voidloop(){intreading=analogRead(inputPin);floatvolts=reading/204.6;Serial.println(volts);delay(500);}
You can find this sketch, which is called ch_10_analog_input, with the downloads (Recipe 10.2).
The sketch defines the inputPin as A0. When referring to one of the A0 to A5 pins on an Arduino, you have to use the letter and the number (A and 0), whereas for the other pins you just use the number.
The analogRead function returns a number between 0 and 1023, where 0 means 0V and 1023 means 5V. This number is converted to a voltage by dividing it by 204.6 (1023 / 5). Note that the analog range can be changed by connecting the Arduino AREF (analog reference) pin to a different voltage.
When you open the Serial Monitor you will see a series of values displayed. As with the digital inputs of Recipe 10.10 the analog input is floating and so the numbers (voltage on A0) will probably fluctuate something like this:
2.42 2.36 2.27 2.13 1.99 1.86 1.74 1.62 1.40 0.70
Try the experiments in Recipe 10.11 and put a wire into A0. Touching the end of the wire with your fingers so that you act as a radio antenna should make the analog readings even more wild. Connecting A0 to the 5V connector of the Arduino should display a voltage reading of 5.00 on the Serial Monitor and GND will give you 0.00; connecting A0 to the 3.3V socket on the Arduino should give you a reading of around 3.30.
If the maximum voltage you want to measure is below 5V, then you can use the Arduino AREF pin to keep the 0–1023 range of readings but for a smaller voltage range and thus achieve higher precision.
For example, if you tie the AREF pin to the 3.3V pin on the Arduino you will get a full range of readings over the 3.3V range. The voltage at AREF needs to be stable and regulated or your readings will be inaccurate.
The Raspberry Pi does not have analog inputs, but you can use an ADC IC (Recipe 12.4).
Use the analogWrite function of the Arduino on one of the PWM-capable pins.
The following example sketch will set the brightness of an LED wired to pin 11. The brightness is set by sending a number between 0 and 255 from the Arduino Serial Monitor to the Arduino board. For the curious, 255 is 1 less than 2 to the power of 8.
constintoutputPin=11;voidsetup(){pinMode(outputPin,OUTPUT);Serial.begin(9600);Serial.println("Enter brightness 0 to 255");}voidloop(){if(Serial.available()){intbrightness=Serial.parseInt();if(brightness>=0&&brightness<=255){analogWrite(outputPin,brightness);Serial.println("Changed.");}else{Serial.println("0 to 255");}}}
You can find this sketch, which is called ch_10_analog_output, with the downloads for the book (Recipe 10.2).
In addition to illustrating PWM output from a GPIO pin, this example sketch also illustrates how you can send data from your computer to the Arduino via the Serial Monitor.
The setup function sets outputPin to be an OUTPUT and then starts serial communication. Finally, the setup function sends a message to the Serial Monitor instructing you how to use the sketch by sending a number between 0 and 255.
Inside the loop function, the call to Serial.available() tests to see if anything has been sent from the Serial Monitor, and if it has, it is converted into an int and assigned to the variable brightness. The analogWrite command is then used to set the output of outputPin.
To see this sketch in operation, you will first need to follow Recipe 14.1 and attach an LED to pin 11.
Open the Arduino IDE’s Serial Monitor (see Recipe 10.10) and then try some different values between 0 and 255 to see how the brightness changes (Figure 10-11).
If, when you type a value into the Serial Monitor and click Send, the LED changes brightness momentarily, but then turns off, the Line ending drop-down list at the bottom of the Serial Monitor (see Figure 10-11) is probably not set to “No line ending.”
What is happening is that the number is being sent and works, but then the line ending arrives as another message and is interpreted as being 0, turning the LED off again.
Not all the pins on an Arduino can be used for PWM like this. In fact, only the pins on the Arduino Uno marker with a ~ can. On an Arduino Uno, that’s pins 3, 5, 6, 9, 10, and 11. Other Arduino models have different sets of pins that are PWM-capable, but you will need to refer to the Arduino documentation to know which ones.
For the Raspberry Pi version of this recipe, see Recipe 10.14.
Use the PWM feature of the RPi.GPIO library to control the output power of a GPIO pin. The following Python example program illustrates this:
importRPi.GPIOasGPIOled_pin=18GPIO.setmode(GPIO.BCM)GPIO.setup(led_pin,GPIO.OUT)pwm_led=GPIO.PWM(led_pin,500)pwm_led.start(100)try:whileTrue:duty_s=raw_input("Enter Brightness (0 to 100):")duty=int(duty_s)pwm_led.ChangeDutyCycle(duty)finally:("Cleaning up")GPIO.cleanup()
You can find this program in the downloads for the book (see Recipe 10.4). If you are using Python 3 rather than Python 2, change the command raw_input to just input.
To see this program in action, you will need to attach an LED to GPIO pin 18 (see Recipe 14.1).
The RPi.GPIO library is a little more complex to use than its Arduino counterpart. After defining the pin as an output, you then have to create a PWM channel using the line:
pwm_led = GPIO.PWM(led_pin, 500)
The number 500 is the frequency of the PWM pulses in Hz. This PWM channel is then started using the following line:
pwm_led.start(100)
Here, the value of 100 is the initial duty cycle (percentage of time the pin is high) of the PWM signal (in this case, 100% of the time).
The rest of the script interacts with the user requesting a value of the duty cycle between 0 and 100. Run the program and try different versions of brightness as shown here:
$ sudo python led_brightness.py Enter Brightness (0 to 100):0 Enter Brightness (0 to 100):20 Enter Brightness (0 to 100):10 Enter Brightness (0 to 100):5 Enter Brightness (0 to 100):1 Enter Brightness (0 to 100):90
When you want to exit the program, press CTRL-C.
The Raspberry Pi does not use a real-time operating system. That is, at any one time, there are many differnt processes running. So if you are trying to generate pulses of an exact length such as with PWM, you will find that you get a certain amount of jitter in the LED brightness as the pulse generation is interrupted.
For the Arduino counterpart to this recipe, see Recipe 10.13.
You want to enable the I2C bus on your Raspberry Pi to connect I2C peripherals to it such as the displays used in Recipe 14.9 and Recipe 14.10.
In the latest versions of Raspbian, enabling I2C (and for that matter SPI—Recipe 10.16) is simply a matter of using the Raspberry Pi configuration tool that you will find on the main menu under Preferences (Figure 10-13). Just check the box for I2C and click OK. You will be prompted to restart.
On older versions of Raspbian, the raspi-config tool does the same job.
Start raspi-config using the following command:
$ sudo raspi-config
Then select Advanced from the menu and scroll down to I2C (Figure 10-14).
When you are asked “Would you like the ARM I2C interface to be enabled?” say “Yes.” You will also be asked if you want the I2C module to load at startup, to which you should also say “Yes.”
I2C is a commonly used standard for connecting devices together. It uses two data pins SDA (data) and SCL (clock) to transfer data bidirectionally between devices. Usually one of the devices on the bus is a microcontroller or in this case, the SoC of the Raspberry Pi. Multiple devices can be connected to the same I2C bus pins, so, for example, you could have both a display and a sensor connected to the same two bus pins, each device having its own unique address.
To use I2C devices from Python, install the Python I2C library by using the commands:
$ sudo apt-get update $ sudo apt-get install python-smbus
You will then need to reboot the Raspberry Pi for the changes to take effect.
When using I2C hardware the i2c-tools software can be a great help in debugging and making sure devices are properly connected to the Raspberry Pi. This can be installed using the command:
$ sudo apt-get install i2c-tools
When you have a device attached to the I2C bus, running the i2cdetect utility will tell you if it’s connected and what I2C address it’s using, as shown in Figure 10-15.
To set up the Raspberry Pi’s SPI, see Recipe 10.16.
For recipes that connect I2C peripherals to a Raspberry Pi, see Recipe 14.9, Recipe 14.10, and Recipe 19.3.
By default, Raspbian is not configured for the Raspberry Pi’s SPI. To enable it use the Raspberry Pi configuration tool found in the main menu under Preferences (as in Recipe 10.15), or on older versions of Raspbian, use raspi-config using the command:
$ sudo raspi-config
Then select Advanced, followed by SPI, and then “Yes” before rebooting your Raspberry Pi. After the reboot, SPI will be available.
The SPI allows serial transfer of data between the Raspberry Pi and peripheral devices, such as ADCs and port expander chips, among other devices. It is similar in concept to I2C but uses four pins instead of two. As with I2C SPI data is synchronized with a clock signal (SCLK) but separate lines are used for each direction of communication: MOSI (master out slave in) and MISO (master in slave out) and a separate “Enable” pin is needed from the master for each of the devices connected to the bus. It is an older and less elegant standard than I2C but still widely used.
You may come across examples of interfacing with SPI that use an approach called bit banging, where the RPi.GPIO library is used to interface with the four GPIO pins used by the SPI.
Recipe 12.4 uses an SPI ADC converter chip.
The SPI is used in Recipe 12.4 and Recipe 19.4.
When you are connecting a 3.3V-level output to a 5V input, with very few exceptions (see discussion), no level conversion is needed—you can connect the two directly.
However, if you want to connect a 5V output to a 3.3V input, then that’s a different matter. Direct connection will wall damage the 3.3V device. If the 3.3V device is specified as having 5V-tolerant inputs, then you can just connect the two together directly. Note that the inputs of a Raspberry Pi are not 5V tolerant, so you should connect them together using a voltage divider as shown in Figure 10-16.
Occasionally you will find a 5V device that specifies that the logic level for an input should be above 3.3V. For example, WS2812 LED ICs (Recipe 14.8) theoretically need an input greater than 4V to be considered as logic high according to their datasheet. In practice, I have always found them to work without level conversion, but if you are designing a product to sell, then you would not take that chance and the kind of level shifter shown in Figure 10-17 should be used.
This circuit will actually convert levels in both directions; that is, 5V outputs will be reduced to 3.3V and 3.3V outputs increased to 5V. It makes use of the fact that MOSFETs have a “substrate” protection diode that prevents current from flowing from drain to source.
To understand how this circuit works, first consider the case where the 3.3V side is an output and the 5V side an input; that is, the level is being shifted up.
In this case, if the 3.3V GPIO is high, then the gate-source voltage will be 0V, the MOSFET will be off, and R2 will pull-up the 5V input HIGH. If the 3.3V GPIO output is low, the gate-source voltage will be 3.3V, the MOSFET will turn on, and the 5V input will be effectively connected to the LOW signal from the 3.3V side.
If we swap the direction so that the 5V side is now the output and the 3.3V side the input, then when the 5V output is HIGH the MOSFET source and gate will be at 3.3V, the MOSFET will be off, and the 3.3V input pulled up to 3.3V by R1. If the 5V output is LOW the MOSFET’s built-in protection diode will conduct, pulling the 3.3V input down to the diode’s forward voltage (about 0.6V). This turns the MOSFET on, pulling the 3.3V input fully to ground.
The simplest level conversion using just two resistors is a voltage divider as described in Recipe 2.6.
For a general background on MOSFETs see Recipe 5.3.
For an interesting discussion of the necessity of level shifting for Raspberry Pi inputs, see http://tansi.info/rp/interfacing5v.html.
If you have a lot of signals all requiring level shifting, then it makes sense to use a level-shifting IC or module such as these products from Adafruit: http://bit.ly/2lLHmuG (four signals) and http://bit.ly/2msMgku (eight signals).
Most modern electronics are concerned with switching things. Microcontrollers and any other digital logic device use transistors as switches. Taking this a step further, devices like Arduino and Raspberry Pi can switch external devices, perhaps controlling lighting or power to a heater.
The recipes in this chapter are all concerned with using transistors and other devices to switch. This includes some recipes to extend the switching power of an Arduino and Raspberry Pi.
Use a transistor in a common-emitter arrangement as a “low-side” switch with a resistor to limit the base current. Figure 11-1 shows the schematic for this circuit, that, along with Recipe 11.2, you will use time and time again in your designs.
This type of switching is called “low-side” switching because the transistor acts as a switch between the low voltage of GND and the load.
The resistor R makes sure that the current drawn from the GPIO pin does not exceed the current limit of the pin (40mA for Arduino and 16mA for Raspberry Pi; see also Recipe 10.7). It also protects the transistor from too much base current flowing. This protective role must be balanced against the limited gain of a bipolar transistor, which may only be 100 or less. So if you are planning to use the transistor to switch a current of 1A, you could reasonably expect a base current of 10mA. This means that for this 1A load, you need to choose a value of R that gives a base current somewhere between the available current of the GPIO and 10mA.
Aiming for a 10mA base current (if you are using a 5V GPIO pin and assume that the base-emitter voltage is a fairly constant 0.6V) you can calculate the value of R as:
Applying the same calculation for a 3.3V GPIO pin you get:
The two connections from this circuit to an Arduino or Raspberry Pi are the GND connection and the GPIO pin. The positive voltage supply to the load is entirely separate from the Raspberry Pi or Arduino. This means that you are not restricted to switching the logic level of the Arduino or Pi (3.3V or 5V) but can switch up to the maximum voltage that the transistor is capable of switching.
Having said that, you will often use the positive voltage supply of an Arduino or Raspberry Pi for the convenience of having a single voltage source.
For a discussion of bipolar transistors, see Recipe 5.1.
GPIO ports and their output logic are described in Recipe 10.7.
You will find an example of switching with a transistor using an Arduino in Recipe 11.6 and for a Raspberry Pi in Recipe 11.7.
For switching using a MOSFET, see Recipe 11.3.
The arrangement of Figure 11-1 is called low-side switching because the switching takes place on the lower voltage side; that is, to GND rather than from the positive supply. This means that whatever is being switched has to have a connection to the positive supply voltage.
One approach to high-side switching is to simply rearrange Figure 11-1 a little as shown in Figure 11-2.
The circuit of Figure 11-2 cannot switch voltages (+V) greater than the GPIO pin’s voltage less half a volt.
A transistor in this arrangement is called an emitter follower (Recipe 16.4) because the emitter will generally be about 0.6V less than the base. This means that we can use this arrangement for high-side switching but only so long as the voltage at the GPIO pin is less than +V.
In short, the circuit of Figure 11-2 is only useful for switch loads where one end of the load must be connected to ground and the other does not need a supply voltage that is greater than the control voltage of the GPIO pin.
If you need to switch a higher voltage (perhaps 12V) you might be tempted to consider an alternative to Figure 11-2 that uses a PNP transistor rather than an NPN transistor as shown in Figure 11-3.
This circuit is defective because Q2 will turn on with a base current when its base is about 0.6V lower than +V. So, if you were trying to switch a 12V load from 5V logic, the base voltage would always be over 0.6V and enough base current would flow to keep the transistor on whether the GPIO pin was at 5V or GND.
If you need to be able to switch voltages of V+ that are greater than the 5V of your Arduino or 3.3V of your Raspberry Pi and you don’t want to use the tristate logic trick, then you will need to use the arrangement shown in Figure 11-4.
This uses a separate NPN transistor Q1 to control the base current to Q2 giving a full switching range.
Low-side switching (Recipe 11.1) is the most common and simplest arrangement, and unless you have a good reason such as the need for one end of the load to be connected to ground, you should use low-side switching.
For a discussion of NPN and PNP bipolar transistors, see Recipe 5.1.
GPIO ports and their output logic are described in Recipe 10.7.
You will find an example of switching with a transistor using an Arduino in Recipe 11.6 and for a Raspberry Pi in Recipe 11.7.
For switching using a MOSFET, see Recipe 11.3.
You can use a MOSFET as an electronic switch. Use the transistor in a common-source arrangement. Figure 11-5 shows the schematic for this circuit. Along with Recipe 11.1, you will find yourself using this circuit a lot.
This type of switching is called “low-side” switching because the transistor acts as a switch between the low voltage of GND and the load.
If the GPIO pin is high (3.3V or 5V) and exceeds the gate-threshold voltage of the MOSFET, the MOSFET will turn on, allowing current to flow from +V through the load to GND.
When using MOSFETs as switches controlled by GPIO pins you should look for devices described as logic level. These have a low-threshold voltage (generally 2V or less), whereas MOSFETs not described as logic-level may well have gate-threshold voltages of 4V to 7V.
Logic-level versions of regular MOSFETs often have the same name, but an L after the name. For example, the FQP30N06L is the logic-level version of the FQP30N06.
Low-power MOSFETs like the 2N7000 generally have pretty low gate-threshold voltages anyway and are fine with 3.3V logic without having the L designation.
You may be wondering why the gate resistor R is needed. In reality for most MOSFETS in most relatively low-current applications, it isn’t needed at all and you can just connect the GPIO pin directly to the gate.
However, the MOSFET’s gate appears to the GPIO pin as a capacitor that will be charged and discharged as the GPIO pin goes high and low. So, if you are switching the MOSFET at high speed (say PWM at a high frequency) or the MOSFETs’ gate capacitance is high (it increases with load current) then the maximum rated output current of the GPIO pin may be exceeded and the transistors inside the GPIO output could overheat. In any case, resistors are cheap and it’s good practice to include one.
In Figure 11-5 the gate of the MOSFET is floating. If it is connected to a GPIO set to be an output, then the MOSFET will be in a stable state, but there are several reasons why this might not be the case:
To prevent this unwanted behavior, you can just add a pull-down resistor to keep the gate low unless the GPIO pin is actively driving the gate (see Figure 11-6). This resistor should have a resistance of perhaps 10 times that of the gate-protection resistor (R1) to prevent the effective voltage divider (Recipe 2.6) formed by R1 and R2 from reducing the gate voltage by any significant amount.
For a discussion of MOSFETs, see Recipe 5.3.
GPIO ports and their output logic are described in Recipe 10.7.
You will find an example of switching with a MOSFET using an Arduino in Recipe 11.6 and for a Raspberry Pi in Recipe 11.7.
For switching using a BJT, see Recipe 11.1.
The problems with high-side switching using a MOSFET are similar to those of Recipe 11.2. However, whereas in Recipe 11.2 it was okay to use an emitter-follower configuration or PNP transistor on its own, the need for a gate-source voltage above the threshold voltage to turn the MOSFET on means that the switchable range is reduced by at least the threshold voltage, making the circuit unsuitable for most applications.
So, for high-side switching there is little alternative to using the circuit of Figure 11-7.
By using a BJT rather than a MOSFET for Q1, there will always be enough leakage current through Q1 to keep the gate of Q2 low when the control pin is left floating.
For a discussion of MOSFETs, see Recipe 5.3.
GPIO ports and their output logic are described in Recipe 10.7.
You will find an example of switching with a MOSFET using an Arduino in Recipe 11.6 and for a Raspberry Pi in Recipe 11.7.
Use Table 11-1 to help you decide which NPN BJT or N-Channel MOSFET to use in low-side switching.
| Technology | Examples | |
|---|---|---|
| under 100mA | BJT or MOSFET | 2N3904 or 2N7000 |
| under 200mA | MOSFET | 2N7000 |
| under 500mA | Darlington or MOSFET | MPSA14 or FQP30N06L |
| under 3A | Darlington or MOSFET | TIP120 or FQP30N06L |
| under 20A | MOSFET | FQP30N06L |
While any of these transistors would technically work, over time you’ll find that you return to a few of your favorite transistors.
When it comes to switching small loads (say under 100mA) a small BJT (like the 2N3904) and a small MOSFET (like the 2N7000) are pretty much interchangeable. In fact, their pinouts mean that they are in the same transistor package and are pin-compatible.
Above 100mA but below 200mA I would usually select a 2N7000 because its low on-resistance means that it will not get as hot as a BJT.
Between 200mA and 500mA, I would either use a Darlington MPSA14 to save space over a FQP30N06L MOSFET (in a larger package), but only if I could afford the 1.5V or more voltage drop of the MPSA14.
Between 500mA and 3A you are definitely in large-transistor territory in a TO-220 package. If you can afford the voltage drop of a Darlington then the TIP120 is a good choice; otherwise, a FQP30N06L will serve you well.
For powers over 3A use a FQP30N06L with a heatsink.
See also Recipe 5.5.
2N3904 datasheet: https://www.sparkfun.com/datasheets/Components/2N3904.pdf
2N7000 datasheet: https://www.fairchildsemi.com/datasheets/2N/2N7000.pdf
MPSA14 datasheet: http://www.farnell.com/datasheets/43685.pdf
FQP30N06L datasheet: https://www.fairchildsemi.com/datasheets/FQ/FQP30N06L.pdf
TIP120 datasheet: https://www.fairchildsemi.com/datasheets/TI/TIP122.pdf
If you have a 5V Arduino like the Arduino Uno, then each GPIO pin can switch a maximum of 5V at 40mA. To increase either the voltage or the current, you need to use a transistor. The principles and even the breadboard layouts are much the same whether you use a BJT or a MOSFET. See Recipe 11.5 for the relative merits of each technology.
Figure 11-8 shows the schematic for this.
This circuit is for low-voltage DC only. Do not try and use it to switch AC. To do so would not work and would also be very dangerous.
You can build this circuit on a breadboard to experiment. Figure 11-9 shows the breadboard layout for the project using a 2N7000, which is good for 200mA (2.4W). If you prefer, you could use a 2N3904 or an MPSA14 with exactly the same breadboard layout.
If you have a higher-power LED lamp, you should use a FQP30N06L as shown in Figure 11-10. Again, you could if you prefer use a TIP120.
The Arduino test program for this project is listed here and is available in the book downloads (see Recipe 10.2) where the sketch is called ch_11_on_off:
constintoutputPin=11;voidsetup(){pinMode(outputPin,OUTPUT);Serial.begin(9600);Serial.println("Enter 0 for off and 1 for on");}voidloop(){if(Serial.available()){charonOff=Serial.read();if(onOff=='1'){digitalWrite(outputPin,HIGH);Serial.println("Output ON.");}elseif(onOff=='0'){digitalWrite(outputPin,LOW);Serial.println("Output OFF.");}}}
This sketch follows a similar pattern to that of Recipe 10.13. Pin 11 is set to be an output and when a single-command character “1” or “0” is sent from the Serial Monitor (Figure 11-11) digitalWrite is used to turn pin 11 on or off.
You can see the circuit in action in Figure 11-12, where a 12V SLA battery is used to power the lamp.
Although intended as a demonstration circuit, this recipe is actually quite powerful, allowing you to control the lamp from your computer.
For information on getting started with breadboard, see Recipe 20.1.
For transistor pinouts, see Appendix A.
The basics of an Arduino Uno are described in Recipe 10.1.
To use this same design with Raspberry Pi, see Recipe 11.7.
The circuits used in Recipe 11.6 will also work just fine if you wire the control connection and GND to a Raspberry Pi rather than an Arduino. Figure 11-13 shows the breadboard layout for using a 2N7000 MOSFET with a Raspberry Pi to switch a 12V LED lamp module.
To control the lamp, you can use the following program, which is called ch_11_on_off.py and can be found with the downloads for the book (see Recipe 10.4):
importRPi.GPIOasGPIOGPIO.setmode(GPIO.BCM)led_pin=18GPIO.setup(led_pin,GPIO.OUT)try:whileTrue:answer=input("1 for on 0 for off: ")ifanswer==1:GPIO.output(led_pin,True)# LED onelifanswer==0:GPIO.output(led_pin,False)# LED offfinally:("Cleaning up")GPIO.cleanup()
When you run the program you should see this in the terminal session:
$ sudo python ch_11_on_off.py 1 for on 0 for off: 1 1 for on 0 for off: 0
When you enter 1, the lamp should light (pressing 0 will turn it off again).
As with Recipe 11.6 you can also use other transistors than the 2N7000 or FQP20N06L MOSFETs.
For information on getting started with breadboards, see Recipe 20.1.
For transistor pinouts, see Appendix A.
The basics of a Raspbery Pi are described in Recipe 10.3.
To use this same design with an Arduino, see Recipe 11.6.
Use transistors in the half-bridge configuration shown in Figure 11-14.
This circuit combines elements of Recipe 11.3 and Recipe 11.4 and relies on their being three power lines: +V, –V, and GND in the middle. Thus, the three power lines might be +6V, –6V, and 0V.
The control signals A and B turn on Q2 and Q3, respectively. If A and B are both low with respect to –V no current will flow through the load. If A is high, Q2 will conduct and current will flow through Q2 to the load and then to GND. Conversely, if A is low and B is high, Q3 will conduct and current will flow from GND through the load to –V.
Under no circumstances should A and B both be high, since if both Q2 and Q3 are conducting there will effectively be a short-circuit between +V and –V and a damagingly large current will flow. In fact, if you are connecting A and B to GPIO pins and using software to set them high or low, you should put a small delay in between settings to allow A and B to be high at the same time. For example, to change from A high, B low to A low, B high, you should follow these steps:
The half-bridge and its relative the full-bridge are often used to control DC motors, where their ability to reverse the direction of the flow of current allows them to reverse the direction in which the motor rotates.
Although it is perfectly possible to build half-bridge circuits from discrete components, it is more common to use an IC. You will meet several of these in Chapter 13.
For a full-bridge circuit, see Recipe 13.3.
For the FQP27P06 P-Channel MOSFET’s datasheet, see https://www.sparkfun.com/datasheets/Components/General/FQP27P06.pdf.
Use a low-power BJT or MOSFET to switch the power to the relay’s coil as shown in Figure 11-15.
A typical relay coil will need about 50mA to activate the relay contacts, which is slightly too much to use an Arduino pin directly and far too much for a Raspberry Pi GPIO pin. A relay with a nominal 5V coil will generally work with a little over 4V if you use a BJT, but supplying the full 5V by way of a MOSFET is generally better. So a good choice for Q1 would be a 2N7000. R is not at all critical, but 1kΩ would be fine.
The diode D1 is called a “freewheeling” or “flyback” diode and provides a discharge path for high voltages generated as the relay coil is switched off, which protects Q1.
Building a design like this on a breadboard can be a little tricky, as most common relay packages don’t have pins that will fit into the breadboard, so you may have to solder short extension wires to the relay coil or use a prototyping setup like the MonkMakes Protoboard that has a place to solder a relay. Figure 11-16 shows the breadboard layout for using a relay with an Arduino and Figure 11-17 for a Raspberry Pi.
To test out the relay on an Arduino and Raspberry Pi, you can use the programs described in Recipe 11.6 and Recipe 11.7, respectively.
Although it can be tempting to try to get away with connecting the relay coil directly to a GPIO pin, this may damage the Arduino or Pi and is most certainly operating outside of the specifications for the Arduino, Raspberry Pi, or relay and cannot be guaranteed to work correctly.
For information on relays see Recipe 6.4.
SSRs are generally opto-isolated, which means that controlling them is as simple as using an LED. In fact, it’s usually easier because in an SSR a series resistor is generally included. Figure 11-18 shows an SSR module connected to a Raspberry Pi. The SSR’s negative input terminal is connected to GND and the positive terminal to a GPIO pin.
Do not use an SSR to control AC unless you are sure you can wire things up safely and you know exactly what you are doing.
Under no circumstances should you work on a live/hot system while you are prototyping, and always use an RCD-protected AC outlet.
See also Recipe 21.12.
To test out the relay on an Arduino and Raspberry Pi, you can use the programs described in Recipe 11.6 and Recipe 11.7, respectively.
A safe and easy way to control AC using an SSR is to use a PowerSwitch Tail.
As the name suggests, a circuit that has an open-collector output uses an NPN BJT as an output stage (Figure 11-19) with the implication that the emitter is connected to GND, with no internal connections to the collector except to the output.
At first glance this may seem strange, and a common mistake is to treat an open-collector output as a logic output and connect it straight to a GPIO pin. Unless the internal pull-up resistor on the GPIO pin (Recipe 10.7) is enabled, this will not work.
Leaving the collector floating like this has the advantage that by simply using a resistor from the collector to a positive supply, the output voltage of the open collector can be set to match that of the GPIO input you are connecting it to. Figure 11-20 shows how an open-collector output can be used with 3.3V logic (left) and 5V logic (right).
The value of R1 is not critical and needs to lie somewhere in the large range of not exceeding the transistor’s collector current limit and not being succeptable to electrical noise. So, anything between 1kΩ and 1MΩ is fine. Common resistor values for this are 1kΩ and 10kΩ.
If your GPIO pin has the ability to enable an internal pull-up resistor you can use this instead of an external resistor.
If the circuit or module you are using specifies the current rating of the open-collector output, you can use it to directly drive a load (e.g., a relay). The load should be in place of the resistor between the output and a positive voltage supply.
The MOSFET equivalent of an open-collector output is the open-drain output (see Figure 11-21). This can be used in exactly the same way as its BJT equivalent. In fact, it’s not uncommon to find device outputs labeled as open collector that actually use a MOSFET.
This chapter looks at sensors that convert some physical measurement such as temperature, light, or physical movement into an analog or digital electronic signal.
Many different sensors are explained, and where appropriate, ways of using them with an Arduino or Raspberry Pi are included.
Connect the switch between GND and a GPIO pin set to be a digital input as shown in Figure 12-1 and enable the GPIO pin’s internal pull-up resistor.
Your software will probably also need to “debounce” the signal from the switch.
Here is an Arduino sketch that writes a message to the Serial Monitor whenever the switch is pressed. You can find this sketch (ch_12_switch) with the downloads for the book (see Recipe 7.2):
constintinputPin=12;voidsetup(){pinMode(inputPin,INPUT_PULLUP);Serial.begin(9600);}voidloop(){if(digitalRead(inputPin)==LOW){Serial.println("Button Pressed!");while(digitalRead(inputPin)==LOW){};delay(10);}}
The internal pull-up resistor is turned on by specifying INPUT_PULLUP in the pinMode function.
Inside the loop the inputPin is continually read until it is pressed (becomes LOW). At this point, a message is displayed in the Serial Monitor and the while loop ensures there are no further triggerings until the switch has been released. The debouncing is achieved by the 10-millisecond delay that is triggered after each button press is detected. This gives the switch contacts time to settle before they are tested again.
You can try out the example by poking the pins of a tactile push switch between GND and pin 12 on the Arduino as shown in Figure 12-3.
The equivalent code for a Raspberry Pi is listed here (ch_12_switch.py):
importRPi.GPIOasGPIOimporttimeGPIO.setmode(GPIO.BCM)input_pin=23GPIO.setup(input_pin,GPIO.IN,pull_up_down=GPIO.PUD_UP)try:try:whileTrue:ifGPIO.input(input_pin)==False:("Button Pressed!")whileGPIO.input(input_pin)==False:time.sleep(0.01)finally:("Cleaning up")GPIO.cleanup()
The logic of this program follows exactly the same pattern as for the Arduino.
Having male GPIO pins on a Raspberry Pi makes it a little more difficult to attach a switch. One way to attach the switch is to use a microswitch pushed into a pair of female-to-female jumper wires (Figure 12-4) or use a Squid Button (Figure 12-5).
If you plan to use a number of push switches, then whether or not you are using a Squid Button, you can use the Squid library to simplify the process of debouncing. Download and install the Squid library from https://github.com/simonmonk/squid where you will also find installation instructions. Once installed, the test program can be simplified to the following example (ch_12_switch_squid.py):
frombuttonimport*b=Button(23)whileTrue:ifb.is_pressed():("Button Pressed!")
Microswitches (Figure 12-6) are push switches that are not designed to be directly pressed by a person, but rather have a lever attached and are used to sense physical movement such as when a linear actuator has reached its end position or as a safety interlock to make sure a microwave door is closed.
The microswitch is an SPDT device generally with closed, normally open, and common terminals (see Recipe 6.2).
Although switch using an Arduino or Raspberry Pi generally uses a pull-up resistor and switches to ground, you can also switch to the positive supply.
To switch to the positive supply on an Arduino, you have to use an external pull-down resistor to prevent the input from floating because the Arduino does not have internal pull-down resistors on its GPIO pins (pin mode INPUT).
On the other hand, the Raspberry Pi does have internal pull-down resistors that can be enabled for a particular pin using the command:
GPIO.setup(input_pin,GPIO.IN,pull_up_down=GPIO.PUD_DOWN)
For information on the Squid Button, see https://www.monkmakes.com/squid_combo/.
Digital inputs are also described in Recipe 10.10 and Recipe 10.11.
GPIO pins are described in Recipe 10.7.
You’ll want a type of rotary encoder called a quadrature encoder, which behaves like a pair of switches (Figure 12-7). The sequence in which they open and close as the rotary encoder’s shaft is turned determines the direction of rotation.
A basic rotary encoder will have three pins. One for A, one for B, and a common pin. The rotary encoder shown in Figure 12-7 has two extra pins that are used for a push switch that is activated when the knob is pushed rather than turned.
When using a rotary encoder with a microcontroller or SBC, the common contact is connected to GND and the switch contacts connected to digital inputs with pull-up resistors enabled.
The following Arduino sketch, which is called ch_12_quadrature, can be found with the downloads for the book (Recipe 10.12). The sketch assumes that the two switch pins are connected to pins 6 and 7:
constintaPin=6;constintbPin=7;intx=0;voidsetup(){pinMode(aPin,INPUT_PULLUP);pinMode(bPin,INPUT_PULLUP);Serial.begin(9600);}voidloop(){intchange=getEncoderTurn();if(change!=0){x+=change;Serial.println(x);}}intgetEncoderTurn(){// return -1, 0, or +1staticintoldA=0;staticintoldB=0;intresult=0;intnewA=digitalRead(aPin);intnewB=digitalRead(bPin);if(newA!=oldA||newB!=oldB){// something has changedif(oldA==0&&newA==1){result=(oldB*2-1);}elseif(oldB==0&&newB==1){result=-(oldA*2-1);}}oldA=newA;oldB=newB;returnresult;}
To avoid skipping turns, the function getEncoderTurn must be called as frequently as possible in loop.
getEncoderTurn compares the current state of the A and B switches with their states last time getEncoderTurn was called to infer whether the knob is being turned clockwise or counterclockwise, returning a value of 1 or –1, respectively. If there is no change to the values of A and B then 0 is returned.
You can find the Raspberry Pi version of the rotary encoder program in the file ch_12_quadrature.py (see Recipe 10.4) and here:
importRPi.GPIOasGPIOimporttimeGPIO.setmode(GPIO.BCM)input_A=18input_B=23GPIO.setup(input_A,GPIO.IN,pull_up_down=GPIO.PUD_UP)GPIO.setup(input_B,GPIO.IN,pull_up_down=GPIO.PUD_UP)old_a=1old_b=1defget_encoder_turn():# return -1, 0, or +1globalold_a,old_bresult=0new_a=GPIO.input(input_A)new_b=GPIO.input(input_B)ifnew_a!=old_aornew_b!=old_b:ifold_a==0andnew_a==1:result=(old_b*2-1)elifold_b==0andnew_b==1:result=-(old_a*2-1)old_a,old_b=new_a,new_btime.sleep(0.001)returnresultx=0whileTrue:change=get_encoder_turn()ifchange!=0:x=x+change(x)
The test program counts up as you turn the rotary encoder clockwise, and counts down when you rotate it counterclockwise:
pi@raspberrypi ~ $ sudo python rotary_encoder.py 1 2 3 4 5 6 7 8 9 10 9 8 7 6 5 4
Both the Arduino and Raspberry Pi versions of the software work in just the same way.
Figure 12-8 shows the sequence of pulses that you will get from the two contacts, A and B. You can see that the pattern repeats itself after four steps (hence the name quadrature encoder).
When rotating clockwise (left to right in Figure 12-8), the sequence will be:
| Phase | A | B |
|---|---|---|
|
1 |
0 |
0 |
|
2 |
0 |
1 |
|
3 |
1 |
1 |
|
4 |
1 |
0 |
When rotating in the opposite direction, the sequence of phases will be reversed:
| Phase | A | B |
|---|---|---|
|
4 |
1 |
0 |
|
3 |
1 |
1 |
|
2 |
0 |
1 |
|
1 |
0 |
0 |
The Python program listed previously implements the algorithm for determining the rotation direction in the function get_encoder_turn. The function will return 0 (if there has been no movement), 1 for a rotation clockwise, or -1 for a rotation counterclockwise. It uses two global variables, old_a and old_b, to store the previous states of the switches A and B. By comparing them with the newly read values, it can determine (using a bit of clever logic) which direction the encoder is turning.
The sleep period of 1 millisecond is used to ensure that the next new sample does not occur too soon after the previous sample; otherwise, the transitions can give false readings (see “Contact Bounce”).
The test program should work reliably no matter how fast you twiddle the knob on the rotary encoder; however, try to avoid doing anything time consuming in the loop, or you may find that turn steps are missed.
To use a pot to sense rotation, use Recipe 12.3.
Put the resistive element in a voltage divider with a fixed-value resistor to convert the resistance measurement into a voltage as shown in Figure 12-9.
The Raspberry Pi does not have analog inputs, so to use resistive sensors with a Raspberry Pi, you either need to add analog inputs to your Raspberry Pi (see Recipe 12.4) or use the step-response method (see Recipe 12.5).
When it comes to choosing the value of a fixed resistor, the aim should be to try and maximize the range of output voltages that will be presented to the analog input. With an Arduino Uno’s analog input range of 0 to 5V you ideally want an analog input voltage of 0 to 5V. Because a voltage divider “divides” the input voltage, you are never going to get the full voltage range as an output unless you use a higher input voltage. This introduces the potential for overvoltage at the analog input and so generally it is better to accept a slightly narrowed range rather than risk damaging your board.
Let’s take as an example a photoresistor that has a minimum resistance of 1kΩ under bright light and a resistance that rises to 1MΩ in total darkness. Assuming that you are using a 5V Arduino:
If we pick a value for the fixed resistor R2 of about 10 times of the minimum value of the photoresistor R1 then R2 would have a value of 10kΩ, so at maximum brightness:
For a resistance of 10k for the photoresistor, the Vout would be 2.5V and when the photoresistor is in complete darkness (1MΩ), the Vout would fall to 0.05V.
This would give pretty good coverage of the whole range of the photoresistor’s readings.
The following Arduino sketch assumes that R1 is a photoresistor with 1kΩ light resistance and R2 is a fixed 10kΩ resistor. The sketch calculates the resistance of R1 and displays it in the Arduino IDE’s Serial Monitor every half-second. You can find the sketch here and with the downloads for the book (see Recipe 10.2). It is called ch_12_r_adc.
constintinputPin=A0;constfloatr2=1000.0;constfloatvin=5.0;voidsetup(){pinMode(inputPin,INPUT);Serial.begin(9600);}voidloop(){intreading=analogRead(inputPin);floatvout=reading/204.6;floatr1=(r2*(vin-vout))/vout;Serial.(r1);Serial.println(" Ohms");delay(500);}
For an introduction to photoresistors, see Recipe 2.8.
For Arduino code to display such analog readings, see Recipe 10.12.
For information on voltage dividers, see Recipe 2.6.
To add analog inputs to a Raspberry Pi, see Recipe 12.4.
The Raspberry Pi does not have analog inputs so connect an ADC IC to the Raspberry Pi.
Use the MCP3008 8-channel ADC chip. This chip actually has eight analog inputs, so you can connect up to eight sensors to one of these and interface to the chip using the Raspberry Pi SPI. Figure 12-10 shows the schematic for using an MCP3008 with a Raspberry Pi.
Note that these analog inputs have a maximum input voltage of 3.3V. You will also need to make sure the SPI of the Raspberry Pi is enabled and the py-spidev Python library (included in new releases of Raspbian) is installed (Recipe 10.16).
You can find the Raspberry Pi program to access and display the analog readings from analog channel 0 in the program ch_12_mcp3008.py (see Recipe 10.4):
importspidev,timespi=spidev.SpiDev()spi.open(0,0)defanalog_read(channel):r=spi.xfer2([1,(8+channel)<<4,0])adc_out=((r[1]&3)<<8)+r[2]returnadc_outwhileTrue:reading=analog_read(0)voltage=reading*3.3/1024("Reading=%d\tVoltage=%f"%(reading,voltage))time.sleep(1)
You can use this recipe with Recipe 12.7, Recipe 12.9, and Recipe 12.10 to read analog sensors with a Raspberry Pi.
You can use resistive sensors with a Raspberry Pi directly, without the need for an ADC IC (see Recipe 12.5).
See how long it takes for a capacitor to charge the resistive sensor and use this time to calculate the resistance of the sensor.
Figure 12-11 shows the schematic for measuring resistance using nothing more than two resistors and a capacitor.
A Python library to simply read values of resistance can be downloaded from GitHub where you will also find installation instructions and documentation.
The following example shows how you can use this library to measure the value of the sensor resistance when the schematic of Figure 12-11 is wired up to a Raspberry Pi with pin A connected to GPIO 18 and pin B to GPIO 23. The program is located in the examples folder of the pi_analog library and is called resistance_meter.py:
fromPiAnalogimport*importtimep=PiAnalog()whileTrue:(p.read_resistance())time.sleep(1)
To test out the method, try using a few different values of fixed resistance. You can also use different values of C1 and R1 by specifying the value of capacitance in µF and R1 in Ω in the constructor. For example, for high resistance values you might want to use a smaller capacitor (10nF) to speed up the conversion. You could use the following code:
fromPiAnalogimport*importtimep=PiAnalog(0.01,1000)whileTrue:(p.read_resistance())time.sleep(1)
This technique relies on the ability of GPIO pins to switch between being an input and an output while the controlling program is running.
The basic steps for taking a measurement are as follows:
The Monk Makes Electronics Starter Kit for Raspberry Pi has several projects that use this step-response method to measure temperature and light.
If you have an Arduino or board with analog inputs then use Recipe 12.3. If your board does not have analog inputs (say a Raspberry Pi) then use Recipe 12.4 or Recipe 12.5.
All the preceding methods will work just fine for determining if the sensor is illuminated more brightly in one reading than in another, but obtaining a measurement in common units of light measurement is a lot trickier. Questions that make getting the light measurement difficult are:
Even if you answer these questions, you get into problems with the linearity of the photoresistor and will likely need to manually calibrate your meter to account for manufacturing differences in the photoresistors.
In other words, despite its apparrant simplicity making a light meter that will give you a reading in Lux or Watts per square meter is a specialist task.
For a discussion on light measurement, see https://en.wikipedia.org/wiki/Lux.
Use a thermistor in a voltage-divider arrangement (see Recipe 12.3), calculate the resistance, and then use the Steinhart–Hart equation to calculate the temperature.
Figure 12-12 shows the schematic for connecting a thermistor to an Arduino analog input. You should use an NTC thermistor, which has a specified nominal resistance (its resistance at 25° C) and a value of B (sometimes called beta) that determines its resistance characteristics.
You can calculate the resistance of the thermistor R1 using the voltage-divider formula (see Recipe 2.6):
This can be rearranged to:
With a 5V Arduino and a fixed 1k resistor for R2, this gives:
The Steinhart–Hart equation states that:
where:
If you plug all this math into an Arduino sketch and wire up a thermistor as shown in Figure 12-12, you end up with the following code, which can also be found with the downloads for the book in the sketch ch_12_thermistor:
constintinputPin=A0;// r2 is the bottom fixed resistor in the voltage dividerconstfloatr2=1000.0;// thermistor propertiesconstfloatB=3800.0;constfloatr0=1000.0;// other constantsconstfloatvin=5.0;constfloatt0k=273.15;constfloatt0=t0k+25;voidsetup(){pinMode(inputPin,INPUT);Serial.begin(9600);}voidloop(){intreading=analogRead(inputPin);floatvout=reading/204.6;floatr=(r2*(vin-vout))/vout;floatinv_t=1.0/t0+(1.0/B)*log(r/r0);floatt=(1.0/inv_t)-t0k;Serial.(t);Serial.println(" deg C");delay(500);}
To measure temperature using a thermistor, the step-response method, and a thermistor, see Recipe 12.8.
You can find an example of using an analog temperature-sensing IC in Recipe 12.10 and a digital device in Recipe 12.11.
Use a thermistor and the pi-analog library as described in Recipe 12.5. Figure 12-13 shows the schematic for connecting a thermistor to a Raspberry Pi.
The thermistor should be an NTC device. This just means that as the temperature gets hotter the resistance gets lower. You will need to know its nominal resistance (at 25 C) and its value of B.
The pi-analog library has a program for reading the temperature in degrees C that you will find in the examples folder for the library called thermometer.py. The code for this is listed here:
fromPiAnalogimport*importtimep=PiAnalog()whileTrue:(p.read_temp_c(3800,1000))time.sleep(1)
The two parameters to read_temp_c are the thermistor’s value of B and resistance, which should be changed to suit your thermistor.
To use a thermistor with analog inputs, see Recipe 12.7.
For more information on thermistors, see https://en.wikipedia.org/wiki/Thermistor.
You can find an example of using an analog temperature-sensing IC in Recipe 12.10.
Use the pot as a potential divider, with the slider attached to an analog input as shown in Figure 12-14.
The voltage at the slider will vary from 0V to the supply voltage as you rotate the pot’s knob. You can use the same test program as Recipe 12.3 to measure the position.
Although a Raspberry Pi does not have analog inputs, you can still use this technique with a Raspberry Pi if you add an ADC chip as described in Recipe 12.4.
For devices without an analog input, you can use the step-response method to measure the resistance between one end of the pot and the slider as shown in Figure 12-15.
The resistance between the slider and the end of the pot will vary from 0Ω to the maximum resistance of the pot as you rotate the pot’s knob. You can use the test program from Recipe 12.5 to measure the resistance of the pot and hence the rotary position.
The voltage-divider approach will produce more consistent results than the step-response method.
For more on pots, see Recipe 2.3.
You can use a quadrature encoder (Recipe 12.2) to measure rotary movement.
For background on voltage dividers, see Recipe 2.6.
Use a temperature-sensing IC such as the TMP36 or LM35. Figure 12-16 shows how you would connect such a device to the analog input of an Arduino. If you want to use such a sensor with a Raspberry Pi, you need to add analog inputs as described in Recipe 12.4. The TMP36 can operate from 3.3V or 5V.
Note that only the SMD version of this IC has the extra SHUTDOWN pin. This can be connected to a digital output of, say, an Arduino to reduce the current consumption of the IC to 100nA when the pin is set to LOW.
C1 should be placed as close to the IC as possible.
The temperature of a TMP36 in degrees C (let’s call it t) is related to the voltage by the following formula:
where v is the output voltage of the TMP36. So, if the output voltage is 0V, the temperature is –50° C; if it is 1V, the temperature is 50° C.
Figure 12-17 shows the breadboard layout for connecting the three-pin through-hole version of the TMP36, connected to an Arduino.
The Arduino sketch ch_12_tmp36 illustrates the use of this device. You can find this sketch here and with the downloads for the book (see Recipe 10.2):
constintinputPin=A0;constfloatsensitivity=0.01;// V/deg Cconstfloatoffset=-50.0;// deg Cvoidsetup(){pinMode(inputPin,INPUT);Serial.begin(9600);}voidloop(){intreading=analogRead(inputPin);floatvolts=reading/204.6;floatdegC=(volts/sensitivity)+offset;// float degF = degC * 9.0 / 5.0 + 32.0;Serial.println(degC);delay(500);}
The two constants sensitivity and offset allow you to use the sketch with other temperature sensors in the TMP36 family of ICs that have different sensitivity and temperature ranges.
The TMP36 is not a very accurate device. The datasheet says ±2° C, which is fairly typical in practice and probably with similar accuracy as a thermistor (although the math is a lot easier). For greater accuracy, you should look at a digital sensor like the DS18B20 (see Recipe 12.11).
For the TMP36 datasheet, see http://bit.ly/2mbtFsg.
To measure temperature using a thermistor and an analog input, see Recipe 12.7.
You don’t have to have a microcontroller or SBC to make use of a sensor like this. For simple thermostatic applications, you can use a comparator IC (see Recipe 17.10).
Use a digital temperature measurement IC like the DS18B20, which is factory calibrated to provide an accuracy of ±0.5° C.
This IC uses a 1-wire interface bus that allows up to 255 of the ICs to be connected to just one GPIO port. Figure 12-18 shows a schematic diagram for connecting a DS18B20s to an Arduino. The IC will work just as well with the 3.3V supply of a Raspberry Pi, although in the case of the Pi, GPIO pin 4 must be used as this pin is earmarked for use by the 1-wire interface.
The 4.7kΩ external pull-up resistor is necessary for the 1-wire bus to operate reliably.
Having connected the DS18B20 as shown in Figure 12-18, you will need to download the OneWire library and the DallasTemperature library. In both cases choose the Download ZIP option from the GitHub page and then add the ZIP library to your Arduino IDE from the Sketch→Include Library→Add ZIP Library menu option.
The following sketch illustrates the use of a single DS18B20, reporting the temperature to the Serial Monitor every half-second. You can find the sketch here and with the downloads for the book; it is called ch_12_ds18b20:
#include <OneWire.h>#include <DallasTemperature.h>constinttempPin=2;OneWireoneWire(tempPin);DallasTemperaturesensors(&oneWire);voidsetup(){Serial.begin(9600);sensors.begin();}voidloop(){sensors.requestTemperatures();floattemp=sensors.getTempCByIndex(0);Serial.println(temp);}
Because you can attach multiple sensors to a single GPIO pin, the getTempCByIndex function takes the number of the sensor that you wish to use (starting at 0). If you have multiple sensors you will have to use trial and error to identify which is which.
Raspbian has support for the 1-wire interface used by the DS18B20 but you have to enable it by editing the file /boot/config.txt and adding the following line to the end of the file. Then reboot your Raspberry Pi for the change to take effect.
dtoverlay=w1-gpio
The program for this is called ch_12_ds18b20.py and can be found with the downloads for the book (see Recipe 10.4):
importglob,timebase_dir='/sys/bus/w1/devices/'device_folder=glob.glob(base_dir+'28*')[0]device_file=device_folder+'/w1_slave'defread_temp_raw():f=open(device_file,'r')lines=f.readlines()f.close()returnlinesdefread_temp():lines=read_temp_raw()whilelines[0].strip()[-3:]!='YES':time.sleep(0.2)lines=read_temp_raw()equals_pos=lines[1].find('t=')ifequals_pos!=-1:temp_string=lines[1][equals_pos+2:]temp_c=float(temp_string)/1000.0returntemp_cwhileTrue:(read_temp())time.sleep(1)
As with the Arduino version of this program, the sensor to be read is accessed by position in the line:
device_folder = glob.glob(base_dir + '28*')[0]
The interface to the DS18B20 uses a file-like structure. The file interface will always be in the folder /sys/bus/w1/devices/ and the name of the file path will start with 28, but the rest of the file path will be different for each sensor.
The code assumes that there will only be one sensor, and finds the first folder starting with 28. To use multiple sensors, use different index values inside the square brackets.
Within that folder will be a file called w1_slave, which is opened and read to find the temperature.
The sensor actually returns strings of text like this:
81 01 4b 46 7f ff 0f 10 71 : crc=71 YES 81 01 4b 46 7f ff 0f 10 71 t=24062
The code extracts the temperature part of this message. This appears after t= and is the temperature in one-thousandths of a degree Celsius.
The read_temp function calculates the temperature in degrees Celsius and returns it.
If you want to attach multiple sensors (up to 255) you can wire them up as shown in Figure 12-19. Only the one pull-up resistor is needed, and because the sensor is digital and at a low data transmission rate, you can attach sensors to long leads with no effect on the accuracy of the reading.
If you would rather have just two wires running to your DS18B20, you can use the device’s special parasitic power feature. In essence, it harvests energy from the data line, storing it temporarily in capacitors inside the IC. In parctical terms, the 3-wire method will allow you to use longer wires to your sensor and will be more reliable, but see the IC’s datasheet if you wish to use this mode.
If you plan to deploy your sensor somewhere wet, use encapsulated DS18B20 sensors that are enclosed in a waterproof case that can be found on eBay.
The DS18B20 datasheet can be found here: http://bit.ly/2mTPyuu
To measure temperature with a thermistor, see Recipe 12.7 and Recipe 12.8.
To measure temperature with the TMP36 analog temperature-sensing IC, see Recipe 12.10.
Use a DHT11 humidity and temperature sensor, which has a serial output that does not really conform to any bus standard like 1-wire, I2C, or SPI. However, libraries for both Arduino and Raspberry Pi are available for it.
Figure 12-20 shows how it should be connected to an Arduino. When used with a Raspberry Pi, the pin labeled VDD (voltage drain drain) should be connected to 3.3V and the DATA pin to GPIO 4.
When connecting to a Raspberry Pi, use the 3.3V power connector not the 5V one and connect the data pin of the DHT11 to GPIO4.
The Arduino sketch can be found with the downloads for the book (Recipe 10.2) and is called ch_12_dht11. The sketch requires the Arduino SimpleDHT library to be installed. You can do this from the Arduino Library Manager by using the option Sketch→Include Library→Manage Libraries, searching for SimpleDHT, and then clicking the Install button next to the library.
#include <SimpleDHT.h>constintpinDHT11=2;SimpleDHT11dht11;voidsetup(){Serial.begin(9600);}voidloop(){bytetemp;bytehumidity;dht11.read(pinDHT11,&temp,&humidity,NULL);Serial.(temp);Serial.(" C, ");Serial.(humidity);Serial.println(" %");delay(1000);}
The call to dht11.read is a little unusual because it passes the variables temp and humidity with an & in front of them to indicate that they can be changed within the read function. In this way, after the read function has finished executing, temp and humidity will have updated values.
The Raspberry Pi code for this sensor requires an Adafruit library to be installed using the following commands:
$ git clone https://github.com/adafruit/Adafruit_Python_DHT.git $ cd Adafruit_Python_DHT $ sudo python setup.py install
The program itself can be found with the downloads for the book (Recipe 10.4) and is called ch_12_dht11.py:
importtime,Adafruit_DHTsensor_pin=4sensor_type=Adafruit_DHT.DHT11whileTrue:humidity,temp=Adafruit_DHT.read_retry(sensor_type,sensor_pin)(str(temp)+" C "+str(humidity)+" %")time.sleep(1)
The DHT11 is the cheapest and most common series of similar sensors with different accuracies. For better quality results use the DHT22.
Other recipes for measuring temperature are Recipe 12.7, Recipe 12.8, Recipe 12.10, and Recipe 12.11.
For distances between 4 inches (10cm) and 6 feet (2m) use an HC-SR04 ultrasonic rangefinder module.
Figure 12-21 shows how the rangefinder is connected to an Arduino. Interfacing to it requires one pin of the Arduino to act as a digital output (connected to TRIG) and one as a digital input (connected to ECHO).
The TRIG pin causes the HC-SR04 to emit a pulse of ultrasound at 40kHz and the ECHO pin goes high when the reflected sound wave is received. The time taken for this to happen is an indication of the distance from the sensor to the object.
To connect the rangefinder to a Raspberry Pi, the output voltage of the ECHO pin of the rangefinder needs to be reduced to 3.3V. This can be done with a simple level converter using a pair of resistors as a voltage divider. The schematic for this is shown in Figure 12-22.
For more information on level conversion, see Recipe 10.17.
An Arduino sketch (ch_12_rangefinder) for rangefinding can be found with the downloads for the book (see Recipe 10.2):
constinttrigPin=9;constintechoPin=10;voidsetup(){pinMode(trigPin,OUTPUT);pinMode(echoPin,INPUT);Serial.begin(9600);}voidloop(){floatcm=takeSounding();Serial.(int(cm));Serial.(" cm ");intinches=int(cm/2.5);Serial.(inches);Serial.println(" inches");delay(500);}floattakeSounding(){digitalWrite(trigPin,HIGH);delayMicroseconds(10);// 10us trigger pulsedigitalWrite(trigPin,LOW);delayMicroseconds(200);// ingore echos while sending 200uslongduration=pulseIn(echoPin,HIGH,100000)+200;floatdistance=duration/29.0/2.0;returndistance;}
All the action takes place in the takeSounding function. First, a 10µs pulse is sent to the TRIG pin of the rangefinder resulting in a burst of eight cycles of 40kHz ultrasound. The 200µs delay allows time for this burst to complete before measuring the time taken until an echo is received.
The distance is calculated using the speed of sound (29cm/µs.) The value is divided by 2 because the time taken is for both the outward and return journey of the sound signal.
The Raspberry Pi program can be found in the file ch_12_rangefinder.py with the downloads for the book (see Recipe 10.4):
importRPi.GPIOasGPIOimporttimetrigger_pin=18echo_pin=23# USE LEVEL CONVERTER 5V->3.3VGPIO.setmode(GPIO.BCM)GPIO.setup(trigger_pin,GPIO.OUT)GPIO.setup(echo_pin,GPIO.IN)deftime_to_echo(timeout):t0=time.time()whileGPIO.input(echo_pin)==Falseandtime.time()<(t0+timeout):passt0=time.time()whileGPIO.input(echo_pin)==Trueandtime.time()<(t0+timeout):passreturntime.time()-t0defget_distance():GPIO.output(trigger_pin,True)time.sleep(0.00001)# 10usGPIO.output(trigger_pin,False)time.sleep(0.0002)# 200uspulse_len=time_to_echo(1)distance_cm=pulse_len/0.000058distance_in=distance_cm/2.5return(distance_cm,distance_in)whileTrue:("cm=%f\tinches=%f"%get_distance())time.sleep(1)
The HC-SR04 rangefinders are not particularly accurate, especially when used with a Raspberry Pi, where the operating system will sometimes increase the timing readings for the echo.
Another unwanted influence on the readings comes from variations in the speed of sound. This changes a little both with temperature and humidity.
The datasheet for the HC-SR04 module can be found here: http://bit.ly/2mTOPtn.
This chapter looks at various types of motors and how both their speed and direction can be controlled. This involves the electronics of controlling fairly high load currents as well as the software needed. This chapter will cover examples for Arduino and Raspberry Pi.
When people talk of motors, what tends to spring to mind are the small DC motors that you might find in a battery-powered toy car. DC motors are common and often combined with a gearbox to reduce their high speed of rotation into a single unit called a gearmotor.
Stepper motors operate on a different principle and are found in printers of all sorts including 3D printers as they can be advanced in small steps (typically 1/200 of a revolution or more).
Servomotors fit a different niche, allowing accurate positioning of their “arm” in a restricted range of angles (about 180°). Servomotors are often found controlling the steering of a remote-control car or the control surfaces of a remote-control plane or helicopter.
All of these types of motors are available in various sizes to meet the power requirements of different applications. Whatever the size, controlling such motors follows the same basic principles.
Use a transistor switch, but add a snubbing diode as shown in Figure 13-1. This is based on Recipe 11.1, which is fine for a small DC motor. For higher currents use a power MOSFET as described in Recipe 11.3.
The diode D1 prevents the transistor from being damaged. A “snubbing” diode like this should always be used to protect a switching transistor from excessive reverse voltage that occurs when the inductive load of the motor releases stored energy as a pulse of voltage in the opposite polarity to that in which it was driven. This reverse voltage is called “back-emf.”
It is not usually necessary to use a snubbing diode with a power MOSFET, because these devices have built-in diodes to prevent damage from electrostatic discharge, which will also protect against voltage spikes. They are (at least for relatively modest motors) sufficient to protect the transistor. However, adding a diode as you would with a BJT is the safest thing to do.
If you want to wire up the circuit of Figure 13-1, you can use the test programs in Recipe 11.6 and Recipe 11.7 to control a motor from an Arduino or Raspberry Pi.
Many of the techniques described in Chapter 11 can be used to switch a motor.
To control the speed of a motor, see Recipe 13.2.
Using a transistor switch and PWM to adjust the speed of the motor, measure the motor’s speed using an optical detector and slotted wheel attached to the shaft of the motor.
You can use the schematic in Figure 13-2 and pulse the GPIO control pin with PWM as described in Recipe 10.13 and Recipe 10.14.
Using PWM to control a motor actually controls the power supplied to the motor rather than its speed, but assuming the motor’s load remains constant, these amount to the same thing.
Measuring the motor speed requires a sensor that does not interfere with the rotation of the motor. One way to do this is to use an optical sensor like the prebuilt model shown in Figure 13-2 along with a laser-cut disk that has slots in it. As the disk rotates it alternately blocks and allows light to pass, resulting in a series of pulses that can be used to determine both the speed of the motor and the number of rotations it has made.
The optical sensor includes a built-in comparator and has an “open collector” (Recipe 11.11) output that requires a 1kΩ pull-up resistor to 5V. These sensors are readily available from eBay for a few dollars.
The motor-control circuit uses a MOSFET in the circuit described in Recipe 11.3.
The sketch ch_13_motor_speed_feedback (see Recipe 10.2) reports the speed of the motor in RPM (revolutions per minute) once every second in the Serial Monitor. It also allows you to send a PWM value of 0 to 255 to control the speed of the motor.
Make sure that the Line endings drop-down list of the Serial Monitor is set to “No line ending.”
constintoutputPin=11;constintsensePin=2;constintslotsPerRev=20;constlongupdatePeriod=1000L;// mslonglastUpdateTime=0;longpulseCount=0;floatrpm=0;voidsetup(){pinMode(outputPin,OUTPUT);Serial.begin(9600);Serial.println("Enter speed 0 to 255");attachInterrupt(digitalPinToInterrupt(sensePin),incPulseCount,RISING);}voidloop(){if(Serial.available()){intsetSpeed=Serial.parseInt();analogWrite(outputPin,setSpeed);}updateRPM();}voidincPulseCount(){pulseCount++;}voidupdateRPM(){longnow=millis();if(now>lastUpdateTime+updatePeriod){lastUpdateTime=now;rpm=float(pulseCount)*60000.0/(20.0*updatePeriod);pulseCount=0;Serial.println(rpm);}}
An interrupt is used so that every time the sensePin goes from LOW to HIGH the function incPulseCount is called that increments the value of pulseCount.
The function updateRPM will use pulseCount to calculate the RPM once per second before resetting pulseCount to 0.
To just turn a motor on and off, see Recipe 13.1, and to control the direction of a DC motor, see Recipe 13.3.
Use an H-bridge circuit that consists of two push-pull drivers. To keep the number of components low, this is normally accomplished using an H-bridge IC. Figure 13-3 shows the schematic for using the popular L293D motor controller with an Arduino to control two DC motors independently.
The L293D has separate voltage supplies for the ICs logic (VCC1) and the motor (VCC2). This allows the motor to operate at a different voltage than the logic and also reduces the problem of electrical noise caused by the motor disrupting the logic.
Speed control of the motors is accomplished by using a PWM signal to drive the 1,2EN and 3,4EN pins that enable the push-pull drivers in pairs. The direction of one motor is controlled by the L293D pins 1A and 2A and the second motor by 3A and 4A. Table 13-1 shows the four possible states of motor drive for the control pins 1A and 2A.
| 1A | 2A | Motor M1 |
|---|---|---|
| LOW | LOW | Off |
| LOW | HIGH | Clockwise |
| HIGH | LOW | Counter-clockwise |
| HIGH | HIGH | Fast-stop |
To control the motors, three Arduino pins are needed for each motor. One to control the speed and two for the A and B control pins for the direction that are connected to the 1A and 2A control pins for one motor and the 3A and 4A pins of the L293 for the other.
constintmotor1SpeedPin=5;constintmotor2SpeedPin=6;constintmotor1DirAPin=2;constintmotor1DirBPin=3;constintmotor2DirAPin=4;constintmotor2DirBPin=7;voidsetup(){pinMode(motor1SpeedPin,OUTPUT);pinMode(motor2SpeedPin,OUTPUT);pinMode(motor1DirAPin,OUTPUT);pinMode(motor1DirBPin,OUTPUT);pinMode(motor2DirAPin,OUTPUT);pinMode(motor2DirBPin,OUTPUT);Serial.begin(9600);// M1 full speed clockwiseanalogWrite(motor1SpeedPin,255);digitalWrite(motor1DirAPin,LOW);digitalWrite(motor1DirBPin,HIGH);// M2 half speed counter-clockwiseanalogWrite(motor2SpeedPin,127);digitalWrite(motor2DirAPin,HIGH);digitalWrite(motor2DirBPin,LOW);}voidloop(){}
The code sets all the control pins to be outputs and then sets one motor to go at full speed in one direction and the other at half speed in the other. Try experimenting with this code to make the motors behave differently.
The 3.3V digital outputs of a Raspberry Pi will work just fine connected to the L293D, but the logic supply to the L293D must be 4.5V or more, so the 5V pin of the Raspberry Pi GPIO connector should be used. Table 13-2 shows the connections between Raspberry Pi and L293D.
| Raspberry Pi GPIO Pin | L293D Pin Name | L293 Pin Number(s) | Function |
|---|---|---|---|
| 5V | VCC1 | 16 | Logic supply |
| GND | GND | 12 | Ground |
| GPIO18 | 1,2EN | 1 | M1 speed |
| GPIO23 | 3,4EN | 9 | M2 speed |
| GPIO24 | 1A | 2 | M1 direction A |
| GPIO17 | 2A | 7 | M1 direction B |
| GPIO27 | 3A | 10 | M2 direction A |
| GPIO22 | 4A | 15 | M2 direction B |
The following Python programs (ch_13_l293d.py) will set M1 to operate at full speed in one direction and M2 at half-speed in the other direction:
importRPi.GPIOasGPIOGPIO.setmode(GPIO.BCM)# Define pinsmotor_1_speed_pin=18motor_2_speed_pin=23motor_1_dir_A_pin=24motor_1_dir_B_pin=17motor_2_dir_A_pin=27motor_2_dir_B_pin=22# Set pin modesGPIO.setup(motor_1_speed_pin,GPIO.OUT)GPIO.setup(motor_2_speed_pin,GPIO.OUT)GPIO.setup(motor_1_dir_A_pin,GPIO.OUT)GPIO.setup(motor_1_dir_B_pin,GPIO.OUT)GPIO.setup(motor_2_dir_A_pin,GPIO.OUT)GPIO.setup(motor_2_dir_B_pin,GPIO.OUT)# Start PWMmotor_1_pwm=GPIO.PWM(motor_1_speed_pin,500)motor_1_pwm.start(0)motor_2_pwm=GPIO.PWM(motor_2_speed_pin,500)motor_2_pwm.start(0)# Set one motor to full speedmotor_1_pwm.ChangeDutyCycle(100)GPIO.output(motor_1_dir_A_pin,False)GPIO.output(motor_1_dir_B_pin,True)# Second motor to half speedmotor_2_pwm.ChangeDutyCycle(50)GPIO.output(motor_2_dir_A_pin,True)GPIO.output(motor_2_dir_B_pin,False)input("Enter '0' to stop ")("Cleaning up")GPIO.cleanup()
The code follows the same pattern as its Arduino counterpart. First, the pins are set to be outputs and then two PWM channels are defined to control the motor speeds. Finally, one motor is set to full speed in one direction and the other to half-speed in the other direction.
The function GPIO.cleanup() sets all the pins to be inputs just before the program exits to stop both motors.
Figure 13-4 shows a “schematic” for what is going on with an H-bridge driver. Don’t try and build this schematic; if you do, prepare for the possibility of destroying some of the transistors if Q1 and Q2 or Q3 and Q4 are turned on at the same time. Also, this circuit will only stand a chance of working if the motor voltage is almost the same as the logic voltage of the control pins (see Recipe 11.4).
The idea of the circuit is that the control pin A makes Q1 conduct if it is LOW and Q2 conduct if it is HIGH. Similarly control pin B makes Q3 conduct if it is low and Q4 conduct if pin B is HIGH.
By setting A and B, you can control the direction of flow of current through the motor according to Table 13-1.
For more information on push-pull (half-bridge) drivers, see Recipe 11.8.
A servomotor offers the solution to this problem. Wire the servomotor up as shown in Figure 13-5.
Generally servomotors will use a separate power supply from the supply used by the Arduino or Raspberry Pi, as the large load current as the motor starts may well drop the supply voltage enough to reset the controlling device. However, for a small lightly loaded servomotor, you may get away with using the same supply for both.
The resistor R1 is there to protect the GPIO pin, but is not strictly necessary as most servomotors draw very little current from the control pin. But if you do not have the datasheet for the servo you are using then R1 is a sensible precaution.
Figure 13-6 shows a small 9g hobby servo. The connector to the servo is fairly standardized, but you should also check the servomotor’s datasheet.
The red lead is the positive supply to the motor, the brown lead the ground connection, and the orange lead the control signal.
The control signal will normally be fine with a 3.3V logic, but if the datasheet for the servomotor indicates that this needs to be higher, use a level converter (Recipe 10.17).
The following example code (ch_13_servo) in the downloads for the book (see Recipe 10.2) assumes that the control pin of a servo is connected to pin 9 of an Arduino Uno.
When you open the Arduino Serial Monitor you will be prompted to enter an angle for the servoarm:
#include <Servo.h>constintservoPin=9;Servoservo;voidsetup(){voidsetup(){servo.attach(servoPin);servo.write(90);Serial.begin(9600);Serial.println("Angle in degrees");}voidloop(){if(Serial.available()){intangle=Serial.parseInt();servo.write(angle);}}
Make sure that you have Line endings drop-down on the Serial Monitor set to “No line ending.”
The servo.write method of the servo library sets the servo arm to an angle in degrees between 0 and 180.
The Raspberry Pi equivalent of the Arduino sketch is ch_13_servo.py in the book downloads (see Recipe 10.4):
importRPi.GPIOasGPIOimporttimeservo_pin=18# Tweak these values to get full range of servo movementdeg_0_pulse=0.5# msdeg_180_pulse=2.5# msf=50.0#50Hz = 20ms between pulses# Do some calculations on the pulse width parametersperiod=1000/f# 20msk=100/period# duty 0..100 over 20msdeg_0_duty=deg_0_pulse*kpulse_range=deg_180_pulse-deg_0_pulseduty_range=pulse_range*kGPIO.setmode(GPIO.BCM)GPIO.setup(servo_pin,GPIO.OUT)pwm=GPIO.PWM(servo_pin,f)pwm.start(0)defset_angle(angle):duty=deg_0_duty+(angle/180.0)*duty_rangepwm.ChangeDutyCycle(duty)try:whileTrue:angle=input("Angle (0 to 180): ")set_angle(angle)finally:("Cleaning up")GPIO.cleanup()
The set_angle function makes use of the variables deg_0_duty and duty_range, which are calculated once at the start of the program to calculate the duty cycle that will generate a pulse of the right length for the specified angle.
Servomotors rarely have exactly the same range of movement, so this program and its Arduino equivalent are a great way to find the range of angles that your servomotor can reach.
Figure 13-7 shows how the pulses arriving at a servomotor’s control pin alter the angle of the servomotor’s arm.
The servomotor expects a pulse every 20ms to maintain its position. The length of that pulse determines the position of the servomotor’s arm, which can normally travel through about 180°. A short pulse of between 0.5 and 1ms will position the arm at one end of its travel. A pulse of 1.5ms will position the servomotor’s arm in the center position and a long pulse of up to 2.5ms at its furthest travel.
If you have a lot of servomotors to connect to an Arduino or a Raspberry Pi, then it can help to use a servomotor interface board such as the ServoSix board (Figure 13-8).
Using the Python GPIO library to generate the pulses can result in some jitter in the movement of the servoarm. This is due to inaccuracies of the pulse timing as Raspbian tries to do several things at once.
This can be improved by using the ServoBlaster service that configures certain GPIO pins exclusively for servo use or the ServoSix library that is built on ServoBlaster, but it just configures the pins for servo use while the controlling program is running.
Another alternative is to devolve the control of the servos entirely to hardware such as the Adafruit 16-channel servoboard, which is then sent control messages from the Raspberry Pi.
For more information on the ServoBlaster Python library for Raspberry Pi, see https://github.com/richardghirst/PiBits/tree/master/ServoBlaster.
You can find the ServoSix library at https://github.com/simonmonk/servosix and the ServoSix connection board at https://www.monkmakes.com/servosix/.
To use the Adafruit servo interface board, see https://www.adafruit.com/product/815.
A bipolar stepper motor can do what you need. Use a dual H-bridge IC such as the L293D used in Recipe 13.3 to drive the two coils of a bipolar stepper motor. Figure 13-9 shows the schematic diagram for this using an Arduino Uno and Figure 13-10 shows the diagram for a Raspberry Pi.
A push-pull driver is needed for each of the two coils of the stepper motor. The enable pins of the L293D are both tied to a single GPIO pin. Generally the enable pins will be permanently enabled, although they could be used with a high-frequency PWM signal if the stepper motor voltage is below the power-supply voltage.
You can find an Arduino sketch called ch_13_bi_stepper in the downloads for the book (Recipe 10.2):
#include <Stepper.h>constintin1Pin=2;constintin2Pin=3;constintin3Pin=4;constintin4Pin=7;constintenablePin=5;Steppermotor(200,in1Pin,in2Pin,in3Pin,in4Pin);voidsetup(){pinMode(in1Pin,OUTPUT);pinMode(in2Pin,OUTPUT);pinMode(in3Pin,OUTPUT);pinMode(in4Pin,OUTPUT);pinMode(enablePin,OUTPUT);digitalWrite(enablePin,HIGH);Serial.begin(9600);Serial.println("Command letter followed by number");Serial.println("p20 - set the motor speed to 20");Serial.println("f100 - forward 100 steps");Serial.println("r100 - reverse 100 steps");motor.setSpeed(20);}voidloop(){if(Serial.available()){charcommand=Serial.read();intparam=Serial.parseInt();if(command=='p'){motor.setSpeed(param);}elseif(command=='f'){motor.step(param);}elseif(command=='r'){motor.step(-param);}}}
The sketch uses the Stepper library that is included with the Arduino IDE. The library requires you to specify the number of steps as the first parameter in the following line:
Steppermotor(200,in1Pin,in2Pin,in3Pin,in4Pin);
To try out the program, open the Serial Monitor and send commands such as f100, where f is the direction (forward or reverse) and 100 is the number of steps.
The Raspberry Pi software for driving a bipolar stepper motor can be found in the file ch_13_bi_stepper.py. To download the code for the book see Recipe 10.4.
importRPi.GPIOasGPIOimporttimeGPIO.setmode(GPIO.BCM)in_1_pin=18in_2_pin=23in_3_pin=24in_4_pin=25en_pin=22GPIO.setup(in_1_pin,GPIO.OUT)GPIO.setup(in_2_pin,GPIO.OUT)GPIO.setup(in_3_pin,GPIO.OUT)GPIO.setup(in_4_pin,GPIO.OUT)GPIO.setup(en_pin,GPIO.OUT)GPIO.output(en_pin,True)period=0.02defstep_forward(steps,period):foriinrange(0,steps):set_coils(1,0,0,1)time.sleep(period)set_coils(1,0,1,0)time.sleep(period)set_coils(0,1,1,0)time.sleep(period)set_coils(0,1,0,1)time.sleep(period)defstep_reverse(steps,period):foriinrange(0,steps):set_coils(0,1,0,1)time.sleep(period)set_coils(0,1,1,0)time.sleep(period)set_coils(1,0,1,0)time.sleep(period)set_coils(1,0,0,1)time.sleep(period)defset_coils(in1,in2,in3,in4):GPIO.output(in_1_pin,in1)GPIO.output(in_2_pin,in2)GPIO.output(in_3_pin,in3)GPIO.output(in_4_pin,in4)try:('Command letter followed by number');('p20 - set the inter-step period to 20ms (control speed)');('f100 - forward 100 steps');('r100 - reverse 100 steps');whileTrue:command=input('Enter command: ')parameter_str=command[1:]# from char 1 to endparameter=int(parameter_str)ifcommand[0]=='p':period=parameter/1000.0elifcommand[0]=='f':step_forward(parameter,period)elifcommand[0]=='r':step_reverse(parameter,period)finally:('Cleaning up')GPIO.cleanup()
This code does not use a library, but directly sets the outputs of the push-pull drivers to activate the coils in the right sequence to move the motor forward or backward for the specified number of steps.
The preceding code is written for Python 3. If you are running the program as Python 2, then you will need to change the line:
command = input('Enter command: ')
to:
command = raw_input('Enter command: ')
The Python programs in this book are designed to work with Python 2 or Python 3, but the input/raw_input issue is one source of incompatibility between the Python versions that is difficult to code around.
Unlike servomotors, stepper motors can rotate continuously—they just do it one step at a time. Typically a stepper motor will have a few tens to a few hundred steps to one full rotation. Moving the stepper motor from one step position to the next involves activating its two coils in a certain pattern.
The L293D lends itself well to experimenting with stepper motors on a breadboard. Figure 13-11 shows an Arduino wired up from the schematic of Figure 13-9. Note that the GND connections are connected inside the chip, so not all ground connections in the schematic need to be made.
The stepper motor used to test out the preceding examples is from Adafruit, where you will also find a datasheet for the motor).
To use unipolar stepper motors (usually 5-lead), see Recipe 13.6.
Unipolar stepper motors are a little easier to use than their bipolar relatives discussed in Recipe 13.6. They do not need a push-pull half-bridge driver, but can be controlled using a Darlington array chip like the ULN2803. Figure 13-12 shows the schematic for using this IC with an Arduino and Figure 13-13 for a Raspberry Pi.
The ULN2803 contains eight open-collector Darlington transistors, each capable of sinking about 500mA and so can be used to drive two unipolar stepper motors.
You can find an example Arduino sketch that uses the stepper library in ch_13_uni_stepper with the downloads for the book (see Figure 10-2).
#include <Stepper.h>constintin1Pin=2;constintin2Pin=3;constintin3Pin=4;constintin4Pin=7;Steppermotor(513,in1Pin,in2Pin,in3Pin,in4Pin);voidsetup(){pinMode(in1Pin,OUTPUT);pinMode(in2Pin,OUTPUT);pinMode(in3Pin,OUTPUT);pinMode(in4Pin,OUTPUT);Serial.begin(9600);Serial.println("Command letter followed by number");Serial.println("p20 - set the motor speed to 20");Serial.println("f100 - forward 100 steps");Serial.println("r100 - reverse 100 steps");motor.setSpeed(20);}voidloop(){if(Serial.available()){charcommand=Serial.read();intparam=Serial.parseInt();if(command=='p'){motor.setSpeed(param);}elseif(command=='f'){motor.step(param);}elseif(command=='r'){motor.step(-param);}}}
The sketch is pretty much the same as that of Recipe 13.5, but in this case there is no enable pin possible. See the sketch in Recipe 13.5 for a description of the code.
The Raspberry Pi version of the software can be found in the program ch_13_uni_stepper.py. It is identical to that of Recipe 13.5 but with the driver-enable feature removed:
importRPi.GPIOasGPIOimporttimeGPIO.setmode(GPIO.BCM)in_1_pin=18in_2_pin=23in_3_pin=24in_4_pin=25GPIO.setup(in_1_pin,GPIO.OUT)GPIO.setup(in_2_pin,GPIO.OUT)GPIO.setup(in_3_pin,GPIO.OUT)GPIO.setup(in_4_pin,GPIO.OUT)period=0.02defstep_forward(steps,period):foriinrange(0,steps):set_coils(1,0,0,1)time.sleep(period)set_coils(1,0,1,0)time.sleep(period)set_coils(0,1,1,0)time.sleep(period)set_coils(0,1,0,1)time.sleep(period)defstep_reverse(steps,period):foriinrange(0,steps):set_coils(0,1,0,1)time.sleep(period)set_coils(0,1,1,0)time.sleep(period)set_coils(1,0,1,0)time.sleep(period)set_coils(1,0,0,1)time.sleep(period)defset_coils(in1,in2,in3,in4):GPIO.output(in_1_pin,in1)GPIO.output(in_2_pin,in2)GPIO.output(in_3_pin,in3)GPIO.output(in_4_pin,in4)try:('Command letter followed by number');('p20 - set the inter-step period to 20ms (control speed)');('f100 - forward 100 steps');('r100 - reverse 100 steps');whileTrue:command=raw_input('Enter command: ')parameter_str=command[1:]# from char 1 to endparameter=int(parameter_str)ifcommand[0]=='p':period=parameter/1000.0elifcommand[0]=='f':step_forward(parameter,period)elifcommand[0]=='r':step_reverse(parameter,period)finally:('Cleaning up')GPIO.cleanup()
The unipolar stepper motor that I used to validate these recipes is this Adafruit model: https://www.adafruit.com/product/858.
To use bipolar stepper motors, see Recipe 13.6.
The ULN2803 datasheet can be found here: http://www.ti.com/lit/ds/symlink/uln2803a.pdf.
LEDs can be used both for illumination and as indicators. They can also be arranged as 7-segment displays or as tiny pixels in an OLED (organic LED) display.
This chapter contains recipes relating to powering and controlling LEDs as well as for using a display with an Arduino or Raspberry Pi.
Back in Recipe 4.4 you saw how an LED needs a series resistor to prevent too much current from flowing. Too much current will shorten the life of an LED, but more importantly, it may damage or destroy the Arduino or Raspberry Pi GPIO pin that is controlling the LED.
Wire up your LED to a GPIO pin as shown in Figure 14-1 and then use Table 14-1 to select a value for the series resistor.
| Infrared | Red | Orange/Yellow/Green | Blue/White | Violet | UV | |
|---|---|---|---|---|---|---|
| Vf | 1.2-1.6V | 1.6-2V | 2-2.2V | 2.5-3.7V | 2.7-4V | 3.1-4.4V |
| 3.3V GPIO 3mA | 1kΩ | 680Ω | 470Ω | 270Ω | 220Ω | 68Ω |
| 3.3V GPIO 16mA | 150Ω | 120Ω | 82Ω | 56Ω | 39Ω | 15Ω |
| 5V GPIO 20mA | 220Ω | 180Ω | 150Ω | 150Ω | 120Ω | 100Ω |
In practice, nearly all LEDs will illuminate to some degree even from 3.3V with a 1kΩ resistor limiting the current. So, as an even broader rule of thumb, if you don’t care about optimizing the brightness of your LED then a 270Ω resistor is fine.
For optimum brightness find the datasheet for your LED and use the forward-voltage Vf and maximum forward current If with the formula in Recipe 4.4 to calculate the optimum value of resistor.
If you connect an LED as shown in Figure 14-1 you can test turning it on and off using an Arduino and Raspberry Pi with Recipe 10.8 and Recipe 10.9.
A convenient thing to have around if you want to use LEDs with a Raspberry Pi is a Raspberry Squid (Figure 14-2). This has series resistors for the red, green, and blue LEDs built-in to the leads, so you can just plug it straight onto the GPIO connector of a Raspberry Pi.
For more background on LEDs, see Recipe 4.4.
To make your own Raspberry Squid, see https://github.com/simonmonk/squid.
Modify Recipe 7.7 to add a control input for the LED driver as shown in Figure 14-4.
When the GPIO pin is low, Q1 will be off and effectively takes no part in the circuit. The LM317 then acts as a constant-current source where R2 sets the current as discussed in Recipe 7.7 according to the formula:
So if you know what current you want to set, you can calculate the value of R2 using:
Since R3 is very low compared to the input impedance of the Adjust pin of the LM317, it can be ignored.
When the GPIO pin is taken above the gate-threshold voltage of Q1, Q1 will turn on, pulling the Adjust pin low and reducing the regulated voltage to 0V.
The LM317 will get hot if the DC-input voltage is significantly higher than the forward voltage of the LED. In fact, the power it will turn into heat will be:
where If is the forward voltage of the LED, Vin is the input voltage, and Vf is the forward voltage of the LED.
R2 will generally be a low-value resistor that will produce heat with a power of:
As an example, Figure 14-5 shows the circuit of Figure 14-4 supplying 120mA to a high-power LED. For this, R2 is a 10Ω 1/4W resistor. The control pin is connected to a GPIO pin of an Arduino.
You can turn the LED on and off using the sketch from Recipe 10.8 but on and off will be swapped over because a HIGH at the GPIO pin will turn the LED off.
You can also use PWM to control the LED brightness, but again, the logic is inverted, so you will need to modify the following line in ch_10_analog_output from:
int brightness = Serial.parseInt();
to be:
int brightness = 255 - Serial.parseInt();
You can use the Python program from Recipe 10.9, but as with the equivalent Arduino sketch the on/off logic will be inverted.
For brightness control, you will also need to modify the line:
duty = int(duty_s)
to be:
duty = 100 - int(duty_s)
The LM317 datasheet can be found here: http://www.ti.com/lit/ds/symlink/lm317.pdf.
Arrange columns of LEDs in series to match the supply voltage, with a current-limiting resistor for each column. The example in Figure 14-6 shows how you could power 20 LEDs with a forward voltage of 1.7V and a forward current of around 20mA from a 12V power supply.
In this case, five forward-biased LEDs in a column will drop a total of 8.5V, leaving 3.5V to be dropped across the resistor. Using Ohm’s Law, this means the resistor should have a value of 175Ω so a standard value of 180Ω would lower the current just slightly but enough.
While it’s tempting to reduce the number of resistors you need by putting more LEDs in series, this can cause practical problems of overcurrent if the stated forward voltage of the LEDs is not quite accurate. As a rule of thumb, I generally like to keep ¼ of the supply voltage for the series resistor.
The extreme version of this design is to power a long series of LEDs directly from mains voltage. It works, but frankly this is just terrifying—don’t do it.
It’s tempting to consider just putting LEDs in series to share a series resistor as shown in Figure 14-7.
The problem with doing this is that if there are slight variations in the forward voltage of each LED (which there will be) the LED with the smallest Vf will start conducting first and immediately draw ALL the current from the resistor. This may well burn out the LEDs one at a time.
For basic information on LEDs and series resistors, see Figure 14-1.
There is a nice online calculator that will do the series resistor calculations for you here: http://led.linear1.org/led.wiz.
You have a big bank of LEDs (see Recipe 14.3) and you want to switch them all on and off from an Arduino or Raspberry Pi.
Switching a big bank of LEDs is really no different from switching any sizeable load. You can use Recipe 13.3 to do this.
For programs to turn the LEDs on and off, you can use Recipe 10.8 and Recipe 10.9.
You can also use a PWM signal to control the brightness of a big bank of LEDs using the programs found in Recipe 10.13 and Recipe 10.14.
See Chapter 11 for a whole load of recipes concerned with switching loads like this.
Use multiplexing—a technique that reduces the number of GPIO pins needed to light lots of LEDs. Figure 14-8 shows how you can control a 4-digit LED display from an Arduino Uno.
Each digit of the display has seven segments in a figure-8 arrangement. Each of these segments is labeled A to G and is connected, inside the LED package, to all the segments of the same name. In this display, all the cathodes of the segments for a particular digit are connected together as a common cathode. The LED display has a pin for each of these four common cathodes so that the software can enable each digit in turn, set its segment pattern, and then move on to the next digit.
The sketch ch_14_7_seg_mux displays the numbers 1 to 4 on the display (see Figure 14-9).
The sketch can be found with the downloads for the book (see Recipe 10.2):
constintdigitPins[]={2,3,4,5};constintsegPins[]={6,7,8,9,10,11,12,13};// abcdefgDconstcharnum[]={0b11111100,// 0 abcdef0b00001100,// 1 ef0b11011010,// 2 ab de g0b10011110,// 3 a defg0b00101110,// 4 c efg0b10110110,// 5 a cd fg0b11110110,// 6 abcd fg0b00011100,// 7 def0b11111110,// 8 abcdefg0b10111110};// 9 a cdefgintdigits[]={1,2,3,4};voidsetup(){for(inti=0;i<4;i++){pinMode(digitPins[i],OUTPUT);}for(inti=0;i<8;i++){pinMode(segPins[i],OUTPUT);}}voidloop(){refreshDisplay();}voidrefreshDisplay(){for(intd=0;d<4;d++){for(intseg=0;seg<8;seg++){digitalWrite(segPins[seg],LOW);}digitalWrite(digitPins[d],HIGH);for(intseg=0;seg<8;seg++){digitalWrite(segPins[seg],bitRead(num[digits[d]],7-seg));}delay(1);digitalWrite(digitPins[d],LOW);}}
The digit and segment pins are contained in arrays. The setup function sets them all as outputs.
Two other arrays are defined: num contains the bit patterns for the numbers 0 to 9. A 1 in the bit position means the segment should be lit for that value. The array digits holds the numeric value to be displayed on each of the four positions.
Every time the refreshDisplay function is called, all four digits of the display will be displayed and then the display blanked. This means that refreshDisplay must be called as frequently as possible or the display may become flickery or dim. The function has an outer loop that loops for each digit number d between 0 and 3. Inside this loop, the segments are first turned off and then the control pin for the current digit is enabled.
An inner loop then loops for each segment (seg) and determines whether the current segment should be lit or not, based on the expression:
bitRead(num[digits[d]],7-seg)
This first finds the current digit value and then looks up the bit pattern for that value.
The critical thing about the preceding example code is that anything that you do inside the loop function along with refreshDisplay must happen quickly, or the display will start to flicker. The human eye will not see the flickering until refreshDisplay is called less frequently than 30 times a second, giving you a theoretical 30 milliseconds (approximately) to do something else in loop. This is more than enough time to check the state of digital inputs and perform other simple actions, but remember—always keep loop as fast as possible.
Figure 14-9 shows that there is quite a lot of wiring involved in multiplexing the display. The same hardware can be attached to the GPIO pins of a Raspberry Pi (at least a 40-pin GPIO Raspberry Pi) but the nature of the operating system means that you might find the refresh a little uneven. For a Raspberry Pi, it is probably better to use a display module that has its own hardware such as the I2C LED display in Recipe 14.9.
To use an I2C 7-segment LED module, see Recipe 14.9.
Use a technique called Charlieplexing.
The name Charlieplexing comes from the inventor Charlie Allen of the company Maxim, and the technique takes advantage of the feature of GPIO pins that allows them to be changed from outputs to inputs while a program is running. When a pin is changed to be an input, not enough current will flow through it to light an LED or influence other pins connected to the LED that are set as outputs.
Figure 14-10 shows the schematic for controlling six LEDs with three pins.
Looking at Figure 14-10, if you want to turn on LED1, you need to make pin A high and B low. But to make sure that none of the other LEDs light, you need to set C to be an input, so that no current can flow into or out of it. More accurately, to make sure that not enough current to light an LED flows into or out of it.
For a small number of LEDs, you can test out Charlieplexing on a breadboard as shown in Figure 14-11.
Connect the three control points on the breadboard to pins D5, D6, and D7 of your Arduino (D6 to the middle control pin). You can then use the following sketch (ch_14_charlieplexing) to try out Charlieplexing. You will find the sketch with the downloads for the book (see Recipe 10.2):
constintpins[]={5,6,7};constintpinLEDstates[6][3]={{1,0,-1},// LED 1{0,1,-1},// LED 2{-1,1,0},// LED 3{-1,0,1},// LED 4{1,-1,0},// LED 5{0,-1,1}// LED 6};intledState[6];voidsetup(){Serial.begin(9600);Serial.println("LED Number (0 to 5)");}voidloop(){if(Serial.available()){intled=Serial.parseInt();ledState[led]=!ledState[led];}refresh();}voidrefresh(){for(intled=0;led<6;led++){clearPins();if(ledState[led]){setPins(led);}else{clearPins();}delay(1);}}voidsetPins(intled){for(intpin=0;pin<3;pin++){if(pinLEDstates[led][pin]==-1){pinMode(pins[pin],INPUT);}else{pinMode(pins[pin],OUTPUT);digitalWrite(pins[pin],pinLEDstates[led][pin]);}}}voidclearPins(){for(intpin=0;pin<3;pin++){pinMode(pins[pin],INPUT);}}
The key to this code is the pinLEDstates data structure. This specifies the states that the controlling pins should be set to for a particular LED. So, LED3 has the pattern –1, 1, 0. This means that for LED3 to be lit, the first control pin should be set to an input (–1), the second control pin to a HIGH digital output, and the third to a LOW digital output. If you check Figure 14-10 this will confirm those settings.
The loop function first prompts for a particular LED and then toggles that LED turning it on if it was off and off if it was on. The array ledStates is used to keep track of which LEDs should be on or off.
The loop function then calls refresh, which first clears all the pins setting them to inputs using clearPins and then for each of the LEDs uses setPins to either set the pins appropriately to turn the LED on or not depending on that LED’s entry in ledState.
This works fine for a fairly small number of LEDs, assuming that the Arduino is not doing much else, so that refresh can be called frequently. You may have noticed that the LEDs flicker when serial communication is in progress through the Serial Monitor.
Using a Raspberry Pi instead of an Arduino just requires you to swap the male-to-male header leads to be male-to-female connectors and choose three GPIO pins. In the case of the following example program (ch_14_charlieplexing.py) these should be 18, 23, and 24. You should also increase the value of the resistors to 270Ω.
You can find the program with the downloads for the book (see Recipe 10.4):
importRPi.GPIOasGPIOimportthread,timeGPIO.setmode(GPIO.BCM)pins=[18,23,24]pin_led_states=[[1,0,-1],# LED1[0,1,-1],# LED2[-1,1,0],# LED3[-1,0,1],# LED4[1,-1,0],# LED5[0,-1,1]# LED6]led_states=[0,0,0,0,0,0]defset_pins(led):forpininrange(0,3):ifpin_led_states[led][pin]==-1:GPIO.setup(pins[pin],GPIO.IN)else:GPIO.setup(pins[pin],GPIO.OUT)GPIO.output(pins[pin],pin_led_states[led][pin])defclear_pins():forpininrange(0,3):GPIO.setup(pins[pin],GPIO.IN)defrefresh():whileTrue:forledinrange(0,6):clear_pins()ifled_states[led]:set_pins(led)else:clear_pins()time.sleep(0.001)thread.start_new_thread(refresh,())whileTrue:x=int(raw_input("Pin (0 to 5) :"))led_states[x]=notled_states[x]
The Raspberry Pi version follows the same pattern as the Arduino version except that the call to refresh is in a separate thread of execution, so the display will automatically update, even if the Python program is waiting for input.
The number of LEDs that can be controlled for the number of GPIO pins (n) used is given by the formula:
Using four pins, you can have 16–4 = 12 LEDs, whereas 10 pins would give you a massive 90 LEDs.
For a great description of Charlieplexing as well as layouts for large numbers of LEDs, see https://en.wikipedia.org/wiki/Charlieplexing.
Wire up a common-cathode RGB LED as shown in Figure 14-12.
The red, green, and blue LEDs, in this example, all have different values of series resistor to try and provide equal brightness. The three LED channels can either be simply turned on and off to mix seven different colors from the three control pins, or you can use PWM on the pins to mix more subtle colors.
Connect an RGB LED to an Arduino as shown in Figure 14-12 using the three Arduino pins 9, 10, and 11 for the blue, green, and red channels, respectively.
The following sketch can be found with the downloads for the book (Recipe 10.2) and is called ch_14_rgb_led:
constintredPin=11;constintgreenPin=10;constintbluePin=9;voidsetup(){pinMode(redPin,OUTPUT);pinMode(greenPin,OUTPUT);pinMode(bluePin,OUTPUT);Serial.begin(9600);Serial.println("Enter R G B (E.g. 255 100 200)");}voidloop(){if(Serial.available()){intred=Serial.parseInt();intgreen=Serial.parseInt();intblue=Serial.parseInt();analogWrite(redPin,red);analogWrite(greenPin,green);analogWrite(bluePin,blue);}}
By sending three numbers separated by spaces from the Arduino Serial Monitor, you can mix pretty much any color from the LED.
When using a Raspberry Pi, you can follow the same approach of creating three PWM channels using the RPi.GPIO library (see Recipe 10.14) or, as in the following example, you can install the Python Squid library, which simplifies the process.
To install the Squid library, run the following commands:
$ git clone https://github.com/simonmonk/squid.git $ cd squid $ sudo python setup.py install
The equivalent program for controlling the RGB LED from a Raspberry Pi can be a little fancier and use the Tkinter Python library to make a user interface that allows you to use sliders to adjust the red, green, and blue channels (Figure 14-14):
fromsquidimport*fromTkinterimport*rgb=Squid(18,23,24)classApp:def__init__(self,master):frame=Frame(master)frame.pack()Label(frame,text='Red').grid(row=0,column=0)Label(frame,text='Green').grid(row=1,column=0)Label(frame,text='Blue').grid(row=2,column=0)scaleRed=Scale(frame,from_=0,to=100,orient=HORIZONTAL,command=self.updateRed)scaleRed.grid(row=0,column=1)scaleGreen=Scale(frame,from_=0,to=100,orient=HORIZONTAL,command=self.updateGreen)scaleGreen.grid(row=1,column=1)scaleBlue=Scale(frame,from_=0,to=100,orient=HORIZONTAL,command=self.updateBlue)scaleBlue.grid(row=2,column=1)defupdateRed(self,duty):rgb.set_red(float(duty))defupdateGreen(self,duty):rgb.set_green(float(duty))defupdateBlue(self,duty):rgb.set_blue(float(duty))root=Tk()root.wm_title('RGB LED Control')app=App(root)root.geometry("200x150+0+0")root.mainloop()
The LED in Figure 14-12 is a common cathode device; that is, all the negative terminals (cathodes) of the LEDs are connected together. RGB LEDs are also available in common anode form, which can sometimes be more convenient if they are being controlled by transistors as it allows low-side switching.
For recipes on PWM for Arduino and Raspberry Pi, see Recipe 10.13 and Recipe 10.14, respectively.
The easiest way to control large numbers of RGB LEDs is to use addressable LED strips as described in Recipe 14.8.
Do the power calculations carefully for your pixels and then use a single GPIO pin to send the data to the pixel array. Figure 14-15 shows a typical arrangement for a large number of pixels. If you only have a few pixels (say 5–10), you can power them directly from your Arduino or Raspberry Pi.
If you don’t mind taking the risk of damaging your Pi, Arduino, or whatever is supplying USB power to them, you can power more pixels as long as you are extremely careful in your code to keep the brightness of the pixels well below the maximum brightness. However, this is not recommended.
To test out an addressable LED strip with an Arduino, connect pin D9 to the data terminal of an addressable LED strip.
The Arduino sketch ch_14_neopixel is included in the downloads for the book (see Recipe 10.2). The sketch uses the Adafruit NeoPixel library. This can be installed from within the Arduino IDE using the Library Manager by selecting the menu option Sketch→Include Library→Manage Libraries.
Once the Library Manager is open scroll down and select Adafruit NeoPixel and then click Install.
#include <Adafruit_NeoPixel.h>constintpixelPin=9;constintnumPixels=10;Adafruit_NeoPixelpixels=Adafruit_NeoPixel(numPixels,pixelPin,NEO_GRB+NEO_KHZ800);voidsetup(){pixels.begin();}voidloop(){for(inti=0;i<numPixels;i++){intred=random(64);intgreen=random(64);intblue=random(64);pixels.setPixelColor(i,pixels.Color(red,green,blue));pixels.show();}delay(100);}
Change the values of pixelPin and numPixels to match the GPIO pin you are using and the number of pixels in your strip.
Each pixel will be allocated red, green, and blue intensities at random. Note that the maximum of 64 is used rather than the full range of 0 to 255 because an intensity of 255 is actually very bright.
To test out an addressable LED strip with Raspberry Pi, connect GPIO10 to the data terminal of an addressable LED strip.
To use the display, you first need to install some libraries by running the following commands:
$ git clone https://github.com/doceme/py-spidev.git $ cd py-spidev/ $ make $ sudo make install $ cd .. $ git clone https://github.com/joosteto/ws2812-spi.git $ cd ws2812-spi $ sudo python setup.py install
You still also need to enable SPI on your Raspberry Pi (see Recipe 10.16).
You can find a program to test out the LED display in the file ch_14_neopixels.py. See Recipe 10.4 for information on downloading the Python example programs.
importspidevimportws2812fromrandomimportrandintimporttimespi=spidev.SpiDev()spi.open(0,0)N=10# g r bpixels=[]forxinrange(0,10):pixels.append([0,0,0])whileTrue:foriinrange(0,N):pixels[i]=[randint(0,64),randint(0,64),randint(0,64)]ws2812.write2812(spi,pixels)time.sleep(0.1)
Each pixel is represented in an array of three values. These are in order green, red, and blue rather than the more usual red, green, blue. That’s just how the library is. An array (pixels) of N elements where N is the number of pixels is created by using a for loop to append N arrays of green, red, and blue to the pixels array.
The main loop acts just like its Arduino counterpart. It allocates color intensities at random to each pixel position before using the ws2812 library to write out the pixels to the GPIO pin.
If you are using a Raspberry Pi, then you may need to level shift the data output (Recipe 10.17), although I have never found this to be necessary in practice. Looking at the datasheet for the WS2812, the minimum input voltage to count as a logical HIGH is 0.7 times the supply voltage (5V). This gives a theoretical value of 3.5V.
You can make a convenient display to attach to an Arduino or Raspberry Pi by sacrificing jumper leads by snipping off one connector and soldering the wire to the LED strip. Figure 14-16 shows such a display connected to a Raspberry Pi. Note the use of the heat-shrink sleave to help stop the solder joints from flexing.
For more information on the ws2812-spi library, see https://github.com/joosteto/ws2812-spi, including instructions on using the NumPy library to improve performance for long LED strings.
You can find the datasheet for the WS2812 here: https://cdn-shop.adafruit.com/datasheets/WS2812.pdf.
To control a single RGB LED directly, see Recipe 14.7.
Addressable LED pixels are not confined to strips of LEDs; you can also buy them organized into rings (Adafruit product 1586) and arrays (Adafruit product 1487).
An alternative library that is based on the Raspberry Pi’s DMA hardware rather than its SPI can be found here: https://github.com/richardghirst.
You want to use a 7-segment display but without the spaghetti wiring of Recipe 14.5.
Use a ready-made I2C display module like the one shown in Figure 14-17.
This module and similar modules that can be found on eBay, with four or even eight digits, are a convenient way to add a 7-segment LED display to an Arduino or Raspberry Pi.
Figure 14-18 shows how to wire one up using two GPIO pins.
The I2C serial interface needs two data pins as well as 5V of power. On both the Arduino and Raspberry Pi, specific pins must be used for the I2C interface. On the Arduino Uno, these are the SCL (serial clock) and SDA (serial data) pins (see Recipe 10.7) and on a Raspberry Pi, these are GPIO2 and GPIO3.
This display and many types of displays like it use the HT16K33 IC, which can actually control up to 16 segments in 8 digits. Although the module needs to be powered with 5V, its I2C interface works fine from 3.3V Raspberry Pi GPIO pins, so no level conversion is necessary.
The sketch uses the Adafruit LED Backpack library and Adafruit GFX library. These can be installed from within the Arduino IDE using the Library Manager by selecting the menu option Sketch→Include Library→Manage Libraries.
Once the Library Manager has opened scroll down and select the two libraries and and then click Install.
Adafruit provides a whole load of examples for using the library that you can access directly from the Arduino IDE. A good example to try out can be found under the menu item File→Examples→Adafruit Backpack Library→sevenseg.
The connections between the Raspberry Pi and the module are as follows:
VCC is the abbreviation for volts collector collector, and is frequently used to identify the positive power supply pin of an IC or module.
Before you can use the display, you will need to enable the Raspberry Pi’s I2C interface by following Recipe 10.15.
Adafruit also provides Python code for this module. To install it, enter the following commands into the terminal:
$ sudo apt-get update $ sudo apt-get install build-essential python-dev $ sudo apt-get install python-imaging $ git clone https://github.com/adafruit/Adafruit_Python_LED_Backpack.git $ cd Adafruit_Python_LED_Backpack $ sudo python setup.py install
A good example to try out is the clock example sevensegment_test.py.
Building a project using a module like this is fine when you are developing a prototype, but in a finished product, you would most likely use direct multiplexing as described in Recipe 14.5 (to reduce costs) or use the HT16K33 IC on a circuit board of your own design, if you really need a hardware driver.
You can find lots more information on this display at its project page on Adafruit.
To control a similar display but using multiplexing, see Recipe 14.5.
You can download the HT16K33 datasheet from http://bit.ly/2mbaWyP.
Use an I2C OLED display like the one shown attached to an Arduino in Figure 14-20.
The display has the same four connections as the display used in Recipe 14.9 so you can make the same connections as shown in Figure 14-18.
Wire up the display as described in Recipe 14.9.
You will also need to add the Adafruit GFX and SSD1306 libraries to your Arduino IDE by using the Library Manager (from the menu Sketch→Include Library→Library Manager and then scroll down the list and install both the Adafruit GFX Library and the Adafruit SSD1306 library).
The example sketch ch_14_oled will display the message shown in Figure 14-20. To install the Arduino programs for the book, see Recipe 10.2.
#include <Wire.h>#include <Adafruit_GFX.h>#include <Adafruit_SSD1306.h>Adafruit_SSD1306display(4);voidsetup(){display.begin(SSD1306_SWITCHCAPVCC,0x3c);display.clearDisplay();display.drawRect(0,0,display.width()-1,display.height()-1,WHITE);display.setTextSize(1);display.setTextColor(WHITE);display.setCursor(5,10);display.("Electronics Cookbook");display.display();}voidloop(){}
Wire up the display as described in Recipe 14.9.
Before you can use the display, you will need to enable the Raspberry Pi’s I2C interface by following Recipe 10.15.
You will also need to download and install the SSD1306 Python library and prerequisites using the following commands:
$ sudo pip install pillow $ git clone https://github.com/rm-hull/ssd1306.git $ cd ssd1306 $ sudo python setup.py install
Now change the directory to the book’s example programs and run the program ch_14_oled.py (see Recipe 10.4). The text “Electronics Cookbook” with a rectangular border should appear on the display. If it doesn’t, then there is a good chance you will need to change the I2C address of the device in the file demo_opts.py that is with the other downloads. Change line 13 from 0x3c to the I2C address of your device. The file ch_14_oled.py is listed here:
fromdemo_optsimportdevicefromoled.renderimportcanvasfromPILimportImageFontfromdemo_optsimportargsfont=ImageFont.load_default()withcanvas(device)asdraw:draw.rectangle((0,0,device.width-1,device.height-1),outline=255,fill=0)font=ImageFont.load_default()draw.text((5,20),'Electronics Cookbook',font=font,fill=255)
Once you get into the realm of needing a display that can show text and graphics, you can of course use an HDMI monitor with your Raspberry Pi.
For a simple numeric display see Recipe 14.9 and for a low-cost two-line alphanumeric display see Recipe 14.11.
The SSD1306 library page on GitHub has more examples and documentation for using these displays: https://github.com/rm-hull/ssd1306.
Use an LCD module based on the HD44780 IC. Figure 14-21 shows one of these displays wired to an Arduino and Figure 14-22 shows how the display should be connected on a breadboard. Figure 14-23 shows the connections for a Raspberry Pi as a schematic.
The HD44780 can be configured to use either an 4- or 8-bit parallel data bus. If the 4-bit bus is used only bits 4 to 7 of the bus are used. The pin Vo is used to control the contrast of the screen. You will need to adjust R1 to be able to see anything on the screen.
The Arduino IDE includes a library called LiquidCrystal that takes care of all the communications with the HD44780 IC. The following example can be found with the Arduino downloads for the book (Recipe 12.2) in the sketch ch_14_lcd:
#include <LiquidCrystal.h>// RS EN D4 D5 D6 D7LiquidCrystallcd(7,8,9,10,11,12);voidsetup(){lcd.begin(16,2);lcd.("Electronics");lcd.setCursor(0,1);lcd.("Cookbook");}voidloop(){lcd.setCursor(10,1);lcd.(millis()/1000);}
To use an HD44780 display on a Raspberry Pi, you will first need to install the Adafruit CharLCD Python library by entering the following commands:
$ git clone https://github.com/adafruit/Adafruit_Python_CharLCD.git $ cd Adafruit_Python_CharLCD $ sudo python setup.py install
You can now try out the example program ch_14_lcd.py:
importtimeimportAdafruit_CharLCDasLCD# Raspberry Pi pin configuration:lcd_rs=27# Note this needs to be changed to 21 for Model B rev1 Pis.lcd_en=22lcd_d4=25lcd_d5=24lcd_d6=23lcd_d7=18lcd_backlight=4lcd_columns=16lcd_rows=2lcd=LCD.Adafruit_CharLCD(lcd_rs,lcd_en,lcd_d4,lcd_d5,lcd_d6,lcd_d7,lcd_columns,lcd_rows,lcd_backlight)lcd.message('Electyronics\nCookbook')t0=time.time()whileTrue:lcd.set_cursor(10,1)lcd.message(str(int(time.time()-t0)))time.sleep(0.1)
Adafruit has a wide selection of these types of displays, including ones that have an RGB color backlight (https://www.adafruit.com/products/399).
In many projects the only digital IC you will need is a microcontroller. With sufficient GPIO pins you can do most digital tasks. In this chapter, you will find recipes for digital ICs that still manage to find a role in modern electronics design.
Sometimes, a single digital logic IC is all you need. A single digital logic IC is often cheaper and removes the need for programming that would otherwise arise if you used a microcontroller.
Use a 100nF capacitor as close as possible to the power pins of the digital IC. The shorter the leads to the capacitor the better.
This process of connecting a capacitor with short circuit board tracks to the power pins of an IC is called “decoupling” because each IC has its own little reservoir of charge and will therefore not be “coupled” to a neighboring capacitor by affecting its power supply. Capacitors used in this way are also called “bypass” capacitors.
Figure 15-1 shows a circuit board containing a digital IC with a 100nF multilayer ceramic (MLC) capacitor for both a through-hole and SMD.
The circuit board on the right of Figure 15-1 actually has two capacitors in parallel as the decoupling capacitor. The smaller one is 100nF and the larger one 10µF. You may think that the effect of the 100nF would be lost, but its lower ESR (see Recipe 3.2) allows it to respond faster to pulses of power consumption from the chip. So, the 10µF capacitor is in turn providing a larger local energy store for the smaller capacitor and IC to draw on, but one that has a higher ESR and therefore cannot respond as quickly. Such an arrangement of ever-decreasing capacitor values as you approach the power rails of the IC is particularly common where larger currents are being switched such as in motor controllers and audio power amplifiers.
Digital ICs contain lots of transistors that switch very quickly. The decoupling capacitor provides a little reservoir of charge so that this switching does not result in excessive electrical noise on the power lines that could go on to affect other parts of the circuit.
It is considered to be good practice to include a decoupling capacitor next to every digital IC. In fact, this is also true of analog ICs.
For more information on capacitors, see Chapter 3.
Logic-gate ICs, like the mafia, are arranged into families. TTL (transistor transistor logic) used to be a popular choice, but is now totally obsolete unless you are repairing an equally obsolete computer from the last century. TTL chips starting with the number 74 (e.g., 7400) used to compete with CMOS chips with names that started with 40 (e.g., 4011). Each had their own overlapping ranges of logic gates, flip-flops, shift registers, and counters.
TTL was faster than CMOS, but CMOS used less current and was far less fussy about its supply-voltage range. Now these two families have merged into a single “best-of-both-worlds” family called high-speed CMOS. If you started playing with electronics in the 1970s, you can still find your favorite logic ICs from both families but under one name starting with 74HC. For instance, the 7400 of old is now the 74HC00 and the 4011 of old is now called the 74HC4001.
A high-speed CMOS chip has a supply-voltage range of 2V to 6V and only consumes about 1µA until it starts switching. Their outputs can also generally source or sink 4mA at their outputs (per gate).
The original 40xx CMOS is still available and can be useful where you need a greater power-supply range than high-speed CMOS can provide.
For the datasheet of a typical high-speed CMOS device, see http://www.ti.com/lit/ds/symlink/sn74hc00.pdf.
Use a serial-to-parallel shift register such as the 74HC4094 and write some code to load its registers with data using a serial interface that only requires three pins. LEDs can then be attached to the outputs. Figure 15-2 shows a schematic for this.
The total current allowed by the 74HC4094 is 50mA so assuming 6mA per LED, a suitable series resistor would be 680Ω if all the LEDs are lit at the same time, to allow 8 x 6mA = 48mA.
You can find the Arduino code to send data to the shift register with the downloads for the book (Recipe 10.2) in the sketch ch_15_sift_reg:
constintstrobePin=5;constintdataPin=6;constintclockPin=7;voidsetup(){pinMode(strobePin,OUTPUT);pinMode(dataPin,OUTPUT);pinMode(clockPin,OUTPUT);Serial.begin(9600);Serial.println("Enter Byte");}voidloop(){if(Serial.available()){charbits=Serial.parseInt();shiftOut(dataPin,clockPin,MSBFIRST,bits);digitalWrite(strobePin,HIGH);delayMicroseconds(10);digitalWrite(strobePin,LOW);Serial.println(bits,2);}}
This sketch uses the Arduino shiftOut function to send the serial data and uses these parameters: the pin to send the data on, the clock pin, a flag to determine the order the data is sent (in this case, most significant bit [MSB] first), and the actual data to send.
If you open the Arduino Serial Monitor, you will be prompted for a value to load into the shift register. This value will be shifted in and then a confirmation of the data in binary will be displayed as shown in Figure 15-3. The value entered should be a decimal value between 0 and 255. This value will be echoed in binary in the Serial Monitor for confirmation.
The following test program assumes you have connected the STROBE pin of the 74HC4094 to GPIO18, the DATA pin to GPIO23, and the CLOCK pin to GPIO24.
The Python code (ch_15_shift_reg.py) follows a similar pattern as that of the Arduino, but in this case we have to implement the shift_out function. This sets the data_pin to the eighth bit of the data, and then pulses the clock_pin before shifting the data left by one bit position, and so on for all eight bits in MSB first order:
importRPi.GPIOasGPIOimporttimeGPIO.setmode(GPIO.BCM)strobe_pin=18data_pin=23clock_pin=24GPIO.setup(strobe_pin,GPIO.OUT)GPIO.setup(data_pin,GPIO.OUT)GPIO.setup(clock_pin,GPIO.OUT)defshift_out(bits):# MSB first. 8 bitsforiinrange(0,8):b=bits&0b10000000bits=bits<<1GPIO.output(data_pin,(b==0b10000000))time.sleep(0.000001)GPIO.output(clock_pin,True)time.sleep(0.000001)GPIO.output(clock_pin,False)time.sleep(0.000001)try:whileTrue:bits=input("Enter Byte ")(bin(bits))shift_out(bits)GPIO.output(strobe_pin,True)time.sleep(0.000001)GPIO.output(strobe_pin,False)finally:("Cleaning up")GPIO.cleanup()
Figure 15-4 shows the logical diagram for the 74HC4094.
The 74HC4094 is a serial-to-parallel shift register. The 8-stage shift register’s data is set a bit at a time by setting the data (D) pin either HIGH or LOW and then pulsing the clock (CP) pin to transfer that bit. The data pin is then set to the next value and the clock pulsed again to shift the bit already in the shift register along one position and then add the new bit at the beginning. This process continues until all eight bits are loaded into the shift register.
The contents of the shift register are not actually transferred to the 74HC4094’s outputs until the strobe pin (STR) is pulsed.
The 74HC4094 also has an output enable (OE) pin that switches all eight outputs either to a high impedance state or to the bit pattern of HIGHs and LOWS in the 3-state-outputs register. If you connect this OE pin to a PWM output you can use it to control the brightness of all the LEDs at the same time.
You can cascade a number of shift registers together by tying their clocks together and attaching the QS2 data output from one shift register to the data input of the next.
Another way of controlling lots of LEDs from a small number of GPIO pins is to use Charlieplexing (Recipe 14.6).
You can find the datasheet for the 74HC4094 here: http://bit.ly/2mqB0ET.
For more information on the Arduino shiftOut function, see http://bit.ly/2msRHAg.
Use an 74HC00 IC to make a reset-set flip-flop as shown in Figure 15-5.
When SW1 is pressed the LED will light and stay lit until SW2 is pressed.
R1 and R2 are pull-up resistors that keep the inputs to flip-flop high until the buttons are pressed. One advantage of this way of switching is that if the switches bounce (Recipe 12.1) it will have no effect on the operation of the circuit.
Note that in Figure 15-5 the inputs of the two unused gates in the 74HC00 are tied to ground. This is considered good practice as it prevents the otherwise floating inputs from causing the gates to oscillate in time with electrical noise.
In addition to switching an LED on or off, you could adapt this circuit to switch large loads with a transistor by combining it with Recipe 11.1 or Recipe 11.3.
You can find the datasheet for the 74HC00 here: http://bit.ly/2lLK0R5.
Use a frequency-divider IC such as the 8-stage 74HC590 in the arrangement shown in Figure 15-6.
The output at QA will be half the input frequency f, QB a quarter, and so on until QH has an output frequency of 1/256 of the input frequency.
For most designs it is preferable to use a microcontroller when it comes to things like counting. However, counting clock cycles with a microcontroller is significantly slower than the clock frequency of the microcontroller itself. So, a maximum frequency might be a few hundred kHz. To count higher frequencies, QH or one of the other outputs of the 74HC590 could be connected to a digital input on a microcontroller to allow frequencies up to the 24MHz maximum the 74HC590 allows.
You can find the datasheet for the 74HC590 here: http://www.nxp.com/documents/data_sheet/74HC590.pdf.
Connect the clock and reset the pins of a 74HC4017 decimal counter IC to an Arduino or Raspberry Pi and attach LEDs to the outputs of the 74HC4017 with suitable current-limiting resistors as shown in Figure 15-7.
The 74HC4017 is a decade counter with decoded outputs. That is, each time it receives a pulse on its clock (CLK) pin it advances to the next output. So, first Q0 is high, then Q1, and so on. The reset pin (RES) sets the counter back to the first output Q0.
Since only one of the LEDs is ever on at a time, the full 20mA output of the 74HC4017 can be used to drive the LEDs.
The Arduino sketch ch_15_decade_counter is given here. You can find it with the downloads for the book (Recipe 10.2):
constintresetPin=6;constintclockPin=7;voidsetup(){pinMode(resetPin,OUTPUT);pinMode(clockPin,OUTPUT);Serial.begin(9600);Serial.println("Enter digit 0..9");}voidloop(){if(Serial.available()){intdigit=Serial.parseInt();setDigit(digit);}}voidsetDigit(intdigit){digitalWrite(resetPin,HIGH);delayMicroseconds(1);digitalWrite(resetPin,LOW);for(inti=0;i<digit;i++){digitalWrite(clockPin,HIGH);delayMicroseconds(1);digitalWrite(clockPin,LOW);delayMicroseconds(1);}}
The code starts by pulsing the reset pin so that the output Q0 will be high. It then issues the number of pulses to the clock pin requested by the number sent from the Serial Monitor.
The reason the LEDs don’t flicker and you don’t see the LEDs before the selected LED flash is that this pulsing happens very quickly (in fact, in a few millionths of a second).
The equivalent Python sketch for the Raspberry Pi assumes you have GPIO18 connected to the reset pin of the 74HC4017 and GPIO23 connected to the clock pin.
The program is called ch_15_decade_counter.py. See Recipe 10.4 for information on installing the example programs:
importRPi.GPIOasGPIOimporttimeGPIO.setmode(GPIO.BCM)reset_pin=18clock_pin=23GPIO.setup(reset_pin,GPIO.OUT)GPIO.setup(clock_pin,GPIO.OUT)defset_digit(digit):GPIO.output(reset_pin,True)time.sleep(0.000001)GPIO.output(reset_pin,False)time.sleep(0.000001)foriinrange(0,digit):GPIO.output(clock_pin,True)time.sleep(0.000001)GPIO.output(clock_pin,False)time.sleep(0.000001)try:whileTrue:digit=input("Enter digit 0..9 ")set_digit(digit)finally:("Cleaning up")GPIO.cleanup()
The program works in just the same way as its Arduino counterpart.
Using a counter like the 74HC4017 can be useful when multiplexing an LED display (Recipe 14.5), as you can use it to select each digit of a 7-segment display or column of an LED matrix, without tying up too many GPIOs.
You can find the datasheet for the 74HC4017 here: http://www.nxp.com/documents/data_sheet/74HC_HCT4017.pdf.
In these circumstances, a simple RC filter (Figure 16-1) will suffice to remove most of the unwanted high-frequency PWM carrier.
Intuitively, all the resistor and capacitor do is make the output slow to respond to changes to the input. All that remains is to decide on suitable values for R and C. We can illustrate this with an example.
The Arduino Mozzi library (Recipe 18.1) generates PWM (Recipe 10.13) audio output. The length of the pulses on the constant PWM frequency of 32.7kHz determine the amplitude of the lower frequency underlying the audio signal (440 Hz). Figure 16-2 illustrates this.
The average output voltage is shown by the dashed line, which increases as the pulses lengthen.
Using a value of 270Ω for R and \330nF for C produces the filtering shown in Figure 16-3. The top trace shows the filtered output and the bottom trace the PWM signal.
You can see that the original sine wave from (top) has been extracted from the PWM signal (bottom).
The kind of RC filter used here is called a first-order filter and only really works well if the signal being filtered is much greater than the frequency you want to keep. Figure 16-4 shows the characteristic plot of gain against frequency.
A gain of 1 means the signal is unchanged in magnitude. In the “stop band” where the signal is being attenuated, the signal’s amplitude halves every time the frequency doubles.
The start of the stop band is taken to be after the “corner frequency” (f0), which is defined as the frequency at which the signal amplitude has been reduced to 75% for its original value.
The corner frequency is given by the formula:
Using a resistor of 270Ω and 330nF capacitor the corner frequency is:
With a corner frequency of 1.768kHz and a frequency of 32.7kHz for the PWM signal (that we are trying to filter out) a quick check will show you that you are looking at a little over four doublings of 1.786kHz, which gives a reduction of four halvings of the amplitude of that high-frequency component. This will reduce the amplitude of the 32.7kHz signal to about 1/16 of its unattenuated value, which is why the PWM frequency is still visible on top of the 440Hz sinewave shown in Figure 16-3.
If you want to try out this experiment, then install the Mozzi library into your Arduino IDE by downloading the ZIP for the library from GitHub and then installing the ZIP for the library from the Arduino IDE’s menu (Sketch→Include Library→Add .ZIP Library).
From the Arduino IDE’s example menu, upload Files→Examples→Mozzi→Basics→Sinewave onto your Arduino and wire it up as shown in Figure 16-1.
Attaching an oscilloscope to the unfiltered and filtered outputs of D9 should give you a trace similar to Figure 16-3.
For a better-quality filter with a much steeper fall-off of gain with frequency, see Recipe 17.7.
In this recipe, we have talked about attenuation of a signal’s amplitude in terms of halving or quartering. The more common unit for attenuation and amplification of a signal is the dB (decibel). This is described in Recipe 17.1.
A great way to help design filters is to use simulation. This example is used in Recipe 21.11.
For instructions on using an oscilloscope, see Recipe 21.9.
Use the transistors in the arrangement shown in Figure 16-5. This arrangement is also sometimes called an “astable,” meaning it has no stable state, and instead oscillates between two states.
When power is first applied to the circuit both Q1 and Q2 will be off. Very slight differences between the capacitor values and the values of R2 and R3 mean that one of the capacitors will start to charge through R2 or R3 faster than the other. The faster-charging capacitor will win the race to turn on the transistor whose base it is connected to. Current flows through this transistor turning on the LED and drops the collector voltage allowing the slower capacitor to start charging until the opposite transistor turns on and so on.
The frequency of this oscillator is determined by the time constant of C1 and R2 (C1 and C2 should have the same value, as should R2 and R3), but also depends on the characteristics of the transistor. For the circuit shown in Figure 16-5 and a supply voltage of 9V, the frequency was measured as 2.8Hz, implying that the frequency is related to R2 and C1 by the formula:
For an oscillator that uses the NE555 timer IC, see Recipe 16.5.
You can see a video of this circuit in action here: https://youtu.be/-NvMFmPHc4s.
Build a ring oscillator using MOSFETs as shown in the schematic in Figure 16-6.
The way to understand how this circuit works is to think of each transistor stage as an inverter. That is, if the gate of the transistor is low, then the drain of the transistor will be pulled high by the LED and resistor. As the transistor’s associated gate capacitor charges, the gate voltage will gradually rise until the transistor is on and then the drain will go low. The final inverter stage then feeds back to the first transistor and the cycle continues. This does not work with an even number of stages as the outputs of the first and last stages would both be high and low (in phase) with each other and no oscillation would occur.
This oscillator produces quite a mesmeric effect as the LED brightness gradually increases and decreases.
In practical terms, when considering a large number of LEDs, you would probably use a microcontroller with LEDs attached to digital outputs, or a decade counter like the 4017 described in Recipe 15.6.
For an interesting Wikipedia article on the ring oscillator, see https://en.wikipedia.org/wiki/Ring_oscillator.
There is a video of this circuit here: https://youtu.be/9O5Ojhr0oGg.
Use a BJT arranged as an emitter-follower, as shown in Figure 15-7. In this case, the input is provided by a pot. The output voltage will follow the input voltage (less the base-emitter voltage).
On the face of it, this may seem pointless and you might be asking yourself why you wouldn’t just take the output from the slider of R1. The reason is that even a very slight load resistance on R1 will alter its output voltage, whereas by using a transistor, a much larger load current can be drawn.
Whatever the voltage set at the base of the transistor (above about 0.6V), the emitter will always be about 0.6V lower, but able to provide significantly more current. In fact, the ratio of base-to-collector current is the DC gain of the transistor. For a transistor like the 2N3904, this is generally taken to be about 100. So for a collector current of say 10mA, less than 100µA should be flowing into the base from R1.
An emitter-follower like this can be used as the basis of a voltage regulator using the schematic in Figure 16-8, although generally a voltage-regulator IC is an easier option.
As described in Recipe 4.3 the Zener diode will keep the base of Q1 at 5.6V as long as the input voltage is greater than 5.6V. The Zener diode acts as a voltage reference to Q1, whose emitter will remain at 5V as long as the load current does not become great enough to start drawing significant base current and hence cause the voltage at the base to drop. Using a power Darlington like the TIP120 with its DC current gain of around 10,000 will provide even better regulation, at higher currents, but at the expense of a bigger base-emitter voltage drop (see Recipe 5.2).
For a more or less perfect unity gain buffer without the base-emitter voltage drop, see Recipe 17.6.
For more information on BJTs, see Recipe 5.1.
Use an NE555 timer IC in the configuration shown in Figure 16-9.
This is not the standard astable oscillator schematic for an NE555. But unless you need to control the duty cycle for PWM or other purposes, it’s fine for a simple oscillator.
The frequency is set by the values of R2 and C1:
So, for an R2 of 10kΩ and a C1 of 10nF, the frequency is:
To simplify the calculations, standardize a few values of C1. For low-frequency LED blinking, use a 1μF capacitor; for audio frequencies of a few hundred Hz, use 100nF; and for higher frequencies into the kHz, use a 10nF capacitor. Fixing the capacitor in this way means you can use the following formula to calculate the value of R2 that you need:
Table 16-1 shows some common frequencies and suitable component values.
| Frequency | C1 | R2 |
|---|---|---|
| 1Hz | 1µF | 693kΩ |
| 2Hz | 1µF | 347kΩ |
| 50Hz | 1µF | 13.9kΩ |
| 100Hz | 1µF | 6.93kΩ |
| 1kHz | 10nF | 69.3kΩ |
| 10kHz | 10nF | 6.93kΩ |
| 100kHz | 10nF | 693Ω |
Remember that capacitors in particular are generally only accurate at values of ±10% and the frequency is also somewhat dependent on the supply voltage. Table 16-2 shows the effect of supply voltage on output frequency for this circuit using an R2 of 10kΩ and a C1 of 10nF.
| Supply Voltage (V) | Output Frequency (kHz) |
|---|---|
| 5 | 5.46 |
| 9 | 6.63 |
| 12 | 7.03 |
| 16 | 7.33 |
You can find the datasheet for the NE555 here: http://www.ti.com/lit/ds/symlink/ne555.pdf.
If you need complimentary outputs from your oscillator, use a 4047 timer IC (Recipe 7.10 ).
The NE555 IC is a versatile device and can also be used as a one-shot timer (Recipe 16.7).
You can also make an oscillator with just two transistors as described in Recipe 16.2.
Use an NE555 timer IC, but this time in the configuration shown in Figure 16-10.
The frequency and duty cycle (proportion of the time the output is high to the time it is low) are set by the values of C1, R1, and R2. The period of time the output is high during each cycle is:
The time it is low is given by:
The overall frequency in Hz will be the inverse of these two times added together:
If you want a fairly even duty cycle, you can just use Recipe 16.5, or make sure that R1 is much smaller than R2 (without being 0).
To avoid all the math, there are lots of good online calculators out there you can use. This one is particularly useful as it allows you to enter just the frequency and duty cycle you want.
The NE555 timer is an extremely flexible device. Figure 16-11 shows the internal structure of the IC.
The design is centered around a reset-set (RS) flip-flop (see Recipe 15.4). This flip-flop has an output that will become high if the S input goes high. It will then stay high until the flip-flop is reset, either by R becoming high or R1 becoming low. The output of the flip-flop drives both a push-pull output stage (Recipe 11.8) connected to the OUT pin and an open-collector output connected to pin DISCH, which is used to discharge a timing capacitor.
Setting and resetting the flip-flop is achieved by using an arrangement of three resistors in a voltage divider from the positive supply (VCC) to GND and two comparitors (Recipe 17.10). If the voltage at TRIG falls below ⅓ of the supply voltage, the lower comparitor sets the flip-flop until the voltage at THRES exceeds ⅔ of the supply voltage and the flip-flop is reset.
The CONT (control) pin is not generally used, but it can be used to adjust the comparitor-threshold voltages. You will also often find schematics where a 10nF capacitor is connected between CONT and GND. This is an additional decoupling capacitor that can improve the oscillator stability, but is by no means essential.
In addition to the standard NE555 timer, a number of variations of the device have been developed. The NE556 is simply a 14-pin IC package that has two NE555 timers in it sharing common supply pins.
The LMC555 is a CMOS version of the 555 timer that is pin compatible and will operate down to 1.5V supply.
You can find the datasheet for the NE555 here: http://www.ti.com/lit/ds/symlink/ne555.pdf and the datasheet for the 555 here: http://www.ti.com/lit/ds/symlink/lmc555.pdf.
Figure 16-11 is taken from an informative Wikipedia page on the 555 timer: https://en.wikipedia.org/wiki/555_timer_IC.
Figure 16-12 shows an NE555 timer configured as a one-shot (monostable) timer.
When SW1 is pressed, OUT becomes HIGH and stays HIGH until either SW2 is pressed (to cancel the timer) or a period of time 1.1 x R1 x C1 has elapsed.
For example, a value of C1 of 100µF and R1 of 100kΩ will give a delay of:
1.1 x 100µ x 100k = 11 seconds
In this timer circuit to achieve timings of a second or more, you need to use an electrolytic of 100µF or greater.
You can, of course, make R1 a variable resistor, or more likely a fixed resistor and variable resistor in series in order to set a minimum delay.
For other 555 timer recipes see Recipe 16.5, Recipe 16.6, Recipe 16.8, Recipe 16.9, and Recipe 16.10.
Use an NE555 timer as shown in Figure 16-13.
For a PWM frequency of around 1kHz, use a value for R1 of 270Ω, R2 a 10kΩ pot, and C1 100nF.
The NE555 timer output can drive about 200mA, which is only sufficient for a pretty small motor. Drawing more current than this will cause the IC to overheat and eventually fail. To drive a higher power motor, use a transistor as described in Recipe 13.2.
The minimum duty cycle of this circuit depends on the ratio of R1 to R2. R1 should be considerably lower than R2 to minimize the duty cycle, but R1 cannot be 0Ω or the oscillations will stop. A ratio of 40:1 is sufficient to ensure the minimum duty cycle is just 3–4%.
Figure 16-14 shows the minimum duty cycle with the knob of R2 at one end of its travel, Figure 16-15 shows a 50% duty cycle, and Figure 16-16 the maximum duty cycle.
To use PWM outputs from an Arduino or Raspberry Pi, see Recipe 13.2.
Use an NE555 timer in the configuration shown in Figure 16-17.
The analog signal must be between 0 and VCC and is applied to the CONT (control) pin of the IC. The Clock signal should be at the modulation frequency and can be provided by another NE555 timer in a stable configuration as described in Recipe 16.5. Rather than using a separate chip to provide the clock, you can use an NE556, which contains the equivalent of two NE555s in one package.
The NE555 is configured as a monostable whose pulse length is determined by R1, C1, and the voltage at CONT. This monostable fires every time the TRIG pin pulses in response to the modulation clock.
R1 and C1 set the maximum pulse length, which should be timed to be one wavelength of the clock.
For example, if the clock frequency is 30kHz, the period length is:
1/30k = 33.3µs
The maximum pulse length Tmax (see Recipe 16.7) is:
Tmax = 1.1 R1 C1
So, an R1 of 470Ω and a C1 of 100nF would give a Tmax of:
1.1 × 270 × 100n = 29.7µs
This would allow the full voltage range of 0 to 5V to be modulated as PWM.
The use of two NE555 ICs (or a single NE556) configured as an oscillator providing a clock with the second configured as a monostable is an alternative to Recipe 16.8 for using PWM top-control power to a load. In such a case, the CONT pin could be connected to the slider of a pot connected between 5V and GND to control the pulse width.
Creating a PWM output signal is the first step in class-D digital amplification (see Recipe 18.5).
To control power to say a motor or other load, see Recipe 16.8.
Use an NE555 configured as an astable and use the CONT pin voltage to control the switching thresholds and hence the frequency. This arrangement is shown in Figure 16-18.
VCOs are standard building blocks in analog audio synthesizers, where the output of a low-frequency oscillator can be used to modulate the audio frequency of a VCO.
This VCO design operates over a fairly limited range of frequencies. Using a 5V supply and values of R1 = 1kΩ, R2 = 10kΩ, and C1 = 10nF the plot of Figure 16-19 shows how the frequency varies with the control voltage.
The useful control voltage range is between about 3 and 5V in this example. Oscillation stopped completely below 1.8V.
For the use of a VCO in an FM transmitter, see Recipe 19.1.
The term “decibel” is not strictly speaking a unit of anything, but rather a way of expressing ratios that is suitable for properties such as sound whose perception by humans is logorithmic. That is, for a sound signal to sound a little bit louder, you might need to double the amplitude (voltage).
That is why a 1W amplifier can provide a reasonable volume of sound, but if you need more volume, then rather than take the next step to 2W of output power, you might jump straight to 10W and then on to 100W.
A positive value of dB represents amplification of a signal and a negative dB attenuation (reduction in amplitude) of a signal.
A gain expressed in dB can either apply to voltage (amplitude) or to power, the power being proportional to the amplitude squared. The unit dB is most commonly used with amplitude, in which case the gain is as follows (log is log to the base 10):
Figure 16-20 shows various common ratios and the dB equivalents.
A gain of 0dB means the output is exactly the same amplitude as the input. A gain of +6dB means a doubling of the amplitude and –6dB an attenuation of the signal by half.
Table 16-3 shows some common dB ratios and what they mean in terms of amplification or attenuation of both amplitude (voltage) and power.
| dB | Amplitude (Voltage) | Power |
|---|---|---|
| 100 | gain of 100,000 | gain of 10,000,000,000 |
| 80 | gain of 10,000 | gain of 100,000,000 |
| 60 | gain of 1,000 | gain of 1,000,000 |
| 40 | gain of 100 | gain of 10,000 |
| 20 | gain of 10 | gain of 100 |
| 10 | gain of 3.162 | gain of 10 |
| 6 | gain of approx. 2 | gain of 3.981 |
| 3 | gain of 1.413 | gain of approx. 2 |
| 0 | no change | no change |
| –3 | attenuation of 1.413 | attenuation of approx. 2 |
| –6 | attenuation of approx. 2 | attenuation of 3.981 |
| –10 | attenuation of 3.162 | attenuation of 10 |
| –20 | attenuation of 10 | attenuation of 100 |
| –40 | attenuation of 100 | attenuation of 10,000 |
| –60 | attenuation of 1,000 | attenuation of 1,000,000 |
| –80 | attenuation of 10,000 | attenuation of 100,000,000 |
| –100 | attenuation of 100,000 | attenuation of 10,000,000,000 |
Wikipedia has a useful description of decibels as a unit of gain at http://bit.ly/2lPeant.
Operational amplifiers, or more commonly known as op-amps, have a helpful way of making theory easy to implement. If you need to make a filter or preamplifier, an op-amp is often the best solution.
An op-amp has two inputs and one output and is represented in schematic diagrams (Figure 17-1) as a triangle with the output coming from one apex and the two inputs labeled + and – on the opposite side. They also need positive and negative power connections. They are available in a variety of IC packages with 5, 6, or 8 pins. ICs are also available that contain two or four op-amps in a single package.
Op-amps amplify the difference between the + and – inputs. The gain of an amplifier will generally be millions or even billions. So the output voltage may be 1,000,000 times the difference between the input voltages. Such a high gain may sound desirable, but it is actually too high to do anything useful with. To reduce the gain to a more manageable level, an op-amp is almost always used with negative feedback where some of the output is fed back to the negative input. You will find examples of using feedback in this way in Recipe 17.4 and Recipe 17.5. In Recipe 17.6 you will see how if all of the output is fed back to the negative input the output will follow the positive input to the op-amp rather like the emitter-follower described in Recipe 16.4.
Traditionally op-amps are powered with a split power supply that has positive and negative supply voltages (Recipe 17.2) in addition to GND in the middle. However, the prevelance of microcontrollers with single 3.3V or 5V supplies has led to many op-amps being capable of single-supply operation (Recipe 17.3).
An op-amp IC is much better than a discrete-transistor design in most situations, providing a lower component count and generally excellent performance. Special types of op-amps are available for different power supply, frequency, and noise requirements.
Here I have tried to simplify this enormous choice to a small set of readily available devices to suit all applications.
Factors that you need to consider include:
A good selection of devices to start from are listed in Table 17-1.
| LM741 | LM321 | TLV2770 | OPA365 | |
|---|---|---|---|---|
| Description | Perhaps the longest-lived and most popular op-amp. | A good high-supply voltage device capable of single-supply operation. | A single-supply low-voltage device with a standby, low-current mode. | A high-performance, low-voltage, low-noise device. SMD only. |
| Guide cost | $0.50 | $0.70 | $2 | $2 |
| Supply voltage range | ±10–22V | 3–30V | 2.5–5.5V | 2.2–5.5V |
| Rail to rail | N | N | Y | Y |
| Gain bandwidth product | 1MHz | 1MHz | 5.1MHz | 50MHz |
| Slew rate | 0.5V/µs | 0.4V/µs | 10V/µs | 25V/µs |
| Common mode rejection | 96dB | 85dB | 86dB | 120dB |
| Noise (nV/√Hz) | Not specified | 40 | 17 | 4.5 |
| Supply current | 1.7mA | 0.7mA | 1mA (1µA standby) | 4.6mA |
| Output current | 25mA | 20mA | 50mA | 65mA |
| Dual-amp package | LM747 | LM358 | TLV2773 | OPA2385 |
| Quad-amp package | LM148 | LM324 | TLV2775 | Not available |
There will be times when you need to step out from the selections in Table 17-1 for some particular application. Perhaps you need an op-amp that works at high frequencies, but has a high upper supply voltage. In such cases, there will almost certainly be a device that fits the niche, but to find it, you will need to do some searching on the internet for recommendations and then carefully inspect the datasheets.
Note that not all op-amps have the same pinout. See Appendix A for pinouts for the op-amps described in this recipe.
Take a look at the datasheets for the op-amps featured in this recipe:
You will also find an op-amp used in Recipe 18.3.
Use a regulated supply or batteries, or both. In any case, use a linear voltage regulator rather than a switching regulator. The current consumption of an op-amp is low enough that power-supply efficiency does not need to be considered.
If you are operating the op-amp with a split power supply, you can use positive and negative versions of a linear regulator as shown in the ±12V supply shown in Figure 17-2.
Op-amps benefit greatly from the use of decoupling capacitors (see Recipe 15.1). If you have an undemanding application, a single 100nF capacitor placed close to the op-amp IC will be just fine. For more demanding applications where you have a lot of gain, it is common to use both a 100nF and 10µF capacitor next to each other and close to the IC body.
The positive side of the supply is as described in Recipe 7.4, but in this case, in addition to a 78L12 (L for low-power) to regulate the positive side of the supply, a 79L12 negative voltage regulator is used to regulate the negative side of the supply.
Although a split supply like this is quite common in audio and scientific instruments, in general, it is more convenient to use a single supply as described in Recipe 17.3.
Figure 17-3 shows a common way of providing a 5V regulated supply and a 2.5V reference voltage using a voltage divider and capacitor. The capacitor C3 stabilizes the voltage further, making it less likely to be influenced by changes in the current flowing through the reference voltage.
As you will see in Recipe 17.4 and Recipe 17.5 nearly all op-amp circuits need this middle reference voltage to provide negative feedback to reduce the op-amp’s gain.
To improve this and provide a stable center voltage use a voltage divider and capacitor with a unity gain buffer as described in Recipe 17.6. If you have a design that uses several op-amps, you will often find that there is a “spare” op-amp in a quad op-amp package that can be used for this purpose.
To power an op-amp using a split-voltage supply, see Recipe 17.2.
Connect up your op-amp as shown in the schematic in Figure 17-4, which shows the arrangement assuming a split ±12V supply.
Without any feedback from the output of an op-amp to its input, the gain of the op-amp will be millions or billions, which is far too high to do anything useful other than amplify noise. This circuit uses R1 and R2 to reduce the gain of the op-amp to a reasonable level. A reasonable level is a factor between 10 and 10,000. If you need more gain than this, you will need to use multiple stages of amplification as well as some filtering to avoid amplifying unwanted noise.
The voltage gain of the circuit is set by the formula:
So if we want our amplifier to have a gain of –10 (times 10 but inverted), we could choose a value for R2 of 10kΩ and of R1 of 1kΩ. That way when we put +1V at IN, OUT would have a voltage of –10V. Conversely, if we put –0.1V at IN, OUT would be +1V.
If you want to use a single 5V supply, the same principle applies, but now the amplification takes place relative to the center voltage of 2.5V. Figure 17-5 shows the schematic for using a 5V regulated supply with an OPA365 rail-to-rail single-supply op-amp.
With single-supply operation, the voltage at IN must be between 0 and 5V and the amplification is relative to the center voltage of 2.5V. This means that if the voltage at IN is 2.5V then OUT will also be 2.5V, but if IN is 2.6V (0.1V higher than 2.5V) then OUT will be at 1.5V (1V less than 2.5V).
So, the formula to calculate Vout for any given Vin in the schematic in Figure 17-5 is:
No matter what the gain of your amplifier is, the op-amp’s output cannot exceed that of the supply voltages. A rail-to-rail op-amp will allow the voltage to swing from one supply to another but not beyond, but a non–rail-to-rail type op-amp may only allow you to get within a volt or two of the supply voltages.
Recipe 17.5 shows a noninverting op-amp configuration.
Use an op-amp in the noninverting configuration of Figure 17-6.
In this case, the gain of the amplifier is given by the formula:
If we used a 10kΩ resistor as R2 and a 1kΩ resistor as R1, the gain would be 11. In other words, the voltage at OUT would be 11 times the voltage at IN. If the voltage at IN is negative, the voltage at OUT will also be negative.
In the case of single-supply operation of the amplifier, let’s say 5V, we have the same 2.5V offset to contend with as we did in Recipe 17.4. Figure 17-7 shows how you might build a single-supply noninverting amplifier.
In this case, the gain is still:
And the output voltage is related to the input voltage by the equation:
The amplifiers described thus far are capable of amplifying both a DC signal (say from a sensor) and AC-changing signals (perhaps an audio signal). A single-supply 5V (or even 3.3V) design like this is ideally suited to connecting the output to the analog input of a microcontroller, as the voltage can swing between 0V and the supply voltage. In such cases, it is conceptually easier to deal with amplification of a voltage without the added complication of the amplified voltage being inverted about 2.5V, so it is more common to use this noninverting recipe in single-supply designs.
See Recipe 17.4 for inverting amplifier designs.
Configure the op-amp as shown in Figure 17-8.
The output voltage will track the input voltage. So if the input is 1V, the output will also be 1V. You can then hang whatever load you like off the output, without worrying too much about it affecting the input.
In other words, the voltage is not being amplified but the current that can pass through a load is greatly increased. An example where this might be used is as a headphone amplifier where the signal voltage is high enough in theory to drive the headphones, but the output would not otherwise be sufficient to power the low impedance of the headphones.
One situation where a buffer like this can be used is to provide the center voltage for a single-supply op-amp amplifier. Figure 17-9 shows a 5V single supply amplifier modified from Figure 17-7 to use a buffer in this way.
Because the input impedance to the buffer is very high, the value of C3 can be reduced as very little current at all will be flowing out of it. Think of it as reducing ripple on an unloaded power supply.
Another way to think of the action of a unity gain buffer is as a current amplifier, which is like using a bipolar transistor in an emitter-follower configuration in Recipe 16.4.
You want a low-pass filter to reduce the amplitude of high frequencies, but you need it to have a steeper cutoff than the simple RC filter of Recipe 16.3.
Use an op-amp and a 2-pole filter.
As an example, let’s say we want to revisit the crude filter you saw in Recipe 16.3 designed to separate a 440Hz signal from a 32.7kHz PWM carrier frequency. In that simple RC filter, we ended up with a corner frequency of 1.786kHz and saw that there would be a halving of signal amplitude for each doubling of the frequency. This resulted in a reduction in the amplitude of about a factor of 16 at 32kHz. By using an active filter, the attenuation (fall-off) at 32kHz can be improved to a factor of 100 easily.
When selecting component values for R1, R2, and C2, you can do a whole load of complicated math by hand, or you can use a filter design tool. In this recipe, we will use the Analog Filter Wizard provided by the chip manufacturer Analog Devices available as an online tool at http://www.analog.com/designtools/en/filterwizard/.
When you navigate to that page in your browser, you will be offered the choice of low-pass, high-pass, or band-pass. When you select low-pass, you will be given the opportunity to specify the corner frequency and other parameters for the filter as shown in Figure 17-10.
The tool is by default configured to work in units of dB (see Recipe 16.11). You can change this to just the amplitude voltage as a ratio by changing the drop-down lists under Passband and next to View to both be V/V as shown in Figure 17-10, where the corner frequency has been set to 1.78kHz and the desired stop-band set to –40dB (factor of 1/100) at 32kHz.
Use the filter-response slider to determine just how steep the curve will be as well as how flat the pass-band’s response is. This will also alter the number of op-amps needed for the design (stages) and the order of the filter. A single op-amp can implement a second-order filter. More orders than that and you will need to chain together several op-amps. The filter type (Butterworth, Chebyshec, or Bessel) will all use the same schematic but different component values to provide different behaviors. See the discussion section for the differences.
For the sake of this example, position the slider so that the second-order Butterworth (first stage) is recommended by the tool and then click Go to Component Selection and “presto,” a schematic complete with component values will be recommended to you as shown in Figure 17-11.
You can then specify supply voltages and other properties of your design as well as look at the effect of component accuracy on the design. Since this is an Analog Devices tool, it will obviously recommend the op-amps they manufacture, but the designs can be used with other manufacturers’ op-amps.
There is nothing to stop you from adding some gain to your filter so that it both filters and amplifies by replacing the connection from the op-amp output to the negative input with a pair of resistors as used in the noninverting amplifier design of Recipe 17.5. In fact, the design tool does allow you to specify a gain when you are specifying the filter (see Figure 17-10).
Unless you have a particularly demanding project, a second-order filter using a single op-amp will generally provide a good balance between complexity and performance. There are whole books written on filter design and other more complex filter design tools.
The properties of the three filter types offered by the Analog Filter Wizard are:
These types are all implemented using the same schematic in Figure 17-11; the calculations performed by the Analog Filter Wizard determine the type of filter.
For other types of filter designs, see the next few recipes.
Use a second-order filter implemented using a single op-amp and design it using a design tool such as the Analog Filter Wizard. Figure 17-12 shows the frequency response of a filter designed by the Analog Filter Wizard to provide high-pass filtering with a gain of 10 and a corner frequency of 1kHz.
Notice that there is a little “hump” in the response between 2kHz and 3kHz where the gain goes above the desired value of 10. This is called overshoot and is another characteristic of Chebyshev filters.
The corresponding schematic for this filter is shown in Figure 17-13.
Most of the things said in the discussion section of Recipe 17.7, especially about the different types of filters, apply equally well to high-pass filters.
Notice that in Figure 17-13 the Analog Filter Wizard has also helpfully suggested the necessary bypass capacitor values (Recipe 15.1).
For a low-pass filter see Recipe 17.7 and for a band-pass filter see Recipe 17.9.
If the band of frequencies you are interested in is reasonably wide, then the best solution is to simply pass the signal through a low-pass filter (Recipe 17.7) and then a high-pass filter (Recipe 17.8.) This will require two op-amps, but then dual op-amp ICs are not much more expensive than single op-amp ICs.
Figure 17-14 shows the schematic for a band-pass filter with corner frequencies of 20Hz and 20kHz, which might be used to restrict a signal to the audio-frequency range.
The filter was designed using the Analog Filter Wizard used in Recipe 17.7 and Recipe 17.8. This time the filter type of Band-pass is selected and the parameters entered as shown in Figure 17-15.
The pass-band is set to 20kHz for a 3dB drop in amplitude (0.71 of the original amplitude) and the stop-band to 100kHz at the high end where we are aiming for attenuation of 20dB (0.1 of original signal amplitude).
The center frequency is not the 10kHz that you might expect but rather the square root of the product of the upper- and lower-corner frequencies. In other words:
Filter design is a specialized field, and in this book, there is only room to look at the most common electronics recipes. However, for many applications a simple design that uses a single op-amp stage will be perfectly adequate.
For low-pass active filter design see Recipe 17.7 and for high-pass filter design see Recipe 17.8.
Use a device closely related to the op-amp called a comparator. Figure 17-16 shows how you could make a simple automatic light that turns on an LED when the light level falls below a certain threshold.
R1 and R3 form a voltage divider whose output corresponds to the light level; that is, the higher the volate, the higher the light level. The variable resistor R2 is used to set the reference voltage at IN–.
The output of the LM311 provides optimal flexibility by providing connections to both the emitter and collector of the NPN output transistor.
If the light level is low enough for IN+ to be lower than IN– the base of the output transistor is supplied with current, and since the emitter is grounded, the transistor turns on and current flows through the LED.
This logic of the transistor being on if IN+ is lower than IN– would seem to be counterintuitive, but the output transistor will often have its emitter grounded and the logic output taken from the collector, which is pulled up to VCC. This effectively acts as an inverter and hence the collector output will be high if IN+ is greater than IN–.
To sense light using an Arduino, see Recipe 12.3 and for a Raspberry Pi Recipe 12.6.
Audio electronics is all about generating signals and amplifying them enough to power a loudspeaker so that you can hear them.
This chapter contains a number of amplification and signal-generation recipes. Any resource that deals with audio-power amplifier design will explain the different classes of amplifiers, which are designated by A, B, AB, and D, and some other more exotic designs. For the most part, these letters designate how the amplifier is constructed from bipolar junction transistors and how they are biased. Since these days there is no real cost or even quality advantage (apart from the most demanding audiophile) to building an amplifier from separate transistors rather than just using an IC, I feel it is only necessary here to highlight the most common designs along with their main characteristics:
Before launching into the construction of your own amplifier designs, think about whether you need to build the amplifier from scratch. For most one-off projects, it is easier and cheaper to use ready-made modules or even USB-powered amplified speakers.
When it comes to generating sound waves from an Arduino, you can easily generate tones. The Raspberry Pi with its large amount of memory and sophisticated hardware allows MP3 and other sounds files to be played through its audio jack, which can then be connected to an external amplifier.
You can experiment with generating tones and driving a speaker from an Arduino if you connect a speaker to an Arduino as shown in Figure 18-1.
The sketch ch_18_speaker can be found with the downloads for the book (see Recipe 10.2):
constintoutputPin=10;voidsetup(){pinMode(outputPin,OUTPUT);Serial.begin(9600);Serial.println("Enter frequency 100-8000 Hz (0 off)");}voidloop(){if(Serial.available()){intf=Serial.parseInt();if(f==0){noTone(outputPin);}else{tone(outputPin,f);}}}
The Arduino tone function takes two parameters, the pin to generate a tone on and the frequency of the tone to generate as a long integer value. The tone function can generate frequencies from 31Hz to 65,535Hz.
To use it, open the Arduino Serial Monitor and make sure you have the Line Ending drop-down list set to “No line ending” then type in a frequency in Hz and click Send.
The 5V signal generated by the tone command is a little too high a voltage to feed directly into an amplifier. It should be reduced to below 2V or so using a pair of resistors as a voltage divider. 1kΩ and 270Ω resistors with the 270Ω resistor to GND will reduce the output by a factor of about 5.
A loudspeaker is an inductive load, so, like the coil of a relay, there is a risk of voltage spikes arising that could damage the GPIO pin driving the speaker. In reality, when using a small speaker driven through a resistor, these spikes will be sufficiently low in energy for the antistatic protection of the GPIO pin to take care of them.
Making crude square-wave buzzing has its place, but the Arduino is actually capable of more sophisticated sound generation using the Mozzi library, which uses a high-frequency PWM signal at 32.7kHz to generate the sound file using PWM.
To try out Mozzi and hear the difference between the square and sinewaves, install the Mozzi library and then run the example program included with the Mozzi library 01. Basics→Sinewave.
You will need to change the connection to R1 from Arduino pin 10 to pin 9 that is used by Mozzi.
If you want to know how Mozzi sounds are generated skip ahead to Recipe 18.1.
For using a voltage divider, see Recipe 2.6.
For oscillator recipes that do not require an Arduino, see Recipe 16.2, Recipe 16.5, and Recipe 16.6.
To generate better-sounding audio from an Arduino, take a look at the Arduino Mozzi library.
When it comes to hardware, most models of Raspberry Pi have a 3.5mm headphone-style jack socket that can be attached to a stereo amplifier and speakers.
In recent versions of Raspbian, you will find the OMXPlayer preinstalled. To play a sound file, you just need to name the sound file you want to play OMXPlayer. For example:
$ omxplayer file.mp3
If you need to play the sound file from within a Python program you can use the os.system command to run OMXPlayer, as follows:
importosos.system('omxplayer file.mp3')
In addition to the headphone jack, sound can also be played through the HDMI connector. The OMXPlayer software should automatically play through HDMI unless the audio jack has something plugged into it.
You can choose the channel the sound should be played through by using the -o option, which can have a value of either local (audio socket) or hdmi. For example:
$ omxplayer -o hdmi file.mp3
You can find out more about the OMXPlayer here: http://elinux.org/Omxplayer. In addition to sound files in most formats, the player can also play video files.
For an alternative method of playing sound files using the Pygame library, see http://bit.ly/2mt4eDM.
The Raspberry Pi Zero does not have an audio jack, but you can still use it to play audio; see http://bit.ly/2mIjZH9 for details.
Use a single-supply rail-to-rail op-amp like the OPA365 and amplify the signal by a factor of between 30 and 100. A gain of 30 is about right if you will be speaking directly into the microphone and 100 if you want the microphone to be useful in picking up ambient sounds.
Figure 18-3 shows the schematic for the microphone preamp with a gain of 101. For a discussion of how to set the gain, see Recipe 17.5.
C1 is used to “AC couple” the weak output from the microphone to the noninverting input of the op-amp. It allows only the AC part of the signal from the mic, rejecting the DC bias that would otherwise be present.
Electret microphones operate like capacitors. Sound waves effectively move one plate of the capacitor closer or further away. The plates of the electret are charged during manufacture and retain that charge for the life of the microphone. These changes in capacitance are converted into a small voltage using an FET transistor built into the microphone. The microphone module is polarized and must be connected the right way around. You also need to supply a drain resistor for the FET (R5 in Figure 18-3).
The circuit of Figure 18-3 will produce an output centered around 2.5V that can be connected directly to an Arduino’s analog input and allow you to do things like measure the maximum sound level.
Figure 18-4 shows the circuit used with an Arduino Uno.
This circuit can be built on a breadboard, but the OPA365 is only available as an SMD, so you will need to use a SOT-23 or SOIC breakout board such as the one from Schmartboard.com, as shown in Figure 18-5.
The Arduino sketch ch_18_sound_meter (see Recipe 10.2) samples the analog input A0 for 100ms and then reports on the maximum amplitude it sampled (Figure 18-6). You could modify this sketch to trigger some action if the sound level rises above a certain level.
Note that the maximum possible reading will be 512 (half the full analog value reading):
constintsoundPin=A0;constlongsamplePeriod=100;// mslonglastSampleTime=0;intmaxAmplitude=0;intn=0;voidsetup(){Serial.begin(9600);}voidloop(){longnow=millis();if(now>lastSampleTime+samplePeriod){processSoundLevel();n=0;maxAmplitude=0;lastSampleTime=now;}else{intamplitude=analogRead(soundPin)-512;if(amplitude>maxAmplitude){maxAmplitude=amplitude;}n++;}}voidprocessSoundLevel(){// replace or add your own code to use maxAmplitudeSerial.("Of ");Serial.(n);Serial.(" samples, the maximum was ");Serial.println(maxAmplitude);}
Ready-made microphone preamplifier modules are available that use electret microphones, for example: https://www.sparkfun.com/products/12758.
Alternatively, you can use the type of microphone found in cellphones called MEMS (microelectromechanical systems). These are essentially microphones on a chip. SparkFun and others sell breakout boards for these extremely tiny microphones, such as this one: https://www.sparkfun.com/products/9868.
For information on using analog inputs with an Arduino, see Recipe 10.12.
You need a low-cost power amplifier to power a small speaker at low volumes, say to accompany an FM radio receiver as in Recipe 19.3.
Use a power-amp IC like the TDA7052, which will work with any power supply from 3V to 15V and can supply 1W of power into an 8Ω speaker. The schematic for a simple amplifier using this device is shown in Figure 18-7.
R1 and R2 are only provided to show how to mix the left and right signals of a stereo audio source to mono. If you have a mono source, just connect it directly to C3.
R3 acts as a volume control, and if the sound source has a volume control, you can replace this with two fixed resistors acting as a voltage divider.
C1 and C2 provide energy stores for the rapidly changing load of the IC as it drives the speaker. C1 should be placed as close to IC1 as possible.
Figure 18-8 shows how you can build an amplifier like this on a solderless breadboard. In this case, the breadboard is stuck to a Monk Makes Protoboard for the convenience of being able to attach the speaker to screw terminals and use the audio jack and power jack.
1W is not very powerful compared with the 20W or more you will generally find in a home stereo system. An amplifier is generally considered a “power” amp if it has enough current amplification to drive a low impedance load (i.e., 4 or 8Ω loudspeakers).
The TDA7052 datasheet can be found here: http://bit.ly/2nA0GgB.
For high-power class-D design, see Recipe 18.5.
Use a class-D digital amplifier IC such as the TPA3122D2. The schematic for this is shown in Figure 18-9.
This design is a modified version of the one found on page 14 of this chip’s datasheet. It will operate on a supply voltage of 10 to 30V, but at a convenient 12V will supply about 7.5W per channel into 4Ω speakers. For more power you need to increase the supply voltage.
The TPA3122D2 is a 20-pin DIL (dual in-line) IC that makes the design very suitable for prototyping on a breadboard (Figure 18-10).
One interesting feature of the TPA3122D2 is that the gain is set by two digital inputs that set the gain to one of four values. Table 18-1 shows how these pins are used. In the schematic of Figure 18-9 the lowest gain of 20dB is selected.
| GAIN1 | GAIN0 | Amplifier gain (dB) |
|---|---|---|
| LOW | LOW | 20 |
| LOW | HIGH | 26 |
| HIGH | LOW | 32 |
| HIGH | HIGH | 36 |
Unlike traditional amplifier designs like that of Recipe 18.4 class-D amplifiers are extremely efficient, transferring sometimes over 90% of the power supplied to them to the output load (loudspeaker).
Figure 18-11 shows how a class-D amplifier works.
The input signal is converted into high-frequency PWM (250kHz in the case of the TPA3122D2) by a combination of a triangle-wave generator and comparator. This is actually the way Recipe 16.9 works. The length of the pulse will be determined by the time it takes for the triangular signal to exceed the value of the analog input. Since the analog input is a much lower frequency than the triangle wave, it can be considered as having a constant instantaneous value, while the triangle wave is “sampling” it. It’s a bit like driving fast past someone who is walking—the pedestrian is effectively stationary from the car’s perspective.
This PWM signal can then be amplified by transistors in a half-bridge switching arrangement such as the one in Recipe 11.8. This is then low-pass filtered and fed to the loudspeaker.
Digital amplifiers are perfectly acceptable for many applications, but they are unlikely to be accepted by HiFi enthusiasts without considerable improvements in design. They generally have higher levels of distortion than analog amplifiers. In Figure 18-12 you can clearly see the distortion in the sinewave being amplified.
For the TPA3122D2 datasheet see http://www.ti.com/lit/ds/symlink/tpa3122d2.pdf.
It used to be that any electronics book worth its salt would include discrete circuits for AM and FM broadcast receivers and maybe even discuss how an analog TV works. In these digital days, topics like this are only for historical interest.
For this reason, this chapter mostly concentrates on the use of digital communications using radio frequencies. The discussion of the nature of radio is restricted to this introduction. The recipes themselves are fundamentally practical.
We take radio frequency for granted now, but when it first became popular, it must have seemed like magic. After all, it allowed you to talk to someone miles away without any wires connecting them. How could this be possible?
Recipe 19.1, Recipe 19.2, and Recipe 19.4 are radio transmitters. Although most countries allow the use of low-power, short-range FM transmitters and allocate certain bands for use with packet radio, you should check your local regulations and make sure you are not breaking the law by using any of these designs.
It all starts with AM transmissions, which use a carrier frequency modulated by the audio signal that is being transmitted. Figure 19-1 shows how this works.
In Figure 19-1 the carrier frequency is only about 4.5 times the audio signal. In a real AM broadcast, the audio signal will generally be a maximum of 16kHz against a carrier frequency of 500kHz, making at least ten times as many cycles of carrier in each cycle of the audio frequency shown in Figure 19-1. But it’s easier to see what is going on with fewer cycles.
Each transmitting station has its own frequency, and for AM public broadcasts in the medium wave (MW) band, this range is around 520kHz to 1600kHz. The amplitude of the carrier is modulated by the audio signal and the resulting signal broadcast through an antenna.
One of the reasons the quality of AM is so bad is that there are many other factors that can affect the amplitude of the carrier, including atmospheric conditions or changes in position of the receiver if you are listening in a moving vehicle.
When it comes to the receiver, you need to be able to separate the radio-frequency carrier (RF) from the audio signal.
The first step in this is to “tune in” to the transmission frequency you are interested in. This means using a narrow band-pass filter (Recipe 17.9) so that all the other stations get tuned out. This is traditionally accomplished by using a tuned circuit in the form of a fixed inductor (also acting as the antenna) and a variable capacitor that is varied to tune into different frequencies.
Since your ears cannot hear frequencies above 20kHz (lower as you get older) a radio carrier frequency of 500kHz or more will be inaudible. With your ears acting as a low-pass filter, you might expect that with suitable amplification of the tuned radio signal, you would be able to hear the audio signal modulating it. This is almost correct, but because the “average” of each cycle (whatever the amplitude) is zero (each positive wave followed by a negative one), you won’t hear anything. However, if you introduce a diode to remove one half of the signal (Figure 19-2), then suddenly the original audio signal can be separated and you will be able to hear the audio in the envelope of the AM signal and your ears will now happily be a low-pass filter for you.
The big empty space on the bottom of Figure 19-2 serves to show where the diode has removed the negative part of the tuned signal.
The earliest AM receivers (crystal sets) were literally a coil, antenna, variable capacitor, diode (germanium for its lower forward voltage), and sensitive headphones as shown in Figure 19-3.
Improvements have been made to the design of AM receivers, in particular amplification of the RF signal before detection, followed by further amplification to drive a loudspeaker, but the basic principles of an AM receiver are as they were a century ago.
Frequency modulation (FM) improves on AM by varying the frequency of the carrier rather than its amplitude. This improves the quality of the sound being broadcast, as the frequency is immune from changes due to atmospheric conditions or movement of the receiver. Figure 19-4 shows how an audio signal would be used to modulate a carrier.
To create an FM transmitter, a VCO (Recipe 16.10) is used. The audio signal is fed into the frequency control input of the VCO to vary the frequency. The first recipe in this chapter (Recipe 19.1) is a simple, low-power FM transmitter.
Extracting the audio signal from an FM broadcast can be accomplished by using a number of techniques, but perhaps the most common is to use a VCO in an arrangement called a phase-locked-loop (PLL). Figure 19-5 shows a PLL configured as an FM demodulator.
The RF signal is first tuned to a particular frequency as with an AM receiver, but then to demodulate the original audio, the RF signal is fed into a phase comparator. The phase comparator produces an output that is zero if its two input signals are completely in phase. If the signals are out of phase with each other then the comparator produces an output proportional to the difference in phase. This signal is then low-pass filtered, amplified, and used to control a VCO whose output supplies the second input to the phase comparator. This feedback results in the VCO producing a signal of the same frequency as the RF input to the phase comparator. As the output of the VCO tracks the RF frequencies the small shifts in phase resulting from the modulation will result in the audio signal being available in the filtered and amplified output of the phase detector. The amplified output contains the demodulated audio signal almost as a side effect of the PLL tracking the broadcast signal.
PLL chips are available that include the VCO, phase comparator, and other parts all in one convenient package. However, if you are making an FM receiver, then you would just use an FM receiver IC that includes the RF amplification, PLL, and pretty much everything needed for the receiver aside from a few resistors, capacitors, and inductors.
Radio is now very much a digital affair. FM radio receivers and transmitters are now often implemented as software-defined radios (SDRs). Processors are now so fast that with a very small amount of hardware they can produce and decode analog broadcast signals in software. For example, the filtering, phase detecting, etc. of a PLL can all be done as software algorithms rather than directly in hardware. In Recipe 19.2 you will find a recipe for a SDR FM transmitter using a Raspberry Pi.
In addition to using digital electronics to decode analog signals, the use of digital signals carried on RF is everywhere from your cellphone to the remote you use to unlock your car.
This chapter has several recipes for passing digital data wirelessly between devices.
Use a high-frequency VCO chip (MAX2606) set to operate in a frequency on the FM band and use the audio signal to make small adjustments to the frequency.
The schematic for this is shown in Figure 19-6.
The variable resistor R4 is used to tune the transmitter to a particular frequency. The antenna can be a telescopic FM antenna or simply a few feet of wire.
The inductor L1 sets the center frequency of the VCO. The datasheet for this device indicates that an inductor of 390nH will give a center frequency of around 102MHz.
The control signal applied to the TUNE pin of the VCO comprises a fixed DC offset supplied by R4 (to allow tuning to a particular transmission frequency) and an audio signal that is sufficient to produce the desired frequency modulation.
The output OUT+ of the MAX2606 drives the antenna. The datasheet also suggests that complementary open-collector output OUT– is also supplied with a 1kΩ pull-up resistor.
This recipe is based on the tutorial by Afroman who also has an open source hardware circuit board that you can make yourself or buy from OSHPark.
The datasheet for the MAX2606 can be found at http://bit.ly/2ltwp5O.
Use the PiFM software and attach an antenna to GPIO pin 4 of your Raspberry Pi. This can be just a female-to-male jumper wire as shown in Figure 19-7.
First, you’ll need to download and install PiFM using the following commands:
$ mkdir pifm $ cd pifm $ wget http://omattos.com/pifm.tar.gz $ tar -xvf pifm.tar.gz
If you have a Raspberry Pi 2 or 3, you have to download and compile a modified version of the software to work on the newer hardware, so run the following commands:
$ git clone https://github.com/oatmeal3000/pi2fm.git $ mv pi2fm pi2fmdir $ mv pi2fmdir/pi2fm.c . $ gcc -lm -std=c99 -g pi2fm.c -o pi2fm
You will now have two executable programs, one called pifm for the Raspberry Pi 1 models and pi2fm for the Raspberry Pi 2 and 3. If you have an original Pi 1 you will need to modify pi2fm to be just pifm in the following commands, which will play the file sound.wav supplied with the pifm software:
pi@raspberrypi:~/pifm $ sudo ./pi2fm sound.wav 94.0 starting... -> carrier freq: 94.0 MHz -> band width: 8.0 now broadcasting: sound.wav ...
Attaching a longer wire to pin 4 will considerably increase the range of the transmitter.
The original web page for the PiFM project can be found here: http://bit.ly/18AcT5u.
Details on the Raspberry Pi 2 version are here: https://github.com/oatmeal3000/pi2fm.
Use a TEA5767 FM radio-receiver module controlled by an Arduino and either connect headphones or use a power amplifier to drive speakers.
Figure 19-8 shows how the module is connected to an Arduino.
To make the module as easy to program as possible, download the Arduino TEA5767 library by clicking on Clone or download on GitHub. Select the option to download as a ZIP file and then from the Arduino IDE select the menu option Sketch→Include Library→Add ZIP Library and navigate to the ZIP file you just downloaded.
To build a circuit using this module on a breadboard (Figure 19-9), you will need a breakout circuit board that allows you to connect the fine pitch of the module’s connectors to the breadboard. You can make this yourself using stripboard or buy a breakout board from OSHPark or Monk Makes.
The sketch ch_19_fm_radio uses the Serial Monitor so that you can enter the frequency you want to tune in to. When using the Serial Monitor with this sketch, make sure the “Line ending” drop-down list is set to “No line ending” before sending a frequency to the Arduino.
The sketch is available with the book downloads (see Recipe 10.2) and is listed here:
#include <Wire.h>#include <TEA5767Radio.h>TEA5767Radioradio=TEA5767Radio();voidsetup(){Serial.begin(9600);Serial.println("Enter Frequency:");Wire.begin();}voidloop(){if(Serial.available()){floatf=Serial.parseFloat();radio.setFrequency(f);Serial.println(f);}}
The setFrequency function accepts a decimal value in MHz (e.g., 93.0).
To make a suitable power amplifier for this project, see Recipe 18.4 or Recipe 18.5.
For an FM transmitter to accompany this receiver, see Recipe 19.1 or Recipe 19.2.
Use a CC1101 RF transceiver (transmitter/receiver). These boards are readily available on eBay at very low cost. Figure 19-10 shows how you would wire one up to the SPI interface of an Arduino.
The module is a 3.3V device and the datasheet states that none of the pins should have a voltage of more than 3.9V applied to them, so a level converter should be used on all pins used as inputs to the CC1101. This takes the form of six resistors used in pairs as voltage dividers (see Recipe 2.6).
Clearly to test out this recipe, you will need two Arduinos and two CC1101 modules each wired up as shown in Figure 19-11.
Testing the modules can get very confusing because the Arduino IDE can only have one port selected at a time. It’s much easier to find a second computer to use both for programming the transmitter and for running the Serial Monitor.
The library used for these examples should be downloaded as a ZIP file from https://github.com/simonmonk/CC1101_arduino by clicking on the Clone or download button and selecting Download ZIP. Save the ZIP file somewhere and then from the Sketch menu choose Sketch→Include Library→Add ZIP Library and select the ZIP you just downloaded.
The two example programs (one for transmit and one for receive) are the examples that accompany the library, but these can also be downloaded with the downloads for the book (see Recipe 10.2).
Here is the transmitter code (ch_19_cc1101_tx):
#include <ELECHOUSE_CC1101.h>constintn=61;bytebuffer[n]="";voidsetup(){Serial.begin(9600);Serial.println("Set line ending to New Line in Serial Monitor.");Serial.println("Enter Message");ELECHOUSE_cc1101.Init(F_433);// set frequency - F_433, F_868, F_965 MHz}voidloop(){if(Serial.available()){intlen=Serial.readBytesUntil('\n',buffer,n);buffer[len]='\0';Serial.println((char*)buffer);ELECHOUSE_cc1101.SendData(buffer,len);}}
The maximum packet size is 64 bytes and buffer is used to contain the data to be sent, which can by anything you can pack into a byte array. In this case, short text messages.
In the setup function, the communication frequency is set. The Serial Monitor first reminds you to turn line endings on in the Serial Monitor. When you send a message the contents of the message are written into buffer and SendData then used to transmit the message you typed.
The corresponding receiver code can be found in ch_19_cc1101_tx and is listed here:
#include <ELECHOUSE_CC1101.h>constintn=61;voidsetup(){Serial.begin(9600);Serial.println("Rx");ELECHOUSE_cc1101.Init(F_433);// set frequency - F_433, F_868, F_965 MHzELECHOUSE_cc1101.SetReceive();}bytebuffer[61]={0};voidloop(){if(ELECHOUSE_cc1101.CheckReceiveFlag()){intlen=ELECHOUSE_cc1101.ReceiveData(buffer);buffer[len]='\0';Serial.println((char*)buffer);ELECHOUSE_cc1101.SetReceive();}}
This sketch uses CheckReceiveFlag to monitor Arduino pin 2 for the CC1101 to indicate that a new message has arrived. When a message does arrive, it is read into buffer and then displayed in the Serial Monitor. Figures 19-12 and 19-13 show the Serial Monitors of the transmitter and receiver, respectively.
You can find the datasheet for the CC1101 IC here: http://bit.ly/2ltuxK9.
The library used here is modified from that of elechouse.com that also sells CC1101 modules: http://bit.ly/2n3lnQK.
Using a solderless breadboard (Figure 20-1) is a great way to temporarily build an electronic design because you can easily swap out different components without having to desolder (Recipe 20.6). Once the design is right it can be transferred either to a prototyping board (Recipe 20.2) or a circuit board of your own design (Recipe 20.3).
Breadboards are available in many shapes and sizes. I recommend having a good supply of 400-point breadboards (often called half-breadboards) as these are a great size to accommodate a couple of chips and a whole load of components. For those situations where you need more prototyping area breadboards can be clipped together.
Figure 20-2 shows how a 400-point breadboard is constructed of rows of five holes, all connected together by a clip. Note that there is a break in connectivity between “abcde” and “fghij.”
The “supply rails” in pairs down the sides of the board are all connected together and can be used for any purpose, but generally the ones marked in blue or with a “–” next to them are used for ground and the red ones marked with a “+” are used for the positive supply.
The rows and columns of the breadboard are labeled with numbers and letters, making it easier to transfer the designs to a more permanent design using Permaproto or Monk Makes Protoboard. These are general-purpose circuit boards with the same layout as breadboards.
Figure 20-3 shows the two-transistor oscillator from Recipe 16.2 built on a breadboard.
Through-hole component leads are pushed into holes on the breadboard and connected to other component leads either by being in the same breadboard row, or by using male-to-male jumper wires to link one part of the board to another.
There is a bit of craft involved in the mental conversion of a schematic to a breadboard layout. Figure 20-4 shows the schematic layout for Recipe 16.2 and Figure 20-5 the one corresponding to the breadboard layout (also shown in Figure 20-3).
When transferring a schematic to a breadboard, I start with the key components and the ones whose legs won’t bend very far. Usually this means starting with any ICs, but in this case, it means the transistors, which I have placed on opposite halves of the breadboard, mirroring the schematic.
Then I add the other components and jumper wires. There is no hard and fast method for this layout, and of course, being solderless, it’s very easy to change things around if you run out of room.
Figure 20-5 was drawn using an open source software tool called Fritzing. This tool produces great-looking diagrams and also allows you to view the same circuit as a schematic, breadboard, or circuit board design, allowing you to use the same software right through from prototyping to circuit board.
When it comes to connecting a breadboard to an Arduino or Raspberry Pi, you can use male-to-male or male-to-female jumper wires, respectively. Figure 20-6 shows Recipe 12.12 on a breadboard connected to a Raspberry Pi.
Figure 20-7 shows an Arduino Micro on a solderless breadboard. This is one of several models of Arduino including the “mini” and “nano” models that are “breadboard friendly.”
The breadboard shown in Figure 20-3 is likely to have proper electronic engineers holding their heads in their hands and gritting their teeth. The problem with it is that it is all too easy for a component lead to touch another lead that it shouldn’t or simply fall out. This type of arrangement requires care to make sure nothing is touching that shouldn’t be but is fine while you are getting something working. For a halfway house before you move to a soldered prototype, you can take a neater approach and use solid-core wire trimmed to just the right length to lie flat on the breadboard instead of using jumper wires. You can also trim all the component legs so that they are just the right lengths, but this can make them difficult to reuse in your next design.
For more information on Fritzing see http://fritzing.org or my book Fritzing for Inventors, TAB DIY, 2015.
When you are ready to transfer your design to a soldered prototype follow Recipe 20.2.
Use a prototyping board or protoboard such as the Adafruit Permaproto or the Monk Makes Protoboard and simply transfer the components from their positions on the breadboard to the same locations on the protoboard.
Figure 20-8 shows the starting point for this process of transferring the design from a breadboard to a Monk Makes Protoboard. The details of the design are not important, but for those interested, it is an energy monitor using a particle photon Arduino-like board, a current sensor, and an AC transformer. Note that the breadboard itself is attached to a Monk Makes Protoboard to allow use of the screw terminal and audio-type socket to connect the current sensor and AC transformer to the prototype.
The components can then be moved from the breadboard one at a time, making note of the lead’s row and column coordinates and soldering them onto the Monk Makes Protoboard as shown in Figure 20-9. Finally, Figure 20-10 shows the completed board and the bare breadboard ready for your next project.
Other useful prototyping boards are available including Permaproto boards from Adafruit that are designed to be attached by a ribbon connector to a Raspberry Pi.
When it comes to Arduino, the Arduino Protoshield is a great way to build something and then plug it as a whole board into the top of an Arduino Uno. Figure 20-11 shows a Protoshield with an LED cube project built onto it. The Protoshield is then attached to an Arduino.
Another popular method for making soldered prototypes is to use stripboard. Stripboard (Figure 20-12 and Figure 20-13) is arranged with copper tracks in rows and can be cut to whatever size you need for your project. Breaks in the track are made using a tool called a “spot cutter” or by using a drill bit rotated by hand just enough to cut the copper.
Perfboard (i.e., perforated board) is like stripboard, but without the copper strips on the back. All connections are made by bending the component leads or lengths of solid-core wire.
Protoboard, which is a variation on perfboard with a separate pad behind each hole, is also available.
For Permaproto see: https://www.adafruit.com/product/571.
For Monk Makes Protoboard see: https://www.monkmakes.com/pb/
The LED cube project is taken from my book The TAB Book of Arduino Projects, TAB DIY, 2015.
While the solution to this recipe cannot fit into one recipe, you can start by using circuit board design software such as CadSoft EAGLE to draw the schematic for your boards and then layout a circuit board. You can then send away the design files (known as Gerbers) to a circuit board fabrication provider.
Designing a simple circuit board is well within the reach of the amateur. If you restrict yourself to two copper layers, then you can use one of many CAD (computer-aided design) packages for circuit board design.
Perhaps the most popular CAD system is EAGLE CAD (Figure 20-14), which is not open source, but there is a free version for noncommercial projects. One advantage of using EAGLE CAD is that it has been adopted by the open source hardware movement as their CAD system of choice and there are many OSH designs for which the EAGLE design files are available for download, which you can adapt to your own needs. EAGLE is not an intuitive piece of software. If you have used any other circuit board design software, you may be able to find your way around unaided, but typically you will need to follow a few tutorials step-by-step before it really starts to make sense.
Nearly all the schematic diagrams in this book were drawn with EAGLE and once you are familiar with all its quirks, you will probably grow to enjoy using it.
For open source enthusiasts KiCad is a fully featured open source equivalent to EAGLE, and it can import some EAGLE file formats. Like EAGLE, don’t expect to have a finished board design ten minutes after downloading the software.
DesignSpark is a free-ish CAD system that is gaining in popularity and is relatively easy to use, but it does inflict adverts on users.
If you have a really simple circuit board design to make that uses fairly common components, then Fritzing will take you to circuit board design via schematic and breadboard and is easy to use. However, if you run into parts that are not included with Fritzing (and you probably will) you may well have to make your own parts, which is a little tricky and requires you to have some skill editing multilayer SVG files.
All of the CAD options described will give you the option to export Gerber design files. You can then use an online circuit board service that will let you upload a ZIP file containing the design, and in a week or two, send you back a small batch of boards. The minimum is usually 10 for as little as a dollar a board for small boards.
The circuit board services are changing all the time. I have used PCBWay, ITEAD Studio, and Seeed Studio for circuit board manufacture without any problems.
It used to be worth making your own circuit boards. In fact, I still have all the equipment for this tucked away in a box that I don’t expect ever to open. Photo etching your own circuit boards does not need to be expensive; you can make your own UV exposure box with UV LEDs easily enough, but you will also need noxious chemicals that do not keep once mixed and are difficult to dispose of responsibly. The end results are also generally inferior to the circuit boards a professional service will produce for you. So my advice is to plan ahead a little and have your circuit boards produced professionally.
For a guide to EAGLE CAD see: Make Your Own PCBs with EAGLE: From Schematic Designs to Finished Boards, TAB DIY, 2014.
The KiKad website is here: http://kicad-pcb.org/.
You can find out about DesignSpark here: https://www.rs-online.com/designspark/pcb-software.
I also have also written a guide to using Fritzing called Fritzing for Inventors: Take Your Electronics Project from Prototype to Product, TAB DIY, 2015.
Make the junction of the component lead and the solder pad hot for a second or two before applying the solder, as shown in Figure 20-15.
In more detail, to make a good solder joint, you should:
Soldering irons get hot—very hot—and can inflict nasty burns, so be careful. Safety glasses are a good idea as occasionally specks of solder can fly off if flicked by a lead, or even from boiling flux, and if your eyes are close to the thing you are soldering (which is quite likely) you could damage your eyes.
It is also a good idea to use a fume extractor (these do not need to be expensive; see Appendix A) to take away the noxious fumes released as the flux in the solder burns. This is not really something you want in your lungs.
Due to various international regulations that have been put in place, lead (the element Pb) is rapidly being phased out of use in circuit board manufacture. Most solder is now unleaded. Unfortunately, unleaded solder has a higher melting point and is generally a bit more difficult to use than the leaded variety. You can still buy leaded solder and many people keep a reel of “the good stuff.”
If you are using small components, then use a thin multicore rosin solder. I use 0.7mm.
You will find some good video tutorials for soldering on YouTube, and SparkFun has a great video on how to solder here: http://bit.ly/2mDxVyD.
I also recommend the book Learn to Solder by Brian Jepson, Maker Media, 2012.
If you are making a one-off, or just a few prototypes, consider soldering by hand. Unless you are very skilled, the results will not be great, but you should be able to make a functional prototype this way.
Soldering by hand is a great deal easier if you stick to SMD resistors and capacitors that are 0603 or larger and ICs with a pin spacing of 50 mils (1.27mm) or wider as found in SOIC packages.
Most components are available in a variety of different package sizes.
When soldering SMDs you will need to hold the part down (I use tweezers) while you solder each pin to a pad. As with through-hole soldering, heat the pin and pad for a second or so before touching the solder onto the pad and pin, flowing the solder into the joint.
When soldering the first pin, it’s best to put a tiny blob of solder on one pad (Figure 20-16) and then solder the first pin by just heating and pressing the pin onto the pad (Figure 20-17). You should find that once one pin is soldered, you don’t need to hold the device in place (Figure 20-18). When you have soldered all the other pins, it’s a good idea to circle back to the first pin and just flow a bit of solder into it to make sure it’s well soldered.
An alternative to using a soldering iron is to use solder paste and a hot-air gun. Here the procedure is to first place a little solder paste onto the component pads (Figure 20-19). Place the component onto the pads and hold it down with the tip of the tweezers while you heat it up with the hot-air gun (Figure 20-20).
If you have a reflow oven, like the homemade one shown in Figure 20-21, then you start as you would when using a hot-air gun, placing solder paste onto each pad. This task can be made easier by using a stencil, which most circuit board manufacturers will provide during circuit board manufacture for an extra cost.
Having applied the solder paste, place the components (they will stick to the solder paste). Then “cook” the board to melt the solder paste. A sophisticated reflow oven will have profiles you can set for different types of solder paste. It is surprising what you can get away with using a homemade oven. Mine is made from a converted toaster oven with a temperature probe fitted. A bit of trial and error will eventually get things right, but, purely as an example, my procedure for using lead solder paste (which has a lower melting temperature) is:
Your procedure will no doubt be different, but when you’ve found the magic formula for your setup, it should work every time.
Modified toaster ovens are potentially very dangerous (they have the nickname “fire starters” for good reason). Both when making modifications to the oven and when using it you must know exactly what you are doing and the risks involved. If you are not absolutely sure about what you’re doing, do not be tempted to make your own.
A homemade oven should not be left unattended for a moment while in use.
For soldering through-hole components, see Recipe 20.6.
Desoldering is generally a lot harder than soldering. Unless the component you want to desolder is valuable, you can make your life easier by not worrying about destroying it to get it off the board.
For through-hole two-lead components like resistors, I use the following procedure:
Desoldering DIL ICs is a lot more difficult, but again, if you don’t mind sacrificing the IC, you can chop off its pins and desolder each one separately. Removing the IC as a whole is also possible. Starting with the desoldering braid, get the IC as clean of solder as possible and then push a screwdriver under one end of the IC and gently lever it off, swapping sides with the screwdriver to gradually work the IC out.
Desoldering SMDs is much easier. Just hold a hot-air gun over the component and it will probably just blow away after a while.
Desoldering components is time consuming and you often end up damaging the circuit board pads or the component being removed. Sometimes it’s quicker just to throw it in the trash and start again.
To solder through-hole devices, see Recipe 20.4 and for SMDs Recipe 20.5.
Determine the power the device will need to continuously dissipate and decide the maximum temperature (Tmax) you want the device to reach (less than its absolute maximum in the datasheet). Then use the following formula to find the thermal resistance the heatsink (RØheatsink) will need to provide:
Here, Tambiant is the ambient temperature and RØpackage is the thermal resistance of the component package (1.5° C/W for a TO220 power transistor).
As an example, the datasheet for a TIP120 states that the maximum temperature is 150°C so let’s stay well under this with a Tmax of 130°C. Let’s assume the TIP120 is expected to be used in a circuit where it will generate 10W of heat.
Let’s also assume the ambient temperature of the project’s enclosure is 30°C (very dependent on ventilation).
Plugging these numbers into the formula, we have:
Searching through the heatsink listings in a component catalog, you can find heatsinks with thermal resistances of 8.5C/W or better.
Having done the calculations, test the temperature rise of the device for real and in its final enclosure, as the degree of ventilation in the enclosure will make a big difference. If need be, a fan on the heatsink will increase the heat dissipation considerably.
Heatsinks are available in a great variety of shapes and sizes. Figure 20-23 shows a selection of them.
When attaching a device to a heatsink, you should smear a thin layer of heatsink compound (white paste) onto the device to greatly improve the heat transfer from the device to the heatsink.
For background on power, see Recipe 1.6.
The datasheet for the TIP120 is found here: http://bit.ly/2mHBQy6.
This chapter explains how to use some of the most common electronic tools and test equipment. This includes both instruments for measurement such as multimeters and oscilloscopes and also simulation software that can be useful during design, especially when dealing with analog electronics.
To correctly use a lab power supply, follow these steps:
Aside from a multimeter, the lab power supply is probably the most useful piece of test equipment you can own. Owning one will save you vast amounts of time in the long run because you won’t have to hunt around for batteries and cobble together power supplies and reduce the chance of accidental destruction of components when prototyping.
Figure 21-1 shows a typical lab power supply capable of supplying up to 22V at 5A.
The top line of the display shows the voltage and the bottom, the current. When the output is off, the voltage knob allows you to set the voltage. The current knob sets the maximum current the circuit will be allowed to draw. If the circuit exceeds this, the power supply will automatically decrease the voltage until the current is below the set maximum. In this way, the power supply can be used as:
In addition to a single-output power supply like the one shown in Figure 21-1 dual-output power supplies are also available. These are very useful for analog circuits that require a split-voltage supply.
For information on building your power supplies of various sorts, see Chapter 7.
If you have an autoranging multimeter, simply set the meter to DC voltage and connect the probes across the voltage source.
If you have a multimeter where the range is set manually, determine the maximum voltage you expect to see and set the meter to the range whose maximum is above that value. Then connect the probe leads across the point in the circuit you want to measure.
Once you have established that the voltage is not too high for the range you selected, you can reduce the voltage range for better precision.
Figure 21-2 shows a typical medium-range digital multimeter (DMM).
Although an autoranging multimeter might seem to be superior to a multimeter where the range has to be set, in practice, it can be an advantage to think about what reading you are expecting to see before you take the reading (manually setting the range forces you to do this).
Even very low-cost DMMs generally provide better precision and accuracy than an analog meter. The principle advantage of an analog meter is that you may get a few more clues about what you are measuring if, for example, the tip of the meter’s needle jitters slightly to indicate noise, or you can see the rate of change of voltage as the speed of the meter moving in one direction or another. Some DMMs try to give you the best of both worlds by including an “analog” bargraph-type display in addition to the digital display.
For measuring AC voltage, see Recipe 21.3.
Follow the same procedure as Recipe 21.2 except set the multimeter range to AC volts rather than DC volts.
Since you are measuring AC you will get the same polarity of reading no matter how the leads are placed onto the circuit.
If you are planning to measure high-voltage AC ensure your meter probes are rated for high voltage. Also see Recipe 21.12.
Most DMMs will provide only an approximation of the RMS (root mean square) voltage by rectifying and smoothing it. Higher-end multimeters often include the feature “true RMS.”
For measuring DC voltages, see Recipe 21.2.
To use a multimeter to measure current:
DMMs measure the current flowing by measuring the voltage across a very low-value resistor. This is why you generally have to shift the probe leads to a different socket when measuring current.
If you leave the leads of the multimeter in their current measuring sockets and then go to measure voltage, you will effectively short-out the voltage you are trying to measure. This may damage the circuit or blow a fuse inside the multimeter.
To prevent this, always swap the leads back to their voltage-measuring positions when you are finished measuring current.
If you do blow the fuse in your multimeter, you should be able to open up your multimeter’s case and change the fuse.
To measure voltage, DC, and AC, see Recipe 21.2 and Recipe 21.3, respectively.
Most bench power supplies (Recipe 21.1) will also include an ammeter to tell you how much current is being drawn.
Disconnect the wire so that it is not in use and then use the continuity setting on your multimeter and connect the probes to each end of the thing you want to test.
If you are testing a long multicore cable (i.e., in situ and too long for the multimeter leads to reach both ends), you can connect the separate cores together at one end of the cable and test for continuity at the other, as shown in Figure 21-4.
After DC voltage, continuity is probably the setting you are most likely to use on your multimeter. It is particularly useful if your multimeter makes a beeping noise when the resistance is low enough to indicate continuity. This allows you to move the test probes around without having to look at the multimeter’s screen.
Recipe 21.2 provides an introduction to multimeters.
Nearly all multimeters will have several resistance ranges, and many will have a few capacitance ranges as well.
To use these ranges, simply select the range and attach the component to the test leads. You may find that as with measuring current, the test leads have to be inserted into different sockets on the multimeter when using these measurement ranges.
Some DMMs will offer inductance and frequency ranges, and specialized meters are available for measuring resistance, capacitance, and inductance more accurately than the average DMM can.
Some of these will actually allow you to just attach test leads to any component and the meter will first identify it and then measure its properties. Amazingly, such meters are available on eBay as a kit to assemble yourself for around $10.
When measuring component values, do not be seduced into thinking you are making a very accurate measurement of a component value because of the precision of the result. A reading of 1.23µF may still have a measurement of ±10%, so check the specification for your meter.
Recipe 21.2 provides an introduction to multimeters.
Disconnect the circuit and then use a resistor in parallel with the capacitor to discharge the capacitor until the voltage across it has reached a safe level as indicated by a multimeter set to its DC-voltage setting.
When discharging the capacitor, you can either connect the resistor using insulated crocodile clips, or if access is good enough, bend the resistor leads to the correct gap and then hold the resistor with pliers, carefully touching the capacitor leads as shown in Figure 21-5.
Calculate the resistance and the power rating of the resistor such that the capacitor discharges in a reasonable amount of time without the resistor becoming too hot.
The time constant (RC) is the time in seconds for the capacitor’s voltage to drop to 63.2% of its original value. For example, if you have a 100µF capacitor charged to 300V (you might find this in a photographic flashgun) and you want to discharge the capacitor to a safe 10V, a resistor of 10kΩ would have a time constant of 1 second. So holding it to the capacitor for 1 second would reduce the voltage to 190V, a further second to 120V, and so on. So, after 7 seconds, the voltage would be down to a safe 7.6V.
You can calculate the maximum power the resistor will dissipate as heat using:
which in this case would be 9W. That’s quite a physically big resistor, so failing to do a rough calculation and using a standard ¼W resistor is likely to end in a puff of smoke for the resistor.
Increasing the resistance of the resistor decreases the power requirement of the resistor but will take longer for the capacitor to discharge. It is a good idea to monitor the capacitor’s voltage with a multimeter while you discharge.
A capacitor charged to a high voltage is a dangerous thing, but a high-value capacitor even at low voltages can cause massive currents to flow if its terminals are short circuited and the capacitor has a low ESR.
For a calculation on the energy stored in a capacitor, see Recipe 3.7.
Use a voltage divider comprised of a ladder of equal-value resistors to reduce the voltage to be measured. You will need to take into account the effect that the voltage divider has on the voltage being measured and the input impedance of the multimeter. Also, make sure the resistors used are rated for a high enough voltage.
Figure 21-6 shows how you might measure a voltage of around 5kV using a multimeter with a maximum DC voltage measurement of 1000V and an imput impedance of 10MΩ.
The voltage divider will reduce the input voltage by a factor of 10, making the sums easier. Using 10 equal-value resistors (of 1% or better accuracy) is more likely to result in better accuracy of the system overall if the resistors are from the same batch. The closer the resistors are in value to each other the better the divider.
There are a few other things you need to consider. First, remember to calculate how much the chain of resistors will load the output of the high-voltage source. In this case, a load of 10MΩ across 10kV will result in current flowing at 1mA.
If you plan to measure high voltages, you will need special high-voltage leads that are extremely well insulated to prevent sparking across to your fingers. Your voltage divider should also be boxed and not easy to accidentally touch.
Also, see Recipe 21.12.
The heat power generated by each resistor will be 1kV * 1mA = 1W, which is significant. The temptation is to use higher-value resistors (say 10MΩ) to reduce the power and loading on the voltage source, but this will lead to the impedance of the multimeter becoming significant and acting as two similar-value resistors in parallel, making the reading almost useless.
A typical low-cost or medium-range multimeter will only have an input impedance of 10MΩ, which would result in the voltage reading being reduced by about 10% from the actual voltage.
You can determine the input impedance of your multimeter using the schematic in Figure 21-7.
To determine the input impedance of your multimeter (Z in Figure 21-7):
For example, with a value of R1 of 10MΩ and a 10V supply, my meter gave a Vm reading of 4.7V. Plugging the numbers in you get:
If you plan to measure high voltages on a regular basis, buy a specialist high-voltage voltmeter. In addition to having a very high voltage range, these instruments also usually have very high input impedance and do not load the circuit under test to the extent that the voltage being measured is appreciably altered.
You can also use the preceding method using very high-value resistors if you buy a high-quality multimeter with a buffered input that gives the multimeter an input impedance in the hundreds of MΩ or even GΩ range.
For more information on using a resistor as a voltage divider, see Recipe 2.6.
For regular DC-voltage measurement, see Recipe 21.2.
Figure 21-8 shows a typical low-cost oscilloscope displaying a 1kHz 5V test signal available from a terminal on the front of the oscilloscope.
To look at a signal on an oscilloscope:
Every model of oscilloscope is a little different, so you will need to consult the manual for yours to find the controls used in the preceding instructions.
Most oscilloscopes, including the one shown in Figure 21-8, have two channels that allow you to display two signals at the same time as well as a host of other features such as automatic measurement of frequency and signal amplitude.
When choosing an oscilloscope to buy, you can spend from a few hundred dollars to many thousands of dollars. You pay more for higher frequency range, better displays, and more advanced features. A basic 20MHz oscilloscope like the one shown in Figure 21-8 is a perfectly good starting point and has served me well for many years.
In addition to standalone oscilloscopes, you can also buy “PC scopes” that do not have a screen but rather rely on a USB connection to the PC running the oscilloscope software. As with standalone oscilloscopes, PC scopes are available at all prices and qualities. I prefer a standalone device as it’s always there on my workbench and I don’t have to wait for it to boot up, but many people find the extra features that often come with a PC scope and the bigger and better display of a computer monitor outweigh any disadvantages.
For more information on getting the most from your oscilloscope, get to know the manual really thoroughly. You may find all sorts of features that are not immediately obvious from the controls on the front.
Use a function generator (a.k.a. a signal generator).
The function generator shown in Figure 21-9 is a typical low-cost function generator capable of generating two independent sine, square, or triangle waveforms of up to 20 MHz.
To use the function generator:
If you have a single-supply amplifier or other circuit, if the input signal is swinging negative on each cycle, you may damage the circuit you are testing.
Signal generators with digital controls, like the one shown in Figure 21-9, assume a full AC signal and a DC offset have to be explicitly set.
Figure 21-10 shows the oscilloscope trace for a 10kHz sinewave with an amplitude of 2V peak-to-peak and a DC offset of 2.5V generated by the function.
If you are on a budget, you can make your own oscillator as shown in Recipe 16.5.
Use circuit-simulator software.
A free online circuit simulator is a great way to get started with circuit simulation. The PartSim is one such easy-to-use simulator. Sign up for a PartSim account and then start drawing your schematic in the simulator. Figure 21-11 shows the schematic for the simple RC filter from Recipe 16.3.
In addition to drawing R1 and C1, you can also specify an AC-voltage source to drive it. In this case, as the parameter in Figure 21-11 suggests, the test signal will be a 5V square wave (pulse) with rise and fall times of 1µs, a pulse length of 15µs, and an overall period of 30µs. This corresponds roughly to the 32.7kHz carrier signal of Recipe 16.3.
When you click the Run button you will be prompted to enter some parameters for a simulation as shown in Figure 21-12.
There are various types of simulations that can be run, but in this case we are interested in the “Transient Response.” The Start and Stop times determine how long the simulation will run and the Time Step is the step between each calculated value in the simulation.
When you click Run, you will see a new tab appear in the window with the name “transient response” that shows the result of the simulation as shown in Figure 21-13.
You can see that the output is indeed greatly attenuated by the RC filter.
Simulation is very useful in analog design, not least because it tells you how the circuit should behave, whereas a signal generator and oscilloscope will tell you how just one prototype behaves. A physical prototype has the problem that there may be a fault in its construction or components that causes it to behave differently when you make a second prototype. Simulation will tell you what to expect in a reliable and consistent manner.
In addition to idealized components like resistors, capacitors, and perfect op-amps, simulators like PartSim also have a huge array of “models” for actual components, including specific op-amp models.
PartSim is based on the open source SPICE simulation software; learn more at: http://bwrcs.eecs.berkeley.edu/Classes/IcBook/SPICE/.
Assume that coming into contact with a high voltage will kill you.
Although a little hyperbolic, this statement is a good thing to keep at the front of your mind when working with high voltages. Frankly anything above 50V should scare you. So AC with its fatal combination of high voltage and high availability of current should scare you a lot.
Here are some rules I stick to when working on AC:
According to the American Burn Association:
In the United States, on average of 400 people die from electrocution and 4,400 are injured each year because of electrical hazards.
In addition to the risk of a current flowing through your heart and stopping it, burns caused by your body effectively acting as a heating element as well as arcing sparks are risks associated with high voltages.
For the full American Burn Association report, see: http://www.ameriburn.org/Preven/ElectricalSafetyEducator’sGuide.pdf.
The following tables will help you to find the parts used in this book. Where possible, I have listed product codes for suppliers.
There are now many electronic component suppliers that cater to the maker and electronics hobbyist. Some of the most popular are listed in Table A-1.
| Supplier | Website | Notes |
|---|---|---|
|
Adafruit |
Good for modules |
|
|
DigiKey |
Wide range of components |
|
|
MakerShed |
Good for modules, kits, and tools |
|
|
MCM Electronics |
Wide range of components |
|
|
Mouser |
Wide range of components |
|
|
SeeedStudio |
Interesting low-cost modules |
|
|
SparkFun |
Good for modules |
|
| MonkMakes | http://www.monkmakes.com | Electronic Kits for Raspberry Pi, etc. |
| Pimoroni | Raspberry Pi and Arduino | |
| Polulu | https://www.pololu.com/ | Great for motor controllers and robots |
|
CPC |
UK-based, wide range of components |
|
|
Farnell |
International, wide range of components |
|
|
Maplin |
UK-based, bricks and mortar, Raspberry Pi and Arduino |
|
|
Proto-pic |
UK-based, stock SparkFun, and Adafruit modules |
The other great source for components is eBay.
Searching for components can be time consuming and difficult. The Octopart component search engine can be very helpful for tracking down parts.
Many of the hardware projects in this book use jumper wires of various sorts. Male-to-female leads (to connect the Raspberry Pi GPIO connector to a breadboard) and male-to-male (to make connections on the breadboard) are particularly useful. Female-to-female are occasionally useful for connecting modules directly to GPIO pins. You rarely need leads longer than 3 inches (75mm). Table A-2 lists some jumper wire and breadboard specifications, along with their suppliers.
A handy way to get started with breadboard, jumper wires, and some components to get you started is to buy a starter kit like the Hacking Electronics Kit or Electronics Starter Kit for Raspberry Pi by MonkMakes.com.
| Description | Suppliers |
|---|---|
|
M-M jumper wires |
SparkFun: PRT-08431, Adafruit: 759, DigiKey: PRT-08431-ND |
|
M-F jumper wires |
SparkFun: PRT-09140, Adafruit: 825, DigiKey: PRT-09140-ND |
|
F-F jumper wires |
SparkFun: PRT-08430, Adafruit: 794, DigiKey: PRT-08430-ND |
|
Half-sized breadboard |
SparkFun: PRT-09567 Adafruit: 64, DigiKey: 377-2094-ND |
| Raspberry Leaf (26 pin) | Adafruit: 1772 |
| Raspberry Leaf (40 pin) | Adafruit: 2196 |
| Electronics Starter Kit for Raspberry Pi | Amazon, monkmakes.com |
| Monk Makes Protoboard | Amazon, monkmakes.com/pb |
| Adafruit PermaProto for Pi (half breadboard) | Adafruit: 1148 |
| Adafruit PermaProto for Pi (full breadboard) | Adafruit: 1135 |
| Adafruit PermaProto HAT | Adafruit: 2314, DigiKey: 1528-1370-ND |
| DC barrel jack to screw terminal adapter (female) | Adafruit: 368, DigiKey: 1528-1386-ND |
Table A-3 lists resistors used in this cookbook and some suppliers.
| 10Ω 0.25W resistor | Mouser: 293-10-RC, DigiKey: 10QBK-ND |
| 22Ω 0.25W resistor | Mouser: 293-22-RC, DigiKey: 22QBK-ND |
| 100Ω 0.25W resistor | Mouser: 293-100-RC, DigiKey: 100QBK-ND |
| 120Ω 0.25W resistor | Mouser: 293-120-RC, DigiKey: 120QBK-ND |
| 150Ω 0.25W resistor | Mouser: 293-150-RC, DigiKey: 150QBK-ND |
|
270Ω 0.25W resistor |
Mouser: 293-270-RC, DigiKey: 270QBK-ND |
| 330Ω 0.25W resistor | Mouser: 293-330-RC, DigiKey: 330QBK-ND |
|
470Ω 0.25W resistor |
Mouser: 293-470-RC, DigiKey: 470QBK-ND |
|
1kΩ 0.25W resistor |
Mouser: 293-1k-RC, DigiKey: 1.0kQBK-ND |
|
3.3kΩ 0.25W resistor |
Mouser: 293-3.3k-RC, DigiKey: 3.3kQBK-ND |
|
4.7kΩ 0.25W resistor |
Mouser: 293-4.7k-RC, DigiKey: 4.7kQBK-ND |
| 10kΩ 0.25W resistor | Mouser: 293-10k-RC, DigiKey: 10kQBK-ND |
| 22kΩ 0.25W resistor | Mouser: 293-22k-RC, DigiKey: 22kQBK-ND |
| 33kΩ 0.25W resistor | Mouser: 293-33k-RC, DigiKey: 33kQBK-ND |
| 100kΩ 0.25W resistor | Mouser: 293-100k-RC, DigiKey: 100kQBK-ND |
| 180kΩ 0.25W resistor | Mouser: 293-180k-RC, DigiKey: 180kQBK-ND |
| 1MΩ 0.25W resistor | Mouser: 293-1M-RC, DigiKey: 1.0MQBK-ND |
| 1.8MΩ 0.25W resistor | Mouser: 293-1.8M-RC, DigiKey: 1.8MQBK-ND |
|
10 kΩ trimpot |
Adafruit: 356, SparkFun: COM-09806, Mouser: 652-3362F-1-103LF, DigiKey: 3386P-103TLF-ND |
|
Photoresistor |
Adafruit: 161, SparkFun: SEN-09088, DigiKey: NSL-5152-ND |
| Thermistor T0 of 1k Beta 3800 NTC | Mouser: 871-B57164K102J (note Beta is 3730), DigiKey: 495-75312-ND |
Table A-4 lists resistors and capacitors used in this cookbook and some suppliers.
| 1nF 50V | DigiKey: BC2659CT-ND, Mouser: 594-K102J15C0GF5TH5 |
|
10nF 50V |
DigiKey: BC2662CT-ND, Mouser: 594-K103K15X7RF5UL2 |
| 10nF 1000V | DigiKey: 1255PH-ND, Mouser: 81-RDER73A103K3M1H3A |
| 100nF 50V | DigiKey: 399-4151-ND, Mouser: 594-K104K15X7RF53L2 |
| 100nF 400V | DigiKey: EF4104-ND, Mouser: 581-SR758C104KAATR1 |
| 220nF 50V | DigiKey: BC2678CT-ND, Mouser: 594-K224K20X7RF5TH5 |
| 330nF 50V | DigiKey: 399-9882-1-ND, Mouser: 80-C330C334K5R |
| 680nF 50V | DigiKey: 445-8519-ND, Mouser: 81-RCER71H684K2M1H3A |
| 1µF 16V | DigiKey: 445-8614-ND, Mouser: 539-SN010M025ST |
| 4.7µF 16V | DigiKey: 493-10248-1-ND, Mouser: 647-UMA1C4R7MCD2 |
| 10µF 16V | DigiKey: 493-10245-1-ND, Mouser: 667-ECE-A1CKS100 |
| 100µF 16V | DigiKey: P16379CT-ND, Mouser: 598-107CKS016M |
| 220µF 25V | DigiKey: 493-6082-ND, Mouser: 667-EEU-FM1E221 |
| 470µF 35V | DigiKey: 493-12724-1-ND, Mouser: 667-ECA-1VM471 |
| 1000µF 25V | DigiKey: 493-12690-1-ND, Mouser: 667-EEU-FC1E102L |
| 390nH 100mA | DigiKey: 445-1010-1-ND, Mouser: 542-9230-10-RC |
| 4.7µH 250mA | DigiKey: 495-5567-1-ND, Mouser: 70-IR04RU4R7K |
| 22uH 3A Inductor | DigiKey: 495-5590-1-ND, Mouser: 580-12RS223C |
| 33uH 3A Inductor | DigiKey: 495-5705-1-ND, Mouser: 963-LHL13NB330K |
Table A-5 lists transistors and diodes used in this cookbook and some suppliers.
|
FQP30N06L N-channel logic-level MOSFET transistor |
Mouser: 512-FQP30N06L, SparkFun: COM-10213, DigiKey: FQP30N06L-ND |
| FQP27P06 P-channel MOSFET transistor | SparkFun: COM-10349, Mouser: 512-FQP27P06, DigiKey: FQP27P06-ND |
|
2N3904 NPN bipolar transistor |
SparkFun: COM-00521, Adafruit: 756, Mouser: 512-2N3904BU, DigiKey: 2N3904TAFSCT-ND |
| 2N3906 PNP bipolar transistor | SparkFun: COM-00522, Mouser: 512-2N3906TA, DigiKey: 2N3906-APCT-ND |
| TIP120 Darlington transistor | Adafruit: 976, CPC: SC10999, Mouser: 511-TIP120, DigiKey: TIP120-ND |
| 2N7000 MOSFET transistor | Mouser: 512-2N7000, CPC: SC06951, DigiKey: 2N7000TACT-ND |
| STGF3NC120HD IGBT | Mouser: 511-STGF3NC120HD, DigiKey: 497-4353-5-ND |
| IRG4PC30UPBF IGBT | Mouser: 942-IRG4PC30UPBF |
|
1N4001 diode |
Mouser: 512-1N4001, SparkFun: COM-08589, Adafruit: 755, DigiKey: 1N4001DICT-ND |
|
1N4004 diode |
Mouser: 512-1N4004, DigiKey: 1N4004FSCT-ND |
| 1N4007 diode (1000V) | Mouser: 821-1N4007, DigiKey: 1N4007FSCT-ND |
| 1N4148 diode | Mouser: 512-1N4148, DigiKey: 1N4148FS-ND |
| 1N5819 Schottky diode |
Mouser: 512-1N5819, DigiKey: 1N5819FSCT-ND |
| 1N5919 5.6V Zener diode | Mouser: 863-1N5919BG, DigiKey: 1N5919BGOS-ND |
| BT136 TRIAC | Mouser: 583-BT136, DigiKey: 568-12097-5-ND |
Figure A-1 shows the pinouts for the transistors listed in this section.
Table A-6 lists ICs used throughout this cookbook and some suppliers. These are listed in alphabetical order by part name.
| 74HC00 quad NAND | DigiKey: 296-1563-5-ND, Mouser: 595-SN74HC00N |
| 74HC4017 counter decoder | DigiKey: 296-25989-5-ND, Mouser: 595-CD74HC4017E |
| 74HC4094 shift register | DigiKey: 296-26002-5-ND , Mouser: 595-CD74HC4094E |
| 74HC590 counter | DigiKey: 296-1599-5-ND, Mouser: 595-SN74HC590AN |
| CD4047 oscillator | DigiKey: 296-2053-5-ND, Mouser: 595-CD4047BEE4 |
|
DS18B20 temperature sensor |
SparkFun: SEN-00245, Adafruit: 374, Mouser: 700-DS18B20, CPC: SC10426, DigiKey: DS18B20+-ND |
|
L293D motor driver |
SparkFun: COM-00315, Adafruit: 807, Mouser: 511-L293D, CPC: SC10241, DigiKey: 497-2936-5-ND |
| LM2596-5V switcher | DigiKey: LM2596T-5.0/NOPB-ND, Mouser: |
| LM311 comparator | DigiKey: 296-1389-5-ND, Mouser: 926-LM311N/NOPB |
| LM317 adjustable voltage regulator | DigiKey: LM317AHVT-ND , Mouser: 595-LM317KCSE3 |
| LM321 op-amp | DigiKey: LM321MFX/NOPBCT-ND, Mouser: 926-LM321MF/NOPB |
| LM741 op-amp | DigiKey: LM741CNNS/NOPB-ND, Mouser: 926-LM741CN/NOPB |
|
LM7805 voltage regulator |
SparkFun: COM-00107, Adafruit: 2164, Mouser: 511-L7805CV, CPC: SC10586, DigiKey:497-1443-5-ND |
| LM78L12 voltage regulator | DigiKey: LM78L12ACZFS-ND, Mouser: 512-LM78L12ACZ |
| LM79L12 voltage regulator | DigiKey: LM79L12ACZ/NOPB-ND, Mouser: 926-LM79L12ACZ/NOPB |
| MAX2606 VCO | DigiKey: MAX2606EUT+TCT-ND , Mouser: 700-MAX2606EUTT |
|
MCP3008 eight-channel ADC IC |
Adafruit: 856, Mouser: 579-MCP3008-I/P, CPC: SC12789, DigiKey: MCP3008-I/P-ND |
| MCP73831 LiPo charger IC | DigiKey: MCP73831T-2DCI/OTCT-ND, Mouser: 579-MCP73831T5ACIOT |
| NE555 timer | SparkFun: COM-09273, DigiKey: 296-1411-5-ND, Mouser: 595-NE555P |
| OPA365 op-amp | DigiKey: 296-20645-1-ND, Mouser: 595-OPA365AIDBVR |
| TDA7052 1W power amp | DigiKey: 568-1138-5-ND, Mouser: 771-TDA7052ATN2112 |
| TLV2770 op-amp | DigiKey: 296-1897-5-ND, Mouser: 595-TLV2770IP |
| TPA3122D2 15W power amp | DigiKey: 296-23375-5-ND , Mouser: 595-TPA3122D2N |
|
TMP36 temperature sensor |
SparkFun: SEN-10988, Adafruit: 165, Mouser: 584-TMP36GT9Z, CPC: SC10437, DigiKey: TMP36GT9Z-ND |
| TPS61070 boost converter | DigiKey: 296-17151-1-ND, Mouser: 595-TPS61070DDCR |
|
ULN2803 Darlington driver IC |
SparkFun: COM-00312, Adafruit: 970, Mouser: 511-ULN2803A, CPC: SC08607, DigiKey: 497-2356-5-ND |
| WS2812 pixel chip | DigiKey: 28085-ND |
| MOC3032 opto-isolator | DigiKey: MOC3032M-ND, Mouser: 512-MOC3032M |
Figure A-2 shows the pinouts for the ICs listed in this section.
Table A-7 lists opto-electronic components used throughout this cookbook and some suppliers.
|
5mm red LED |
SparkFun: COM-09590, Adafruit: 299, Mouser: 630-HLMP-3301, DigiKey: 160-1853-ND |
|
RGB common cathode LED |
SparkFun: COM-11120, Mouser: 713-104990023, eBay |
|
TSOP38238 IR sensor |
SparkFun: SEN-10266, Adafruit: 157 |
| 4-digit 7-segment common cathode LED display | DigiKey: 67-1450-ND |
Table A-8 lists the modules used in this cookbook and other modules I like.
|
Arduino Uno |
SparkFun: DEV-11021, Adafruit: 50, CPC: A000066, DigiKey: 1050-1024-ND |
| Raspberry Pi3 | Adafruit: 3055, DigiKey: 1690-1000-ND |
|
Level converter, four-way |
SparkFun: BOB-11978, Adafruit: 757 |
|
Level converter, eight-way |
Adafruit: 395 |
|
LiPo boost converter/charger |
SparkFun: PRT-11231 |
|
PowerSwitch tail |
Adafruit: 268 |
| Monk Makes ServoSix board | monkmakes.com, Amazon |
|
16-channel servocontroller |
Adafruit: 815 |
|
Motor driver 1A dual |
SparkFun: ROB-09457 |
|
RasPiRobot board V3 |
Adafruit: 1940, Amazon |
|
PIR motion detector |
Adafruit: 189 |
|
4x7-segment LED with I2C backpack |
Adafruit: 878 |
|
Bicolor LED square-pixel matrix with I2C backpack |
Adafruit: 902 |
|
16 x 2 HD44780 compatible LCD module |
SparkFun: LCD-00255, Adafruit: 181 |
| SSD1306-based 0.96 or 1.2in OLED display | eBay |
| Stepper motor HAT | Adafruit: 2348 |
| 16-channel PWM HAT | Adafruit: 2327 |
| Squid Button | monkmakes.com, Amazon |
| Raspberry Squid RGB LED | monkmakes.com, Amazon |
| I2C OLED display 128x64 pixels | eBay |
| Adafruit Lipo charger module | Adafruit: 1905 |
| SparkFun LiPo charger module | SparkFun: PRT-10217 |
| CC1101 RF transceiver module | eBay |
Table A-9 lists miscellaneous tools and components used in this cookbook and some suppliers.
|
1200mAh LiPo battery |
Adafruit: 258 |
|
5V relay |
SparkFun: COM-00100 |
|
Standard servomotor |
SparkFun: ROB-09065, Adafruit: 1449 |
| 9g mini servomotor | Adafruit: 169 |
|
5V 1A power supply |
Adafruit: 276 |
|
Low power 6V DC motor |
Adafruit: 711 |
|
0.1-inch header pins |
SparkFun: PRT-00116, Adafruit: 392 |
|
5V 5-pin unipolar stepper motor |
Adafruit: 858 |
|
12V, 4-pin bipolar stepper motor |
Adafruit: 324 |
|
Tactile push switch |
SparkFun: COM-00097, Adafruit: 504 |
|
Miniature slide switch |
SparkFun: COM-09609, Adafruit: 805 |
|
Rotary encoder (quadrature) |
Adafruit: 377 |
|
4x3 keypad |
SparkFun: COM-08653 |
|
Piezo buzzer |
SparkFun: COM-07950, Adafruit: 160 |
| Reed switch | Adafruit: 375 |
| Loudspeaker 8Ω 1W | Adafruit: 1313 |
There are many choices here. I would always say start with low-cost equipment and upgrade as and when you feel the need. After all, if you were learning the violin, it would be foolish to start with a Stradivarius!
The items listed in Table A-10 are similar to those I use every day and serve as a guide to help you get started. You should shop around; there are some great bargains to be had.
|
Basic multimeter |
Monk Makes Hacking Electronics Kit, eBay |
| Better multimeter (Tenma 72-7725) | Amazon, eBay |
| Entry-level oscilloscope | Adafruit: 681 |
| Bench power supply | DigiKey: BK1550-220V-ND |
| Good soldering station | SparkFun: TOL-11704 |
| Fume extractor | eBay |
| Thermal heatsink compound | eBay |
Figure B-1 shows the pinout for the Arduino Uno R3.
Figure B-2 shows the pinout for the Arduino Pro Mini.
Figure C-1 shows the pinouts for the current 40-pin GPIO Raspberry Pi.
If you have an Raspberry Pi, it is most likely the model B rev. 2 board shown in Figure C-2.
The very first released version of the Raspberry Pi model B (rev. 1) has some minor pinout differences from the rev. 2 that followed. This is the only version of the Raspberry Pi that is not compatible with later pinouts. The incompatible pins that changed are highlighted in bold in Figure C-3.
Table D-1 lists the most common units used in electronics along with the typical ranges of those units you might find in practice.
| Property | Unit | Typical range |
|---|---|---|
| Current | A (Ampere) | 100nA to 100A |
| Voltage | V (Volt) | 1mV to 1000V |
| Resistance | Ω (Ohm) | 10mΩ to 20MΩ |
| Energy | J (Joule) | 1J to 1MJ |
| Watt | W (Watt) | 1mW to 10kW |
| Capacitance | F (Farad) | 10pF to 10F |
| Inductance | H (Henry) | |
| Frequency | Hz (Hertz) |
sound 20Hz to 20kHz radio 3kHz to 300GHz |
Table D-2 shows the unit prefixes applied to electronic and other units. You will sometimes find R used in place of Ω and u in place of µ.
| Prefix | Multiplier | Scientific |
|---|---|---|
| p (pico) | 1/1,000,000,000,000 | 10E-12 |
| n (nano) | 1/1,000,000,000 | 10E-9 |
| µ (micro) | 1/1,000,000 | 10E-6 |
| m (milli) | 1/1,000 | 10E-3 |
| k (kilo) | 1,000 | 10E3 |
| M (mega) | 1,000,000 | 10E6 |
| G (giga) | 1,000,000,000 | 10E9 |
The animal on the cover of Electronics Cookbook is an elephantnose fish (Gnathonemus petersii). This species is native to West and Central Africa, where it favors muddy and heavily-vegetated areas of rivers. Its Latin name petersii most likely refers to German naturalist Wilhelm Peters.
The elephantnose fish is oblong-shaped and typically dark brown or black in color. Its “trunk”—the signature feature from which the species’s common name is derived—is not actually a nose, but an extension of the mouth that is covered in electroreceptors. Gnathonemus petersii produces a weak electric field that is used to probe for food, navigate through murky waters, and detect prey. It also lends itself to communicating with other fish and finding mates.
Many of the animals on O’Reilly covers are endangered; all of them are important to the world. To learn more about how you can help, go to animals.oreilly.com.
The cover image is from Lydekker’s Royal Natural History. The cover fonts are URW Typewriter and Guardian Sans. The text font is Adobe Minion Pro; the heading font is Adobe Myriad Condensed; and the code font is Dalton Maag’s Ubuntu Mono.