Silicon ChipMax’s Cool Beans - December 2024 SILICON CHIP
  1. Contents
  2. Publisher's Letter: Coming up next year
  3. Feature: The Fox Report by Barry Fox
  4. Feature: Net Work by Alan Winstanley
  5. Project: Raspberry Pi Clock Radio, Part 1 by Stefan Keller-Tuberg
  6. Feature: Max’s Cool Beans by Max the Magnificent
  7. Project: VGA PicoMite by Geoff Graham & Peter Mather
  8. Feature: Using Low-cost Electronic Modules - 6GHz Digital Attenuator by Jim Rowe
  9. Feature: All About Capacitors by Nicholas Vinen
  10. Feature: Techno Talk by Max the Magnificent
  11. Feature: Circuit Surgery by Ian Bell
  12. Project: Secure Remote Switch, Part 1 by John Clarke
  13. Subscriptions
  14. Review: Using Electronic Modules - ZPB30A1 60W DC Load by Jim Rowe
  15. Project: Multi-Channel Volume Control, Part 2 by Tim Blythman
  16. Back Issues
  17. PartShop
  18. Market Centre
  19. Advertising Index
  20. Back Issues

This is only a preview of the December 2024 issue of Practical Electronics.

You can view 0 of the 80 pages in the full issue.

Articles in this series:
  • The Fox Report (July 2024)
  • The Fox Report (September 2024)
  • The Fox Report (October 2024)
  • The Fox Report (November 2024)
  • The Fox Report (December 2024)
  • The Fox Report (January 2025)
  • The Fox Report (February 2025)
  • The Fox Report (March 2025)
  • The Fox Report (April 2025)
  • The Fox Report (May 2025)
Articles in this series:
  • Win a Microchip Explorer 8 Development Kit (April 2024)
  • Net Work (May 2024)
  • Net Work (June 2024)
  • Net Work (July 2024)
  • Net Work (August 2024)
  • Net Work (September 2024)
  • Net Work (October 2024)
  • Net Work (November 2024)
  • Net Work (December 2024)
  • Net Work (January 2025)
  • Net Work (February 2025)
  • Net Work (March 2025)
  • Net Work (April 2025)
Articles in this series:
  • Max’s Cool Beans (April 2024)
  • Max’s Cool Beans (May 2024)
  • Max’s Cool Beans (June 2024)
  • Max’s Cool Beans (July 2024)
  • Max’s Cool Beans (August 2024)
  • Max’s Cool Beans (September 2024)
  • Max’s Cool Beans (October 2024)
  • Max’s Cool Beans (November 2024)
  • Max’s Cool Beans (December 2024)
Articles in this series:
  • (November 2020)
  • Techno Talk (December 2020)
  • Techno Talk (January 2021)
  • Techno Talk (February 2021)
  • Techno Talk (March 2021)
  • Techno Talk (April 2021)
  • Techno Talk (May 2021)
  • Techno Talk (June 2021)
  • Techno Talk (July 2021)
  • Techno Talk (August 2021)
  • Techno Talk (September 2021)
  • Techno Talk (October 2021)
  • Techno Talk (November 2021)
  • Techno Talk (December 2021)
  • Communing with nature (January 2022)
  • Should we be worried? (February 2022)
  • How resilient is your lifeline? (March 2022)
  • Go eco, get ethical! (April 2022)
  • From nano to bio (May 2022)
  • Positivity follows the gloom (June 2022)
  • Mixed menu (July 2022)
  • Time for a total rethink? (August 2022)
  • What’s in a name? (September 2022)
  • Forget leaves on the line! (October 2022)
  • Giant Boost for Batteries (December 2022)
  • Raudive Voices Revisited (January 2023)
  • A thousand words (February 2023)
  • It’s handover time (March 2023)
  • AI, Robots, Horticulture and Agriculture (April 2023)
  • Prophecy can be perplexing (May 2023)
  • Technology comes in different shapes and sizes (June 2023)
  • AI and robots – what could possibly go wrong? (July 2023)
  • How long until we’re all out of work? (August 2023)
  • We both have truths, are mine the same as yours? (September 2023)
  • Holy Spheres, Batman! (October 2023)
  • Where’s my pneumatic car? (November 2023)
  • Good grief! (December 2023)
  • Cheeky chiplets (January 2024)
  • Cheeky chiplets (February 2024)
  • The Wibbly-Wobbly World of Quantum (March 2024)
  • Techno Talk - Wait! What? Really? (April 2024)
  • Techno Talk - One step closer to a dystopian abyss? (May 2024)
  • Techno Talk - Program that! (June 2024)
  • Techno Talk (July 2024)
  • Techno Talk - That makes so much sense! (August 2024)
  • Techno Talk - I don’t want to be a Norbert... (September 2024)
  • Techno Talk - Sticking the landing (October 2024)
  • Techno Talk (November 2024)
  • Techno Talk (December 2024)
  • Techno Talk (January 2025)
  • Techno Talk (February 2025)
  • Techno Talk (March 2025)
  • Techno Talk (April 2025)
  • Techno Talk (May 2025)
  • Techno Talk (June 2025)
Articles in this series:
  • Circuit Surgery (April 2024)
  • STEWART OF READING (April 2024)
  • Circuit Surgery (May 2024)
  • Circuit Surgery (June 2024)
  • Circuit Surgery (July 2024)
  • Circuit Surgery (August 2024)
  • Circuit Surgery (September 2024)
  • Circuit Surgery (October 2024)
  • Circuit Surgery (November 2024)
  • Circuit Surgery (December 2024)
  • Circuit Surgery (January 2025)
  • Circuit Surgery (February 2025)
  • Circuit Surgery (March 2025)
  • Circuit Surgery (April 2025)
  • Circuit Surgery (May 2025)
  • Circuit Surgery (June 2025)
