{"id":486,"date":"2009-05-28T02:38:54","date_gmt":"2009-05-28T07:38:54","guid":{"rendered":"http:\/\/www.tigoe.net\/pcomp\/code\/?p=486"},"modified":"2009-05-31T02:49:25","modified_gmt":"2009-05-31T07:49:25","slug":"controlling-lots-of-outputs-from-a-microcontroller","status":"publish","type":"post","link":"https:\/\/www.tigoe.com\/pcomp\/code\/arduinowiring\/486\/","title":{"rendered":"Controlling Lots of Outputs from a Microcontroller"},"content":{"rendered":"<p>Making LED displays is fun. There are a a few tools that get used all the time, from row-column scanning to LED driver chips to multplexers and shift registers. This tutorial discusses some of the more popular methods for controlling large amounts of LEDs from a microcontroller, including their various strengths and weaknesses, and how they work. For more on this subject see chapter 14 of &#8220;<a href=\"http:\/\/www.amazon.com\/exec\/obidos\/ASIN\/159200346X\/physicalcompu-20\/002-1410032-7298416?creative=125577&amp;camp=2321&amp;link_code=as1\">Physical Computing<\/a>&#8220;, where Dan O&#8217;Sullivan and I discussed it in more depth.\u00a0 I&#8217;ll also include some notes on how to apply these ideas to controlling multiple motors or other high-current loads.<\/p>\n<p>Most microcontroller modules have a limited number of outputs. Even if you <a href=\"http:\/\/www.arduino.cc\/en\/Reference\/Board\">use the analog inputs as digital I\/O<\/a>, there are only 19 pins on an Arduino, for example. That&#8217;s a fairly typical number for an 8-bit controller, and it seems not nearly enough if you want to control, say, 100 LEDs or more.\u00a0 There are a couple ways around this problem.\u00a0 Without adding any additional hardware, you can make a matrix of your LEDs and control them using<strong> row-column scanning<\/strong>.\u00a0 If you want discrete analog control over one output at a time, you can use a <strong>multiplexer<\/strong>. For digital control over multiple pins, you could use an <strong>addressable latch<\/strong> or a <strong>shift register<\/strong>. If you need pseudo-analog control over multiple pins, you could use a PWM driver.\u00a0 There are also several <strong>LED driver chips<\/strong> that are designed specifically to control groups of LEDS.<\/p>\n<p><!--more--><\/p>\n<h2>Basic Principles<\/h2>\n<p>Before getting into the details of the actual methods, there are a few principles that will make your life easier.\u00a0 If you already understand these, feel free to skip to the next section.<\/p>\n<h3>Bit Manipulation<\/h3>\n<p>All of the methods for output control mentioned below share one common process: you store the states of the pins in variables, as arrays of bits, and manipulate the bits to turn things on or off.\u00a0 For example, a row of eight LEDs in a shift register can be represented by an eight-bit (i.e. a byte) variable. If every other LEd were turned off, the byte would look like this:<\/p>\n<pre>0 1 0 1 0 1 0 1<\/pre>\n<p>It doesn&#8217;t matter what the decimal value of this byte is, because all you care about is which bits are on and which bits are off.\u00a0 To change the states of the LEDs, you manipulate the bits.<\/p>\n<p>Computer <a href=\"\/pcomp\/code\/variables\">variables<\/a> are stored in arrays of transistors that can be turned on or off; in other words, in binary arrays. At the lowest level of abstraction, these arrays of bits are manipulated using various logic operations, like AND, OR, NOT, and XOR.\u00a0 They&#8217;re sometimes called <strong>bitwise operators<\/strong> because they operate by manipulating the bits. Here&#8217;s how they work:<\/p>\n<ul>\n<li>AND checks to see if both values are 1, and if so, returns a 1. Otherwise, it returns 0.<\/li>\n<li>OR checks to see if either value is 1. If one or the other is, it returns a 1.<\/li>\n<li>NOT reverses the value.<\/li>\n<li>XOR checks to see that the two values are different. If they are, it returns a 1. Otherwise it returns a 0.<\/li>\n<\/ul>\n<p>These operations have their own symbols in programming languages. Here they are in table form:<\/p>\n<table style=\"height: 98px;\" border=\"1\" width=\"160\">\n<tbody>\n<tr>\n<td width=\"97\" height=\"18\" align=\"left\"><strong>AND (&amp;)<br \/>\n<\/strong><\/td>\n<td width=\"97\"><strong>0<\/strong><\/td>\n<td width=\"97\"><strong>1<\/strong><\/td>\n<\/tr>\n<tr>\n<td height=\"18\">0<\/td>\n<td>0<\/td>\n<td>0<\/td>\n<\/tr>\n<tr>\n<td height=\"18\">1<\/td>\n<td>0<\/td>\n<td>1<\/td>\n<\/tr>\n<tr>\n<td height=\"18\" align=\"left\"><\/td>\n<td align=\"left\"><\/td>\n<td align=\"left\"><\/td>\n<\/tr>\n<\/tbody>\n<\/table>\n<table style=\"height: 64px;\" border=\"1\" width=\"160\">\n<tbody>\n<tr>\n<td height=\"18\" align=\"left\"><strong>OR (|)<br \/>\n<\/strong><\/td>\n<td><strong>0<\/strong><\/td>\n<td><strong>1<\/strong><\/td>\n<\/tr>\n<tr>\n<td height=\"18\">0<\/td>\n<td>0<\/td>\n<td>1<\/td>\n<\/tr>\n<tr>\n<td height=\"18\">1<\/td>\n<td>0<\/td>\n<td>1<\/td>\n<\/tr>\n<\/tbody>\n<\/table>\n<table style=\"height: 64px;\" border=\"1\" width=\"160\">\n<tbody>\n<tr>\n<td height=\"18\" align=\"left\"><strong>XOR (^)<br \/>\n<\/strong><\/td>\n<td><strong>0<\/strong><\/td>\n<td><strong>1<\/strong><\/td>\n<\/tr>\n<tr>\n<td height=\"18\">0<\/td>\n<td>0<\/td>\n<td>1<\/td>\n<\/tr>\n<tr>\n<td height=\"18\">1<\/td>\n<td>1<\/td>\n<td>0<\/td>\n<\/tr>\n<\/tbody>\n<\/table>\n<table style=\"height: 44px;\" border=\"1\" width=\"160\">\n<tbody>\n<tr>\n<td height=\"18\" align=\"left\"><strong>NOT (~)<br \/>\n<\/strong><\/td>\n<td><strong>0<\/strong><\/td>\n<td><strong>1<\/strong><\/td>\n<\/tr>\n<tr>\n<td height=\"18\" align=\"left\"><\/td>\n<td>1<\/td>\n<td>0<\/td>\n<\/tr>\n<\/tbody>\n<\/table>\n<p>So, if you had a row of eight bits turned on, and you wanted the fifth one turned off, you could use the XOR operation, like so:<\/p>\n<table style=\"height: 84px;\" border=\"0\" width=\"236\">\n<tbody>\n<tr>\n<td><strong>Bit number<\/strong><\/td>\n<td><strong>7<\/strong><\/td>\n<td><strong>6<\/strong><\/td>\n<td><strong>5<\/strong><\/td>\n<td><strong>4<\/strong><\/td>\n<td><strong>3<\/strong><\/td>\n<td><strong>2<\/strong><\/td>\n<td><strong>1<\/strong><\/td>\n<td><strong>0<\/strong><\/td>\n<\/tr>\n<tr>\n<td><\/td>\n<td>1<\/td>\n<td>1<\/td>\n<td>1<\/td>\n<td>1<\/td>\n<td>1<\/td>\n<td>1<\/td>\n<td>1<\/td>\n<td>1<\/td>\n<\/tr>\n<tr>\n<td><strong>^<\/strong><\/td>\n<td>0<\/td>\n<td>0<\/td>\n<td>1<\/td>\n<td>0<\/td>\n<td>0<\/td>\n<td>0<\/td>\n<td>0<\/td>\n<td>0<\/td>\n<\/tr>\n<tr>\n<td colspan=\"9\">\n<hr \/>\n<\/td>\n<\/tr>\n<tr>\n<td><\/td>\n<td>1<\/td>\n<td>1<\/td>\n<td>0<\/td>\n<td>1<\/td>\n<td>1<\/td>\n<td>1<\/td>\n<td>1<\/td>\n<td>1<\/td>\n<\/tr>\n<\/tbody>\n<\/table>\n<p>This is called <strong>bitmasking<\/strong>. It allows you to test the states of the bits one by one, and to turn them on or off. Turning on a bit is called <strong>setting<\/strong> the bit, and turning it off is <strong>clearing<\/strong> the bit.<\/p>\n<p>There are two other useful operations for manipulating bits, the <strong>bit shift operators<\/strong>, &gt;&gt; and &lt;&lt;.\u00a0 These move the bits of a byte left or right. For example:<\/p>\n<pre>00000001 &lt;&lt; 2 = 00000100<\/pre>\n<pre>10000000 &gt;&gt; 3 = 00010000<\/pre>\n<p>The bitwise operators in combination with the bit shift operators give you a lot of power over the individual bits of a byte.\u00a0 Here are a couple of handy examples:<\/p>\n<pre>    x &amp;= ~(1 &lt;&lt; n);      \/\/ forces nth bit of x to be 0.  all other bits left alone.<\/pre>\n<pre>    x |= (1 &lt;&lt; n);       \/\/ forces nth bit of x to be 1.  all other bits left alone.<\/pre>\n<pre>    x ^= (1 &lt;&lt; n);       \/\/ toggles nth bit of x.  all other bits left alone.<\/pre>\n<pre>    x = ~x;              \/\/ toggles ALL the bits in x.<\/pre>\n<p>For more on this, see the excellent <a href=\"http:\/\/www.arduino.cc\/playground\/Code\/BitMath\">Bitmath tutorial<\/a> by <a href=\"http:\/\/www.arduino.cc\/playground\/Profiles\/CosineKitty\">CosineKitty<\/a> on the <a href=\"http:\/\/www.arduino.cc\/playground\/\">Arduino playground<\/a>. There are also some handy commands in Arduino for manipulating bits: <a href=\"http:\/\/arduino.cc\/en\/Reference\/BitRead\">bitRead<\/a>, <a href=\"http:\/\/arduino.cc\/en\/Reference\/BitWrite\">bitWrite<\/a>, <a href=\"http:\/\/arduino.cc\/en\/Reference\/BitSet\">bitSet<\/a>, and <a href=\"http:\/\/arduino.cc\/en\/Reference\/BitClear\">bitClear<\/a>. You&#8217;ll see these used to write and read bits of a byte in the examples to follow.<\/p>\n<h3>Synchronous Serial Communication<\/h3>\n<p>Many of the integrated circuits (ICs) used to control lots of outputs communicate using <strong>synchronous serial communication<\/strong>. Unlike asynchronous <a href=\"\/pcomp\/code\/serial-communication\">serial communication<\/a>, in which there are two independent computers with their own clocks, synchronous serial communication has only one clock.\u00a0 The microcontroller (sometimes called the <strong>master device<\/strong>) sends a continuous pulse to the external IC\u00a0 (or <strong>slave device<\/strong>) on one pin (the <strong>clock pin<\/strong>). Each time the clock pin changes from low to high, the external IC reads another output pin from the microcontroller (the<strong> data pin<\/strong>) to see if it&#8217;s high or low, and saves the result in a memory bit. As new bits are read each clock pulse, they&#8217;re shifted bitwise into the IC&#8217;s memory registers, like a bucket brigade.<\/p>\n<p>Once the whole byte&#8217;s been received, the slave interprets the byte and changes its outputs.\u00a0 Depending on the chip, this can happen in a variety of ways.\u00a0 Some chips have an additional pin, called the<strong> latch pin<\/strong> or <strong>output enable pin<\/strong>, that the master device pulses high or low to activate the output.<\/p>\n<p>The general procedure for using an external IC like this goes as follows:<\/p>\n<ol>\n<li>arrange the bits you need to shift into a byte using bit manipulation<\/li>\n<li>toggle the latch to disable output<\/li>\n<li>shift the bits in, pulsing the clock every bit<\/li>\n<li>toggle the latch to enable output with the new state<\/li>\n<\/ol>\n<p>Many programming languages, including pBasic, PicBasic Pro, BX Basic, and Arduino, feature commands for shifting bits out like this, called <strong>shiftOut<\/strong>.\u00a0 Here&#8217;s a link to the Arduino <a href=\"http:\/\/www.arduino.cc\/en\/Reference\/ShiftOut\">shiftOut<\/a> command. There are several synchronous serial protocols, including I2C\/TwoWire and SPI.\u00a0 The Arduino <a href=\"http:\/\/arduino.cc\/en\/Reference\/Wire\">Wire<\/a> library implements the I2C protocol, and the <a href=\"http:\/\/www.arduino.cc\/playground\/Code\/Spi\">Spi<\/a> library implements SPI. Different ICs will use different protocols, so check the datasheet of your chip to know what to use. The examples here mostly use generic synchronous serial communication implemented using the shiftOut command.<\/p>\n<h3>Row-Column Scanning<\/h3>\n<p>You can control more than one LED per output pin of a microcontroller, even with no other external hardware, using <strong>row-column scanning<\/strong>.\u00a0 Even with the 19 pins of an Arduino, this method allows you to control up to 64 LEDs in an 8&#215;8 matrix with a few pins to spare.\u00a0 To do this, you arrange your outputs in a matrix, like so:<\/p>\n<figure id=\"attachment_511\" aria-describedby=\"caption-attachment-511\" style=\"width: 300px\" class=\"wp-caption aligncenter\"><a href=\"https:\/\/tigoe.com\/pcomp\/code\/wp-content\/uploads\/2009\/05\/led-matrix.png\"><img loading=\"lazy\" decoding=\"async\" class=\"size-medium wp-image-511\" style=\"border: 0pt none;\" title=\"led-matrix\" src=\"https:\/\/tigoe.com\/pcomp\/code\/wp-content\/uploads\/2009\/05\/led-matrix-300x274.png\" alt=\"led-matrix\" width=\"300\" height=\"274\" srcset=\"https:\/\/www.tigoe.com\/pcomp\/code\/wp-content\/uploads\/2009\/05\/led-matrix-300x274.png 300w, https:\/\/www.tigoe.com\/pcomp\/code\/wp-content\/uploads\/2009\/05\/led-matrix-1024x937.png 1024w, https:\/\/www.tigoe.com\/pcomp\/code\/wp-content\/uploads\/2009\/05\/led-matrix.png 1174w\" sizes=\"auto, (max-width: 300px) 100vw, 300px\" \/><\/a><figcaption id=\"caption-attachment-511\" class=\"wp-caption-text\">LED matrix.  This matrix shows columns as anodes and rows as cathodes, but some matrices have this reversed.  If you&#39;re using a pre-made matrix, check the datasheet.<\/figcaption><\/figure>\n<p>To control the matrix, you connect the row and column pins to the outputs of your microcontroller.\u00a0 To turn on a given LED, you take its column high and its low row, so that there&#8217;s a voltage difference across the LED. You can turn it off either by taking the column low, or by taking the row high.\u00a0 Either way, the voltage across the LED will be zero.\u00a0 In order to turn on some of the LEDs in a given column, but not others, do the following:<\/p>\n<ol>\n<li>Take the column low.\u00a0 This turns off all the LEDs in the column.<\/li>\n<li>Take the rows of the LEDs that you want to turn ON low.<\/li>\n<li>Take the rows of the LEDs that you want to turn OFF high.<\/li>\n<li>Take the column high.\u00a0 This will create a voltage difference across the LEDs with low rows, and they&#8217;ll turn on.<\/li>\n<\/ol>\n<p>Here&#8217;s a basic Arduino code snippet that turns on each of the LEDs in the matrix in turn, one at a time:<\/p>\n<pre><span style=\"color: #CC6600;\">for<\/span> (<span style=\"color: #996600;\">int<\/span> thisCol = 0; thisCol &lt; 8; thisCol++) {\r\n  <span style=\"color: #777755;\">\/\/ take the row pin (anode) high:<\/span>\r\n  <span style=\"color: #996600;\">digitalWrite<\/span>(col[thisCol], <span style=\"color: #CC0000;\">HIGH<\/span>);\r\n  <span style=\"color: #777755;\">\/\/ iterate over the rows (cathodes):<\/span>\r\n  <span style=\"color: #CC6600;\">for<\/span> (<span style=\"color: #996600;\">int<\/span> thisRow = 0; thisRow &lt; 8; thisRow++) {\r\n    <span style=\"color: #777755;\">\/\/ when the column is HIGH and the row is LOW,<\/span>\r\n    <span style=\"color: #777755;\">\/\/ the LED where they meet turns on:<\/span>\r\n    <span style=\"color: #996600;\">digitalWrite<\/span>(row[thisRow], <span style=\"color: #CC0000;\">LOW<\/span>);\r\n    <span style=\"color: #777755;\">\/\/ delay long enough to see the LED on:<\/span>\r\n    <span style=\"color: #996600;\">delay<\/span>(100);\r\n    <span style=\"color: #777755;\">\/\/ turn the pixel off:<\/span>\r\n    <span style=\"color: #996600;\">digitalWrite<\/span>(row[thisRow], <span style=\"color: #CC0000;\">HIGH<\/span>);\r\n  }\r\n  <span style=\"color: #777755;\">\/\/ take the column pin low to turn off the whole column:<\/span>\r\n  <span style=\"color: #996600;\">digitalWrite<\/span>(col[thisCol], <span style=\"color: #CC0000;\">LOW<\/span>);\r\n}<\/pre>\n<p class=\"post-title-single\">Row-column scanning is a common technique for controlling a larger number of outputs than you have pins.\u00a0 You can combine it with many of the external ICs mentioned below to create even larger control arrays.\u00a0 In fact, some of the LED driver chips, like the MAX7219, are designed for use with row-column scanning matrices. You can see examples of row-column scanning in action in the <a href=\"https:\/\/tigoe.com\/pcomp\/code\/category\/arduinowiring\/424\">8\u00d78 LED matrix control on an Arduino Mega<\/a> example, the <a href=\"https:\/\/tigoe.com\/pcomp\/code\/category\/Processing\/454\">Tale of Two Pongs<\/a> example, and the <a href=\"https:\/\/tigoe.com\/pcomp\/code\/category\/Processing\/514\">Tilty Ball<\/a> example.<\/p>\n<h2>Shift Registers<\/h2>\n<p>Shift registers use <strong>synchronous serial communication<\/strong> to shift data from the microcontroller into the shift register to light up\u00a0 LEDs.\u00a0 There are commonly three pins you need to connect between the microcontroller and the shift register:<\/p>\n<ul>\n<li><strong>Data<\/strong>: microcontroller takes this pin high or low to send a 1 or 0<\/li>\n<li><strong>Clock<\/strong>: microcontroller pulses this, and every time it goes from high to low, the shift register reads the data line<\/li>\n<li><strong>Latch<\/strong>: enables or disables the output of the shift register<\/li>\n<\/ul>\n<p>Different shift registers may add other features, but those are the most basic interface elements that shift registers share in common. Many LED drivers use synchronous serial communication as well.<\/p>\n<p>The data that you shift into a shift register get connected directly to the outputs when you toggle the latch.\u00a0 For example, when you shift sixteen bits into a 16-bit shift register, the 16 bits you send are mapped directly to the\u00a0 16 output pins. This is not necessarily the case for specialized LED driver chips, though.\u00a0 The bits you shift in are often commands for the driver to do specific things, like set a particular pin to a particular PWM rate.<\/p>\n<p>The <a href=\"https:\/\/tigoe.com\/pcomp\/code\/category\/arduinowiring\/534\">ST16C596 shift register<\/a> example shows how to use a shift register.<\/p>\n<h2>Multiplexers and Addressable Latches<\/h2>\n<p>Addressable latches and multiplexers generally have a series of <strong>address pins<\/strong> that you set in order to control which of the ouputs is connected to the chip&#8217;s input.\u00a0 For example, an 8-channel latch or multiplexer has 8 output pins, and three address pins. Turning on or off the address pins connects one of the eight outputs to the input.\u00a0 Why three address pins? Three pins that can be switch on or off makes for 2<sup>3<\/sup>, or 8 possible combinations.\u00a0 That allows you to choose any of the 8 outputs. For a 16-channel chip, you&#8217;d have 4 address pins, giving you 2<sup>4<\/sup>, or 16 possible combinations. Latches and multiplexers usually have an output enable or inhibit pin that allows you to turn off the output while you&#8217;re changing the address pins.\u00a0 Addressable latches also feature a pin that allows you to latch the outputs on or off so that you can control more than one at a time.\u00a0\u00a0 The disadvantage of latches, however, is that they&#8217;re always digital; you can only turn a latch&#8217;s pins on or off.\u00a0 Analog <strong>multiplexers<\/strong>, on the other hand, allow you to connect any voltage from the\u00a0 input pin to any of the output pins. The disadvantage of a multiplexer is that you can control only one pin at a time.<\/p>\n<p>The <a href=\"https:\/\/tigoe.com\/pcomp\/code\/category\/arduinowiring\/540\">CD4067 Multiplexer with LEDs<\/a> example shows how to use a multiplexer.<\/p>\n<p>The <a href=\"https:\/\/tigoe.com\/pcomp\/code\/category\/arduinowiring\/546\">CD4099 Addressable Latch with LEDs<\/a> example shows how to use an addressable latch.<\/p>\n<h2>So How Many Outputs Can You Control From One Microcontroller?<\/h2>\n<p>Here are some estimates based on personal experience.\u00a0 These may not be the limits, these are just based on some quick tests I&#8217;ve done:<\/p>\n<p><em>Using an Arduino Duemilanove\/Diecimila:<\/em><\/p>\n<p><strong>17 usable digital I\/O (not counting analog)<\/strong><\/p>\n<p>Attaching TLC5940 chips:<br \/>\n5 pins per set of ICs<br \/>\nCascade 8 ICs deep?<br \/>\n3 sets of 8 ICs each<br \/>\n24 x 16 LEDs =<br \/>\n<strong>384 LEDs<\/strong><\/p>\n<p><em>Using an Arduino Mega:<\/em><\/p>\n<p><strong>51 usable digital I\/O (not counting analog)<br \/>\n<\/strong><br \/>\nAttaching TLC5940 chips:<br \/>\n5 pins per set of ICs<br \/>\nCascade 8 ICs deep<br \/>\n10 sets of 8 ICs each<br \/>\n80 x 16 LEDs =<br \/>\n<strong>1280 LEDs<\/strong><br \/>\n<strong><br \/>\n<\/strong><\/p>\n<p>These are conservative estimates, as there is not an 8-chip limit on cascading TLC5940s.<\/p>\n<h2>Comparison Chart<\/h2>\n<table border=\"0\">\n<colgroup>\n<col width=\"193\"><\/col>\n<col width=\"74\"><\/col>\n<col width=\"97\"><\/col>\n<col width=\"97\"><\/col>\n<col width=\"97\"><\/col>\n<col width=\"97\"><\/col>\n<col width=\"97\"><\/col>\n<\/colgroup>\n<tbody>\n<tr>\n<td><strong>Option<\/strong><\/td>\n<td><strong>Fading?<\/strong><\/td>\n<td><strong>Multiple on at once?<\/strong><\/td>\n<td><strong>Synchronous serial?<\/strong><\/td>\n<td><strong>Address pins?<\/strong><\/td>\n<td><strong>Pins used<\/strong><\/td>\n<td><strong>Cascading?<\/strong><\/td>\n<\/tr>\n<tr>\n<td>Row-Column scanning<\/td>\n<td>No<\/td>\n<td>Sort of<\/td>\n<td>No<\/td>\n<td>No<\/td>\n<td>2n pins = n2 outs<\/td>\n<td>No<\/td>\n<\/tr>\n<tr>\n<td>Shift register<\/td>\n<td>No<\/td>\n<td>Yes<\/td>\n<td>Yes<\/td>\n<td>No<\/td>\n<td>3 pins = 16 outs<\/td>\n<td>Yes<\/td>\n<\/tr>\n<tr>\n<td>Multiplexer<\/td>\n<td>Yes<\/td>\n<td>No<\/td>\n<td>No<\/td>\n<td>Yes<\/td>\n<td>5 pins = 16 outs<\/td>\n<td>No<\/td>\n<\/tr>\n<tr>\n<td>Addressable latch<\/td>\n<td>No<\/td>\n<td>Yes<\/td>\n<td>No<\/td>\n<td>Yes<\/td>\n<td>5 pins = 8 outs<\/td>\n<td>No<\/td>\n<\/tr>\n<tr>\n<td>PWM driver<\/td>\n<td>Yes<\/td>\n<td>Yes<\/td>\n<td>Yes<\/td>\n<td>No<\/td>\n<td>5 pins = 16 outs<\/td>\n<td>Yes<\/td>\n<\/tr>\n<\/tbody>\n<\/table>\n","protected":false},"excerpt":{"rendered":"<p>Making LED displays is fun. There are a a few tools that get used all the time, from row-column scanning to LED driver chips to multplexers and shift registers. This tutorial discusses some of the more popular methods for controlling large amounts of LEDs from a microcontroller, including their various strengths and weaknesses, and how &hellip; <\/p>\n<p class=\"link-more\"><a href=\"https:\/\/www.tigoe.com\/pcomp\/code\/arduinowiring\/486\/\" class=\"more-link\">Continue reading<span class=\"screen-reader-text\"> &#8220;Controlling Lots of Outputs from a Microcontroller&#8221;<\/span><\/a><\/p>\n","protected":false},"author":2,"featured_media":0,"comment_status":"closed","ping_status":"open","sticky":false,"template":"","format":"standard","meta":{"footnotes":""},"categories":[9,24],"tags":[60,63,59,64,61],"class_list":["post-486","post","type-post","status-publish","format-standard","hentry","category-arduinowiring","category-circuits","tag-addressable-latch","tag-led","tag-multiplexer","tag-row-column-scanning","tag-shift-register"],"_links":{"self":[{"href":"https:\/\/www.tigoe.com\/pcomp\/code\/wp-json\/wp\/v2\/posts\/486","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/www.tigoe.com\/pcomp\/code\/wp-json\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/www.tigoe.com\/pcomp\/code\/wp-json\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/www.tigoe.com\/pcomp\/code\/wp-json\/wp\/v2\/users\/2"}],"replies":[{"embeddable":true,"href":"https:\/\/www.tigoe.com\/pcomp\/code\/wp-json\/wp\/v2\/comments?post=486"}],"version-history":[{"count":17,"href":"https:\/\/www.tigoe.com\/pcomp\/code\/wp-json\/wp\/v2\/posts\/486\/revisions"}],"predecessor-version":[{"id":559,"href":"https:\/\/www.tigoe.com\/pcomp\/code\/wp-json\/wp\/v2\/posts\/486\/revisions\/559"}],"wp:attachment":[{"href":"https:\/\/www.tigoe.com\/pcomp\/code\/wp-json\/wp\/v2\/media?parent=486"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/www.tigoe.com\/pcomp\/code\/wp-json\/wp\/v2\/categories?post=486"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/www.tigoe.com\/pcomp\/code\/wp-json\/wp\/v2\/tags?post=486"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}