Items relevant to "Secure Remote Switch, Part 1":
  • Secure Remote Mains Switch receiver PCB [10109211] (AUD $7.50)
  • Secure Remote Mains Switch transmitter PCB [10109212] (AUD $2.50)
  • PIC16F1459-I/P programmed for the Secure Remote Mains Switch receiver (1010921R.HEX) (Programmed Microcontroller, AUD $10.00)
  • PIC16LF15323-I/SL programmed for the Secure Remote Mains Switch transmitter (1010921A.HEX) (Programmed Microcontroller, AUD $10.00)
  • Firmware and ASM source code for the Secure Remote Mains Switch [1010921A/R] (Software, Free)
  • Secure Remote Mains Switch PCB patterns (PDF download) [10109211/2] (Free)
  • Front panel label and drilling diagrams for the Secure Remote Mains Switch (Panel Artwork, Free)
Articles in this series:
  • Secure Remote Mains Switch, Part 1 (July 2022)
  • Secure Remote Mains Switch, Part 2 (August 2022)
  • Secure Remote Switch, Part 1 (December 2024)
  • Secure Remote Mains Switch, part two (January 2025)
Items relevant to "Multi-Channel Volume Control, Part 2":
  • Multi-channel Volume Control volume PCB [01111221] (AUD $5.00)
  • Multi-channel Volume Control control PCB [01111222] (AUD $5.00)
  • Multi-channel Volume Control OLED PCB [01111223] (AUD $3.00)
  • PIC16F18146-I/SO programmed for the Multi-Channel Volume Control [0111122B.HEX] (Programmed Microcontroller, AUD $10.00)
  • PIC16F15224-I/SL programmed for the Multi-Channel Volume Control [0111122C.HEX] (Programmed Microcontroller, AUD $10.00)
  • Pulse-type rotary encoder with pushbutton and 18t spline shaft (Component, AUD $3.00)
  • 0.96in cyan OLED with SSD1306 controller (Component, AUD $10.00)
  • 2.8-inch TFT Touchscreen LCD module with SD card socket (Component, AUD $25.00)
  • Multi-channel Volume Control control module kit (Component, AUD $50.00)
  • Multi-channel Volume Control volume module kit (Component, AUD $55.00)
  • Multi-channel Volume Control OLED module kit (Component, AUD $25.00)
  • Firmware (C and HEX) files for the Multi-Channel Volume Control (Software, Free)
  • Multi-channel Volume Control PCB patterns (PDF download) [01111221-3] (Free)
Articles in this series:
  • Multi-Channel Volume Control, Pt1 (December 2023)
  • Multi-Channel Volume Control Part 2 (January 2024)
  • Multi-Channel Volume Control, part one (November 2024)
  • Multi-Channel Volume Control, Part 2 (December 2024)
Max’s Cool Beans By Max the Magnificent Arduino Bootcamp – Part 24 (it’s time to get serial) Y ou know how people sometimes tell you, “I’ve got good Before we dive headfirst into the fray with gusto and abandon, following our previous column in the November issue, several readers emailed me, moaning and groaning that the puzzle I posed is unsolvable. “Oh, ye of little faith” is all I can say. Well, not quite; I follow this with, “Watch and learn, Grasshopper”. As you may recall, and as illustrated in Fig.1(a), our problem involves a black box with three inputs (A, B, C) and three outputs (NotA, NotB, NotC). Each output is to be the logical negation of its corresponding input, so a 0 on A results in a 1 on NotA, and vice versa; the situation for the other input-output pairs is similar. We are permitted by those who don the undergarments of authority to use only two NOT gates along with as many 2- and 3-input AND and OR gates as we wish. There are various ways in which we can tackle this problem. The solution shown in Fig.1(b) was generated by my friend George Harper. Personally, I think George’s resolution to this conundrum is awe-inspiring in its elegance. I should note that George is using a pseudo-language of his own devising to represent this solution (most computer languages won’t allow us to start a variable name with a numerical character, for example). Also, George employs ‘&’, ‘|’, and ‘!’ characters in his lution is layered. Equation #3 means, Boolean equations to represent AND, “the internal node 1one will be 1 OR, and NOT functions, respectively. if both 0or1ones is 1 and any of This really is cool. Once we’ve speci- the ABC inputs are 1”. The physical fied the names of our input and output implementation of this expression will signals, we move onto the Boolean require only a 2-input AND gate and a 3-input OR gate. equations describing the internal nodes. Similarly, Equation #4 tells us, “the These equations can be transferred onefor-one into corresponding logic gates. internal node 1or3ones will be 1 if In the following discussions, “#n” 1ones is 1 or all of the ABC inputs are refers to the line number comments 1”. The physical implementation of this associated with the internal nodes. All expression requires only a 2-input OR gate and a 3-input AND gate. of this is pretty much self-explanatory. Equation #5 is similar in concept Remember that 0 and 1 equate to the Boolean concepts of false and true, to equation #2. Since the only posrespectively. sibilities are for 0, 1, 2 or all 3 of the This means we can read equation #1 inputs to be 1, then if 1or3ones is 1 as saying, “internal node 2or3ones (true), 0or2ones must be 0 (false), will be 1 (true) if any two or all three and vice versa. We can achieve this of inputs ABC are 1; otherwise, it will be by inverting the output of 1or3ones 0 (false).” The physical implementa- with our second and final NOT gate. tion of this expression requires three Using equations #6 and #7 to gen2-input AND gates and one 3-input erate the remaining internal nodes, 0ones and 2ones, is easy peasy lemon OR gate. Similarly, equation #2 tells us, “the squeezy. The physical implementation value of internal node 0or1ones of each requires just a single 2-input is NOT the value of internal node AND gate. 2or3ones”. Another way saying that The key takeaway from all this is that is, “internal node 0or1ones will be 0 if we now have three extremely useful 2or3ones is 1; otherwise, it will be 1”. signals: 0ones , 1one , and 2ones , An alternative approach to wrap which tell us if none, only one, or our brains around this part of the problem is A NotA that there are only four Black Box B NotB broad possibilities: all C NotC the inputs are 0, one of the inputs is 1, two of (a) The problem the inputs are 1, or all three of the inputs are 1. Inputs: Since we know that A, B, C; 2or3ones will be 1 if Outputs: two or three of the inputs NotA, NotB, NotC; are 1, it will be 0 only if Internal Nodes: none or only one of the 2or3ones = ( (A & B) | (A & C) | (B & C) ); // #1 inputs are 1. 0or1ones = !(2or3ones); // #2 1one = 0or1ones & (A | B | C); // #3 Since we generate 1or3ones = 1one | (A & B & C); // #4 our 0or1ones value 0or2ones = !(1or3ones); // #5 simply by inverting 0ones = 0or2ones & 0or1ones; // #6 2ones = 0or2ones & 2or3ones; // #7 whatever value is present on 2or3ones, the Equations for Outputs: implementation of this NotA = 0ones | (1one & (B | C)) | (2ones & (B & C)); NotB = 0ones | (1one & (A | C)) | (2ones & (A & C)); expression will only reNotC = 0ones | (1one & (A | B)) | (2ones & (A & B)); quire one of our two NOT (b) The solution gates (“our preciouses”). Fig.1: proof that there is a solution to the problem! As we can see, this so- Practical Electronics | December | 2024 17 news and bad news, which do you want first?” Don’t worry. I’m not going to say that. What I will say is, “I have happy news and sad news”. Also, I’m not going to give you a choice because we’ll start with the opposite of happy news, which is that this is to be the last in our current collection of Arduino Bootcamp columns ( ). Meanwhile, the opposite of sad news is that we are going to start a new series of Weird and Wonderful Arduino Projects, which will use many of the techniques we’ve explored together, including some we are about to discover in this column ( ️). But first… 😞 ☺ B or NotB, that is the question only two of our three ABC inputs are 1, respectively. Having access to these signals means we now have sufficient information at our disposal to generate our three output values. This is where things get so clever I’m tempted to squeak with excitement. We want an output to be 1 only if its corresponding input is 0. Pick any output. This output will be 1 if 0ones is 1 (meaning all the inputs are 0), or if 1one is 1 and either of the other inputs is 1 (meaning this input is 0), or if 2ones is 1 and both the other inputs are 1 (again meaning this input is 0). This is reflected in our three output equations. Every time I look at this solution, a smile comes to my face, and I think, “Wow! That. Is. So. Ingenious!” Pondering our persisting poser Do you remember the other puzzle I posed in last month’s column? I said to assume our four 7-segment lightemitting diode (LED) displays are only ever going to be used to implement a clock. Also, to assume that this clock can support both 12- and 24-hour modes and that we are suppressing any leading zeros in the most-significant hours digit (we introduced this concept in PE, August 2024). Although we didn’t explicitly state it, let’s also assume that we are going to exclude the displays’ decimal point segments from these discussions. Based on all these assumptions, what would be the maximum number of segments we might see active at the same time? And what would be the ideal value for our current-limiting resistors to obtain the maximum possible segment current values, assuming a total allocation of 350mA to power all four of our displays? I bet this is not as easy as you think. If you haven’t already done so, why don’t you take a stab at this now, and then compare it to my answer, which I’ll present at the end of this column. Lest we forget As per our previous column, the current implementation of our clock employs four latching CD4511 BCD (binary-coded decimal) to 7-segment decoders. This means each of our 7-segment displays has its own BCD decoder, each of which latches (stores) the BCD value we wish it to display. As usual, you can download a PDF of our existing ensemble (named CBDec24-brd-01.pdf). And, as usual, all the files mentioned in this column are available from the December 2024 download page on the PE website: https://pemag.au/link/ac1m Since we are no longer multiplexing the displays, they maintain a constant 18 brightness, irrespective of the number we decide to use. However, there are two disadvantages to this scenario. The first is that, in addition to the 4 ABCD signals driving the inputs to the BCD decoders, each decoder also requires its own LE (latch enable) signal. Since we are currently using four displays, this means we are consuming 4 + 4 = 8 of our Arduino Uno’s 12 precious digital input/output (I/O) pins. Every time we add a digit, we will lose another pin ( ). The second disadvantage is that BCD decoders don’t control the dp (decimal point) segments on 7-segment displays. As we will come to see, these segments can be employed to convey all sorts of useful information. So, if we decide we want to use our dp segments, we will have to control them individually, which means losing another pin for each display. In the case of our current 4-digit clock, this means we will end up consuming 4 + 4 + 4 = 12 digital pins, leaving us with no pins available to implement other functions, like driving a buzzer, for example. 😞 Shift over Happily, there is another solution open to us. One that will potentially allow us to drive as many 7-segment displays as we wish—including their dp segments—using only 3, 4, or 5 of the Arduino’s digital I/Os, depending on our implementation. In an earlier column (PE, September 2024), we introduced the concept of memory elements (or ‘registers’) called D-type flip-flops. We also described how these little scamps could be connected to form a serial in, parallel out (SIPO) shift register. Suppose we form an 8-bit ‘bare bones’ SIPO shift register as illustrated in Fig.2(a). All the registers share a common clock signal, which we’ve called SRCLK (shift register clock). The data input to the first register in the chain is called SER (serial data in). The output from each register drives the next register in the chain. When a rising edge (a 0 to 1 transition) is applied to SRCLK, the value on SER will be loaded into the first register. At the same time, the existing contents of the first register will be loaded into the second, the contents of the second register will be loaded into the third, and so on down the chain. One way to visualize this is as a line of eight people passing objects to each other when someone shouts “Now!”. So, to load an 8-bit value into our shift register, we first place the first a 0 or 1 on the SER input, then apply a positive-going pulse to the SRCLK input. We then place the next 0 or 1 on the SER input, apply another positivegoing pulse to the SRCLK input, and so forth until all eight bits have been loaded. This means we need to load the last bit first and the first bit last, if you see what I mean. The outputs from all eight registers, named QA through QH in our illustration, are presented to the outside world, where they can be used to drive all sorts of things like… well, like a 7-segment display. In our case, we are going to use the Q A through Q G outputs to drive the corresponding a through g segments on our display, while the QH output can be used to control our dp segment. Now, this is the clever bit. Assume our 8-bit shift register is presented and packaged as an integrated circuit (IC). We can daisy chain multiple devices together to form a longer shift register. In this case, the SRCLK signal would be used to drive all the chips. Meanwhile, the QH output from the first chip could be used to drive the SER input to the second device, and so on down the line. Returning to Fig.2(a), observe that we’ve taken a copy of the QH output that we’ve called QH’. It’s this QH’ output that we will use to drive the next device in the chain. The reason for our doing this will become apparent shortly. Just to keep things simple, we will refer to these outputs more concisely as abcdefgh in the discussions below. The main point to note at this stage is that, by daisy-chaining a bunch of these devices together, we can now control as many displays as we wish using only two of our Arduino’s digital I/O pins. Pretty cool, eh? All clear! Suppose we decide to daisy chain four 8-bit SIPO shift registers and use them to drive our four 7-segment displays. Further suppose we wish to clear the registers, loading each element with a logic 0 value. In the case of the bare-bones implementation shown in Fig.2(a), we could achieve this by presenting a 0 to the SER input of the first register, then applying 32 clock pulses to the SRCLK input. Our Arduino Uno’s system clock is running at 16MHz (16 million cycles a second), so loading our shift register with 0s will take only an imperceivable fraction of a second. However, since we often wish to clear the contents of our shift registers, and some applications will involve very long shift register chains, it’s common to provide a SRCLR (shift register clear) input, as illustrated in Fig.2(b). It’s also Practical Electronics | December | 2024 SER SER SER SER OE RCLK QA SRCLK QA SRCLK SRCLR RCLK QA SRCLK QA SRCLK SRCLR SRCLR QB QB QB QB QC QC QC QC QD QD QD QD QE QE QE QE QF QF QF QF QG QG QG QH QH QH QH’ QH’ (a) Bare bones (b) With clear (c) Registered outputs (d) Output enable QH’ QH’ Q G QH Fig.2: four different flavours of eight-bit SIPO (serial in, parallel out) shift register. common for this signal to be active-low, as shown by the bar over its name. Once again, the SRCLR signal from our microcontroller will be connected to all the shift registers in the chain. our shift register to drive the abcdefg and dp segments on our display, respectively. So, to display ‘4’, we need a value of 01100110 in our shift register. The problem is that we need to shift this value in through the SER input A fly in the soup using eight clocks (Fig.4). Unfortunately, there’s a fly in the Just for giggles, let’s assume we power soup and an elephant in the room (I up with our shift register containnever metaphor I didn’t like). Suppose ing random/unknown 0 and 1 values we connect the outputs from our 8-bit (shown as red question marks in Fig.4). shift register to a 7-segment display (via While we are in the process of clocking current-limiting resistors, of course). our new values in, our display will Now suppose we wish to display respond as shown in Fig.5. the number ‘4’. This requires segments All this will take place in a fraction ade to be turned off, while segments of a second. If you blink, you’ll miss it, bcfg will need to be turned on as il- which means this may not be particulustrated in Fig.3. larly important if we wish to update Remember that we are planning on our display relatively infrequently. using the abcdefg and h outputs from However, if we are constantly loading new values into our shift register, even if the Clock a b c d e f g h a values are the same (like Start ? ? ? ? ? ? ? ? repeatedly displaying ‘4’, #1 0 ? ? ? ? ? ? ? f b ‘4’, ‘4’…), we could end g c e d dp Fig.3: displaying a ‘4’. #2 #3 #4 #5 #6 #7 #8 1 0 ? ? ? ? ? ? 1 1 0 ? ? ? ? ? 0 1 1 0 ? ? ? ? 0 0 1 1 0 ? ? ? 1 0 0 1 1 0 ? ? 1 1 0 0 1 1 0 ? 0 1 1 0 0 1 1 0 Fig.4: loading our 8-bit value. Practical Electronics | December | 2024 Unknown a f g e up with blurred, ‘ghosting’ effects on our display (the concept of ghosting was introduced in PE, July 2024). The solution is to add an additional set of D-type flip-flops as illustrated in Fig.2(c). These output registers are controlled by their own clock, which we’ve called RCLK (register clock). We are showing RCLK as being positiveedge triggered, so these registers will be loaded when a rising edge (0 to 1 transition) is applied to RCLK. The idea here is that the output registers will maintain whatever 0 and 1 values we last loaded into them, and it’s these values that are presented to the outside world. We can load a new series of 0 and 1 values into our shift register using 8 pulses on SRCLK without affecting the contents of the output registers. Once we are ready to rock and roll, a single pulse on RCLK will copy these new values into the output registers As usual, the RCLK signal from the Off On b c d Start #1 #2 #3 #4 #5 #6 #7 #8 Fig.5: how the display changes while loading the new data. 19 QB 1 16 VCC QC 2 15 QA QD 3 14 SER QE 4 13 OE QF 5 12 RCLK QG 6 11 SRCLK QH 7 10 SRCLR GND 8 9 QH’ Fig.6: top view of the 74xx595 shift register. microcontroller will be connected to all the shift registers in the chain. Chaining all the devices using their QH’ outputs means we can update all their contents and copy their new values into the output registers simulatneously. Feeling enabled One more feature that is commonly found in devices like shift registers is the ability to disable their outputs. Consider the addition of the active-low OE (output enable) input as illustrated in Fig.2(d). When this signal is in its active (0) state, whatever values are stored in 3 We aren’t obliged to use all the features offered by this device. A minimal implementation would involve us using only three microcontroller pins to drive the SER, SRCLK, and RCLK pins on the shift register(s). In this case, we would connect a pull-up resistor to the SRCLR pin to place it in its inactive state (we can clear the register by loading it with a string of 0s), and a pull-down resistor to the OE pin to hold it in its active state. Alternatively, we might opt for a maximal implementation in which we also use the SRCLR and OE pins, thereby requiring us to dedicate five pins from our microcontroller. For the purposes of this column, I chose to straddle the fence by using four pins to control my shift register chain (I decided to reserve the OE feature for another day). the output registers will appear on the device’s abcdefgh outputs. In contrast, when this signal is in its inactive (1) state, the abcdefgh outputs will be placed in a tristate condition. That effectively disconnects what they are connected to (our 7-segment displays). The OE signal from the microcontroller will be connected to all the shift registers in the chain. In our clock project, we could employ this signal to control the brightness of the displays by using pulse-width modulation (PWM) to turn all the outputs from the shift registers on and off very quickly. We introduced the concept of PWM in PE, November 2023). There’s a chip for that I bet you’re wondering if there’s a device that fulfills all the requirements exhibited by Fig.2(d). Well, wonder no more, because the 74HC595 ticks all the checkboxes. I had a quick Google while no one was looking and found a five-pack on Amazon for £6, plus £9 shipping (https://pemag.au/link/ac1n), but there are lots of other sources. When we look at the data sheet for this little rascal (https://pemag.au/link/ ac1o), we discover that they’ve used the same pin names as us (Fig.6). What are the odds? It’s spooky, isn’t it! 3 D3 3 D2 Clearing the decks for action Our new circuit diagram using four 74xx595 shift registers is shown in Fig.7. Pin 2 from the Arduino drives the SER input to the first shift register; the h’ output from this chip drives the SER input to the next chip and so-on down the line. The h’ output from the last chip in the chain is left dangling (unconnected); 3 Connection D0 D1 No connection Ground (0V) 5 10 9 1 2 4 6 7 5 10 9 1 2 4 6 7 5 10 9 1 2 4 6 7 5 10 9 1 2 4 6 7 dp g f e d c b a dp g f e d c b a dp g f e d c b a dp g f e d c b a Display segments and pin numbers Resistors or Resistor Packs h g f e d c b a h’ 74xx595 SER h g f e d c b a h’ 74xx595 SER h g f e d c b a h’ 74xx595 SER h g f e d c b a h’ 74xx595 SER *1 *1 *1 *1 *2 *3 *4 *2 *3 *4 *2 *3 *4 *1 OE = Connected to GND (active state) via 10kΩ pull-down resistor *2 SRCLR = Shift register clear (active low) *3 SRCLK = Shift register clock (positive-edge triggered) *4 RCLK = Storage register clock (positive-edge triggered) *2 *3 *4 5 4 3 2 Arduino pin numbers Fig.7: our new display driver circuit uses four 74xx595 shift registers. 20 Practical Electronics | December | 2024 Adding the shift registers Once we’ve added our new current-limiting resistors, the next step is to add the four shift registers as illustrated in Fig.8. Practical Electronics | December | 2024 Fig.9: wiring the inputs to the shift Arduino pin registers. numbers 2 SER 3 RCLK 4 SRCLK 5 SRCLR 5 4 3 2 Arduino pin numbers 21 Lower Breadboard Lower Breadboard we can use it to add more chips to the chain later if we wish. The first thing we’ll do is clear the decks for action. Make Note: Notches on sure your clock is powered Pin 1 Pin 1 Pin 1 down, then remove the wires the right-hand side connecting Arduino pins 2 through 9 to our breadboards. 74xx595 74xx595 74xx595 74xx595 We’ll also remove any wires connected to the inputs of the CD4511 chips, plus any wires connecting the CD4511s to the four 270Ω resistor packs. As part of this, we will remove any components (pullup resistors and decoupling capacitors) associated with the CD4511s. Also, any power and Fig.8: adding the shift registers. ground wires associated with the CD4511s and the wires connecting It’s very important to note that we are ter to verify that you are seeing +5V pin 1 on each of the resistor packs to rotating these chips 180° to the way we (give or take) across all the power and ground (associated with the dp seg- previously inserted our BCD decoders. ground rail pairs on the breadboards. ments on the displays). This is a tricky topic. The commonly Also check that you are seeing +5V Finally, we will remove the CD4511 accepted practice is to orientate our (give or take) between pins 8 and 16 chips and the resistor packs. chips horizontally such that the notch/ on each chip (apply the black probe dimple is on the left and pin 1 is located to pin 8 and the red probe to pin 16). Resistance is futile on the lower left-hand corner. However, Keeping the red probe on pin 16, also It would be wonderful if we could we are positioning our shift register check that you are seeing +5V between keep on using our existing 270Ω resistor chips the other way round, with the pin 16 and pin 13 on each chip. Once packs, but it was not to be. When we notch/dimple on the right and pin 1 you are satisfied that everything is look at the 74xx595 data sheet, we see on the upper right-hand corner. tickety-boo, power the system down that each output can supply only 6mA. We are doing this to make our wiring again before proceeding to the next step. We know that the supply voltage easier (but I still feel naughty). from the Arduino Uno is 5V and that Add the black wires connecting pin Adding the wires The next step is to add the wires our red segment LEDs have a voltage 8 on these chips to the 0V (ground) rail drop of 2V. Rearranging Ohm’s law, V and the red wires connecting pin 16 driving the inputs to the shift registers = IR, giving R = V/I, tells us that our to the +5V (power) rail. Also add the as illustrated in Fig.9. Although these ideal resistors would be (5V – 2V) ÷ 100nF decoupling capacitors between wires are all shown as being orange in 0.006A = 500Ω. the power and ground rails as close to these diagrams, I personally prefer to use different colors in my own impleThe closest standard resistor value is the red wires as possible. 510Ω (with green-brown-brown color Add the 10kΩ pull-down resistor mentation. For example, I started by using a long bands), which would be great, although and the purple wires as shown. This 560Ω (with green-blue-brown color ensures that pin 13 (the OE input) to yellow wire to connect pin 2 on the each device is in its active low state, Arduino to pin 14 (the SER data input) bands) would also do nicely. on the right-hand shift register. I then Now we have a choice. We can use thereby enabling the outputs. You can see the current state of play used a short yellow wire to connect pin 32 discrete (individual) 510Ω or 560Ω 9 (the QH’ output) on the right-hand resistors if we have them, either plugged in the file CB-Dec24-brd-02.pdf shift register to pin 14 (the SER input) This would be a great time to power directly into our breadboards, or on four 8-resistor breakout boards (BOBs) everything up and use your multime- on the next chip in the chain. as discussed in PE, July 2024. Another option would be to use 560Ω resistor packs, which is what I’ve shown in my diagrams. As we’ve discussed before, these components are created by a variety of manufacturers, like the Bourns 4100R Series (https://pemag.au/link/ac13), 74xx595 74xx595 74xx595 74xx595 and they are available from most major vendors, such as DigiKey (https://pemag.au/link/ac1p). A quick test Before we ‘go for broke’, let’s perform a quick test to ensure we can talk to our shift register chain in a language it understands. I whipped up a little test program, which you can find in the file CB-dec24-code-01.txt As you’ll see when you cast your orbs over this code, we start with some definitions that will ease our lives by making our program more understandable and easier to modify in the future. In addition to defining NUM_SEGS_ ALL to be 32 (the total number of segments in our four displays), we also define the active and inactive values for our RCLK, SRCLK, and SRCLR signals. Next, we declare the names and numbers of the Arduino pins we wish to use to drive our shift register chain, assigning pins 2, 3, 4, and 5 to variable names PinSer, PinRclk, PinSrclk and PinSrclr, respectively. To resistors for display D2 To resistors for display D1 To resistors for display D0 74xx595 74xx595 74xx595 74xx595 Fig.10: wiring the outputs from the shift registers. In our setup() function, we first set all the shift register signals to their inactive values, then we pulse the PinSrclr signal to clear the shift register chips, after which we pulse the PinRclk signal to copy the contents of the shift registers into their output registers. The portion of the code of most interest to us here is the loop() function, shown in Listing 1. We start on line 66 when we present a logic 1 to the serial input to the first shift register in the chain. Then we use the for() loop on lines 67 through 74 to repeatedly load this value into the shift register. Inside this loop, we first pulse the PinSrclk signal to copy the data value into the shift register, then we pulse the PinRclk pin to copy the contents of the shift registers into their output registers. We wait for a second to give ourselves time to see what’s happening on our displays, then we do it all again. We expect to see the segments on the displays light up one after the other, starting with a , then b , then c… ending with dp on the first display, followed by the other displays in their turn. On line 76, we present a logic 0 to the serial input to the first shift register in the chain, then we use the for() loop on lines 77 through 84 to turn all the segments off again, one after the other. From Arduino Once you’ve verified that everything is working as expected, why don’t you experiment with this program a little. For example, if you delete lines 71 through 73 from inside the first loop and reinsert them outside the loop starting at line 75, all the segments will light up simultaneously, stay lit for one second, then start to be extinguished one after the other as before. Cunning code Now take a deep breath because the time has come to pull everything together. We’re going to take our old clock program, which was based on our BCD decoder implementation, and modify it to use our new shift register realisation. You can feast your orbs on my version of this code in the file CB-dec24-code-02.txt After all we’ve been through together, you should be able to understand the bulk of this program without any problem. The interesting part is found in the loop() function. We start by declaring a four-element array of 8-bit unsigned integers called tmpData[] (temporary data), along with a 32-bit unsigned integer called dispData (display data). Observe that we are using the uint8_t and uint32_t data types for these values (we introduced these data types in detail in PE, September 2020). Listing 2: building the 32-bit value to be shifted. Listing 1: some simple test code. 22 Practical Electronics | December | 2024 Lower Breadboard Similarly, I used two more short yellow wires to connect the QH’ output from the second chip to the SER input on the third chip, and the QH’ output from the third chip to the SER input on the fourth. Next, I connected pin 3 from the Arduino to pin 12 (the RCLK input) on the righthand chip, then added short wires to connect this pin to the corresponding pins on the other chips. Similarly, I connected the SRCLK and SRCLR signals as shown. We’re so close I can taste it. The final step is to connect the outputs from the shift registers to the inputs to the current-limiting resistors driving the displays (Fig.10). The full-up implementation is shown in file CB-Dec24-brd-03.pdf To resistors for display D3 As usual, we use our real-time clock (RTC) to determine the hour (in 24-hour format) and minute, both of which are represented as integers. As usual, we convert it from 24-hour format to 12hour format and we load the most- and least-significant digits of our hour and minute values into our temporary data array as illustrated in lines 108 through 111 of Listing 2. Now what we need to do is build the 32-bit value to be loaded into our shift register. Remember earlier when I wrote that we need to load the last bit first and the first bit last? That explains why we load the most-significant hour digit into tmpData[0] and the least-significant minute digit into tmpData[3], opposite to the way we did things before. Our next task is to take these four 8-bit tmpData[] values and use them to construct a single 32-bit dispData value, as illustrated in Fig.11. We start on line 114 by clearing our dispData value to all 0s. The next bit is quite clever, because we use a for() loop whose index follows the sequence 0, 1, 2, 3. Each time round the loop, we use this index to shift the contents of the corresponding tmpData[] value left by the index multiple of 8 bits using the << shift left operator. This means tmpData[0] will be shifted left by 8*0 = 0 bits, tmpData[1] will be shifted left by 8*1 = 8 bits, tmpData[2] will be shifted left by 8*2 = 16 bits and so forth. As part of this, 0s will be shifted into the newly-vacated, least-significant (right-hand) bits. After performing each shift, we logically OR the existing contents of disp­Data with the contents of the newly shifted value using the compound |= assignment operator. If you wish to delve deeper into any of this, you might take a look at my Masking and the C/C++ Bitwise Operators column (https://pemag.au/link/ac1q). One part of this deserves special attention. Observe the use of (uint32_t) on line 117. Let’s consider what would happen if we omitted this from our statement. “Type casting” refers to the process of converting one data type to another. There are two forms of type casting: implicit and explicit. One example of an implicit type cast occurs when we assign a smaller value to a larger one, like assigning an 8-bit value to a 32-bit value, for example. In this case, the 8-bit value will be padded with 24 leading zeros (assuming it’s an unsigned type, anyway). In line 117 of Listing 2, this implicit cast is the last thing that occurs prior to the new value being assigned to dispData. Before this, our 8-bit Practical Electronics | December | 2024 Components from Part 1 LEDs (assorted colours) Resistors (assorted values) Solderless breadboard Multicore jumper wires (male-to-male) https://amzn.to/3E7VAQE https://amzn.to/3O4RvBt https://amzn.to/3O2L3e8 https://amzn.to/3O4hnxk Components from Part 2 7-segment display(s) https://amzn.to/3Afm8yu Components from Part 5 Momentary pushbutton switches https://amzn.to/3Tk7Q87 Components from Part 6 Passive piezoelectric buzzer https://amzn.to/3KmxjcX Components for Part 9 SW-18010P vibration switch https://bit.ly/46SfDA4 Components for Part 10 Breadboard mounting trimpots https://bit.ly/3QAuz04 Components for Part 12 Light-Dependent Resistor https://bit.ly/3S2430m Components for Part 13 BC337 NPN Transistor https://bit.ly/40xAgyS Components for Part 14 HC-SR04 Ultrasonic Sensor https://bit.ly/49AMBq4 Components for Part 15 Real-Time Clock (RTC) https://bit.ly/3S9OjHl Components for Part 18 Long tailed (0.1-inch/2.54mm pitch) header pins https://bit.ly/3U1Vp2z Components for Part 19 Prototyping boards Kit of popular SN74LS00 chips https://bit.ly/3UMkcZ1 https://bit.ly/3wqgzyv Components for Part 20 16V 100µF electrolytic capacitors Ceramic capacitors (assorted values) https://bit.ly/44LzpNa https://bit.ly/4bEAUiv Components for Part 22 SN74LS48N BCD Decoders 16-pin resistor pack (8 × 390Ω) https://bit.ly/3zT18jx https://bit.ly/4d0ISDz Components for Part 23 4 × CD4511 BCD Decoders 16-pin resistor pack (8 × 390Ω) https://bit.ly/3yzWl6k https://bit.ly/46HZ2PQ Components for Part 24 74HC595 8-bit shift registers 4 × 16-pin resistor packs (8 × 560Ω) tmpData[] values will be shifted left by multiples of 8 bits as we just discussed. Since the << shift left operator has a higher precedence than the |= assignment operator, the shifted bits will ‘fall off the end’ of our 8-bit value. This is why we are using (uint32_t) https://bit.ly/3yzWl6k https://bit.ly/46HZ2PQ to perform an explicit cast. It has a higher precedence than a shift operator, so our 8-bit tmpData[] values will be cast into 32-bit values (padded with 0s in the most-significant bits) before the shift takes place. It’s the resulting shifted 32-bit value that will be assigned to our 32-bit dispData variable. tmpData[3] tmpData[2] tmpData[1] tmpData[0] (LS Minutes) 8 0 (MS Minutes) 8 0 (LS Hours) 8 0 (MS Hours) 8 0 a b c d e f g h a b c d e f g h a b c d e f g h a b c d e f g h 31 dispData To Shift Register 0 Fig.11: Building our 32-bit dispData value. 23 Digits Segments 0 6 1 2 2 5 3 5 4 4 5 5 6 5 7 3 8 7 9 5 Fig.12: the number of segments used by each digit in our current display scheme. The last function in my program is we can remove the remaining combinations (10 through 59) from further consideration. As we see, our worst-case scenario occurs at eight minutes past eight o’clock in the evening, which is 20:08 when our clock is running in its 24-hour mode. This will cause us to have 11 + 13 = 24 segments lit at the same time. I could have solved this in my head, but would I have been sure I was right? By jotting things down in this way, we can see how we arrived at our answer and easily check things later. Our second task was to determine the value of the current-limiting resistors that will provide us with the maximum possible segment current value assuming a total allocation of 350mA (the origin of this value was discussed in our previous column). We want to drive our segments as bright as possible without exceeding their 20mA maximum as defined in their data sheet. I’m afraid to say that this is a trick question because the answer depends on the type of chips we are using to drive our displays. Let’s start by calculating 350mA ÷ 24 segments = 14.58mA per segment. If we were still using the CD4511 BCD to 7-segment decoder chips from our previous column, each output can handle up to 25mA, which means our 14.58mA will be a breeze. Since we are using the Arduino Uno’s 5V power supply, and we know the forward voltage drop of our red LED DisplayTime() , which takes our 32-bit dispData value and loads it into the shift register, starting with bit 0 and ending with bit 31. That means bit 0 in dispData ends up driving the dp segment in display D3, while bit 31 in dispData ends up driving the a segment in display D0. I just powered up my clock, and it works like a charm, as is apparent from the great big beaming smile on my face (I look like this now: ). ☺ All is revealed! Now we consider our concluding conundrum. Our first task was to determine the maximum number of segments we might see active at the same time. Before we start, write your solution down on a piece of paper (we don’t want any cheating). Some people’s minds work in such a way that the answer will simply pop out to them. Others, like your humble narrator, are obliged to take a more circuitous approach. There is no right or wrong path to success here. I started by noting the number of segments associated with each displayed digit (Fig.12). Based on this, I created the tables shown in Fig.13. The reason we don’t need to document all the possibilities in the minutes table is that the mostsignificant digit cycles through 0, 1, 2, 3, 4, 5. Since we know 0 consumes the most segments out of these options, 24-Hour 12-Hour Minutes H #Segs H #Segs H #Segs M #Segs 1 2 3 4 5 6 7 8 9 10 11 12 2 5 5 4 5 5 3 7 5 2+6 = 8 2+2 = 4 2+5 = 7 0 6 2 1 5 2 3 5 4 4 5 5 6 5 3 7 8 7 9 5 10 2+6 = 8 11 2+2 = 4 12 13 14 15 16 17 18 19 20 21 22 23 2+5 = 7 2+5 = 7 2+4 = 6 2+5 = 7 2+5 = 7 2+3 = 5 2+7 = 9 2+5 = 7 5+6 = 11 5+2 = 7 5+5 = 10 5+5 = 10 00 01 02 03 04 05 06 07 08 09 10 : 59 6+6 = 12 6+2 = 8 6+5 = 11 6+5 = 11 6+4 = 10 6+5 = 11 6+5 = 11 6+3 = 9 6+7 = 13 6+5 = 11 2+6 = 8 : : 5+5 = 10 segments is 2V, we can calculate the desired value of our current-limiting resistors as (5V – 2V) ÷ 0.01458A = 206Ω. The nearest regular resistor value is 200Ω (with red-black-brown color bands), which is “close enough for government work”, as they say, so we would go with that. However, since we are now using 74HC595 shift registers to drive our displays, we are bound to obey the constraints of their data sheet, which states that the maximum current per output is only 6mA. That still results in relatively bright displays, and it reduces our worst-case display current to 6mA × 24 segments = 144mA. This is well below our 350mA maximum, leaving 350mA – 144mA = 206mA on the table for us to use for other purposes. However, it also means that the values of our current-limiting resistors are now calculated as (5V – 2V) ÷ 0.006A = 500Ω. In this case, the nearest regular value is 510Ω (with green-brown-brown color bands). What? That’s it? I’m afraid we’ve come to the end of our Arduino Bootcamp series. Still, turn that frown upside-down into a smile because all is not doom and gloom. In this series, we’ve covered a lot of ground and learned all sorts of interesting things, many of which will prove useful in our new Weird and Wonderful Arduino Projects series, starting next month. Until then, let’s all think about things we could do to extend the capabilities of the clock project we just created. I’ll share my thoughts in our next column (albeit under a different name). As always, I welcome your insightful comments, penetrating questions, and PE sagacious suggestions. Online resources For the purposes of this series, I’m going to assume that you are already familiar with fundamental concepts like voltage, current and resistance. If not, you might want to start by perusing and pondering a short series of articles I penned on these very topics – see: https://pemag.au/link/ac16 Similarly, I’ll assume you are no stranger to solderless breadboards. Having said this, even if you’ve used these little scamps before, there are some aspects to them that can trap the unwary, so may I suggest you feast your orbs on a column I wrote just for you – see: https://pemag.au/link/ac17 Last, but not least, you will find a treasure trove of resources at the Arduino.cc website, including example programs and reference documentation. Fig.13: my approach to solving the problem. 24 Practical Electronics | December | 2024