{"id":166,"date":"2014-10-22T00:02:35","date_gmt":"2014-10-21T23:02:35","guid":{"rendered":"http:\/\/www.benningtons.net\/?p=166"},"modified":"2018-02-25T02:05:24","modified_gmt":"2018-02-25T02:05:24","slug":"8x8-led-matrix","status":"publish","type":"post","link":"https:\/\/www.benningtons.net\/index.php\/8x8-led-matrix\/","title":{"rendered":"8&#215;8 LED Matrix"},"content":{"rendered":"<p>For some variety I thought I&#8217;d add an electronics post to this website. This isn&#8217;t really a complete project but more of a hacking session with an 8&#215;8 LED matrix.<br \/>\nTaking time to understand and experiment with even such a basic component is a useful way of learning tricks that can be incorporated into future projects. Finding your own way can also be a rewarding challenge and what you discover tends to stick in your memory better than if you&#8217;d just read about it.<\/p>\n<p>So this is what I did&#8230;<\/p>\n<p><b>8&#215;8 LED Matrix:<\/b><\/p>\n<p style=\"padding-left: 30px;\">I&#8217;m using a cheap (<\u00a31) 8 by 8 array of LEDs in a package with 16 pins. The model number printed on the side reads 1088AS and a search on that will provide a basic schematic that shows what the pins are for.\n<nl><br \/>\nRows 1 to 8 are connected to the matrix pins: 9, 14, 8, 12, 1, 7, 2, 5<br \/>\nand columns 1 to 8 are connected to matrix pins: 13, 3, 4, 10, 6, 11, 15, 16<br \/>\n<nl><br \/>\nOther 8&#215;8 matrices are available but they&#8217;re either more expensive (multi-colour), which I wouldn&#8217;t want to risk with my mediocre electronic skills, or they&#8217;re more complex (serial interfaces), which I may tackle in a future post.<br \/>\nIn fact the variety of types is surprising but what&#8217;s more surprising is that they all appear to have different pin-outs.<br \/>\n<nl><br \/>\nMy 16 pin matrix provides connectivity to each of the 8 rows and 8 columns. By driving a row LOW (0v) and a column HIGH (5v) the corresponding LED on the matrix (where that row and that column cross) will be lit. So I started by getting a single light to move around the matrix and it all appeared to be easy. I then realised that getting more than one LED lit at a time would be far more difficult.<br \/>\n<nl><br \/>\nBut first, this is how I wired up my matrix to an Arduino.\n<\/p>\n<p><b>The Circuit:<\/b><\/p>\n<p style=\"padding-left: 30px;\">To get the pin orientation of the matrix look at the labelled edge. The pins on that side are 1-8 and they&#8217;re 16-9 on the far side. As per normal DIL packages the lowest pin is opposite the highest pin.<br \/>\nTo protect the LEDs I put a 1k resistor onto each row pin. Thereby ensuring a resistor in each circuit (between Arduino pin, via LED and resistor, and back to Arduino).<br \/>\n<nl><br \/>\nThat left 16 connections to make to the Arduino pins D2 to D17 (D14 to D17 are labelled A0 to A3). Which wires connect to which digital port isn&#8217;t actually that important because the following code can be adjusted to cater for any order. What is important is to note which wires connect to matrix rows (via a resistor) and which to matrix columns. So two different colours of wire would be a help.<br \/>\n<nl><br \/>\nI&#8217;ve chosen a connection order that looks neat on this circuit picture but I could equally have used D2-D9 for rows and D10-D17 for columns.\n<\/p>\n<p><a href=\"https:\/\/www.benningtons.net\/wp-content\/images\/led_array.jpg\"><img loading=\"lazy\" src=\"https:\/\/www.benningtons.net\/wp-content\/images\/led_array.jpg\" alt=\"led_array\" width=\"200\" height=\"200\" class=\"alignnone size-full wp-image-169\" \/><\/a><br \/>\n<nl><br \/>\n<b>The Code:<\/b><\/p>\n<p style=\"padding-left: 30px;\">To start with I had a single light moving around the perimeter of the matrix. But that was too simple so I added a variable length &#8216;tail&#8217; of lights to follow it.<nl><br \/>\nThe code starts by declaring the sequence of Arduino pins that connect to each row and each column.<br \/>\nThen some variables to set the length of the tail (1 for a single light and up to 28 for the whole perimeter), an array holding the number of each LED in the tail and a counter to show which one is the leading LED.<br \/>\n<nl><\/p>\n<pre class=\"brush: cpp; title: ; notranslate\" title=\"\">\r\n\/*\r\n * 8x8 LED array test1\r\n * display a line of lights moving around the perimeter of the 8x8 matrix\r\n *\/\r\n\r\n\/\/ Arduino pin definitions - (ordered to keep wiring tidy)\r\nint row[] = {14,10,4,12,9,5,8,6};    \/\/rows - driven LOW for on\r\nint col[] = {17,16,13,2,15,3,7,11};  \/\/columns - driven HIGH for on\r\n\r\n\/\/ give our moving light a tail?\r\nint tailLen = 10;      \/\/choose 1 to 28 to set length of tail\r\nint tail[28];          \/\/number of each led currently being lit\r\nint tailPos = 0;      \/\/current position on leading light\r\n\r\nint i, j;\t\t\/\/general counters\r\n<\/pre>\n<p><nl><\/p>\n<p style=\"padding-left: 30px;\">The setup function sets each of our row and column pins as digital outputs. Makes sure all LEDs are turned off before we start and initialises the tail array.<br \/>\n<nl><\/p>\n<pre class=\"brush: cpp; title: ; notranslate\" title=\"\">\r\nvoid setup()\r\n{\r\n  for (i=0; i&lt;8; i++) \t\t\t\t \/\/set arduino pins to be outputs\r\n  {\r\n    pinMode(row[i], OUTPUT);\r\n    pinMode(col[i], OUTPUT);\r\n  }\r\n  for (i=0; i&lt;8; i++) \t             \/\/clear\r\n  {\r\n    digitalWrite(row[i], HIGH);\r\n    digitalWrite(col[i], LOW);\r\n  }\r\n  for (i=0; i&lt;=tailLen; i++) \t\t  \/\/initialise the tail\r\n  {\r\n    tail[i]=-1;\r\n  }\r\n}\r\n<\/pre>\n<p><nl><\/p>\n<p style=\"padding-left: 30px;\">The loop function traces the outline of the 8&#215;8 matrix simply by running through a series of loops to identify which pin to turn on. The function ledout() will deal with turning the LEDs off and on. That way I could modify the loop function to display different patterns without having to change the digital output commands.<br \/>\nYou&#8217;ll notice that I&#8217;m addressing each LED in the matrix as a number between 0 and 63.<br \/>\n<nl><\/p>\n<pre class=\"brush: cpp; title: ; notranslate\" title=\"\">\r\nvoid loop()\r\n{\r\n    for (i=0; i&lt;8; i++)\r\n    {\r\n      ledout(i);\r\n    }\r\n    for (i=15; i&lt;56; i=i+8)\r\n    {\r\n      ledout(i);\r\n    }\r\n    for (i=63; i&gt;55; i--)\r\n    {\r\n      ledout(i);\r\n    }\r\n    for (i=48; i&gt;0; i=i-8)\r\n    {\r\n      ledout(i);\r\n    }\r\n}\r\n<\/pre>\n<p><nl><\/p>\n<p style=\"padding-left: 30px;\">The ledout function adds the new LED to the tail array and in doing so will erase the end of the tail.<br \/>\nIt then loops through the tail array and converts each LED number into a row and column number. Dividing by 8 to get the column (quotient) and using the remainder (modulus) when dividing by 8 to get the row.<br \/>\n<nl><\/p>\n<pre class=\"brush: cpp; title: ; notranslate\" title=\"\">\r\nvoid ledout(int i)\r\n{\r\n  tail[tailPos]=i;\r\n  if (tailPos++ &gt;= tailLen) tailPos=0;\r\n\r\n  for (j=0; j&lt;tailLen; j++)\r\n  {\r\n    if (tail[j]&gt;-1)\r\n    {\r\n      digitalWrite(row[tail[j]%8], LOW);\r\n      digitalWrite(col[tail[j]\/8], HIGH);\r\n      delay(2);\r\n      digitalWrite(row[tail[j]%8], HIGH);\r\n      digitalWrite(col[tail[j]\/8], LOW);\r\n    }\r\n  }\r\n}\r\n<\/pre>\n<p><nl><\/p>\n<p style=\"padding-left: 30px;\">In this example only one LED is lit at a time, followed by a short delay before turning the LED off. Because this happens so quickly it will give the illusion of a constant line of lit LEDs moving around the matrix.<br \/>\nAs a variation a longer delay for the first LED in the line can cause the leading light to appear a bit brighter than the rest of the tail.<br \/>\n<nl><br \/>\nThis method of tracing a moving line on the matrix is akin to the vector graphics seen on an oscilloscope or the old arcade game Battlezone (showing my age). It&#8217;s fairly efficient but it suffers from flicker, you&#8217;ll notice that if you change the tail size. This can be compensated by adjusting the delay when each LED is lit but it&#8217;s not ideal.\n<\/p>\n<p><b>The Matrix Reloaded:<\/b><\/p>\n<p style=\"padding-left: 30px;\">A solution to this flicker is to treat the tiny 8&#215;8 matrix like a TV and display each of the eight rows in turn. Moving from top to bottom in a raster scan fashion. Each full display will then always consist of 8 digital outputs (plus turning LEDs off again) so, once the delay is suitably adjusted, the image remains flicker free no matter how many LEDs are lit.<br \/>\n<nl><br \/>\nThe downside of this method is the need to maintain an array showing which LED should be on or off (just as a computer will reserve some &#8216;display memory&#8217;, or at least they did before graphics cards took over). In this example I&#8217;m being wasteful by using an int array to map the LED matrix. A single bit (1 or 0) would suffice to determine the state of each LED. This larger int array would be useful to map a multi-colour array but for this monochrome array a bitmap would be sufficient and I could use that to display a sequence of patterns, maybe counting from 0 to 9 or running through the alphabet? Maybe next time&#8230;<br \/>\n<nl><br \/>\nHere is the full 2nd version of my Arduino code. To add a bit more interest, as well as tracing the outer 8&#215;8 in a clockwise direction, I&#8217;ve added an inner 4&#215;4 trace going anti-clockwise. Well OK, it&#8217;s not very interesting but what more can I do with 64 LEDs&#8230;<br \/>\n<nl><\/p>\n<pre class=\"brush: cpp; title: ; notranslate\" title=\"\">\r\n\/*\r\n * 8x8 LED array test 2\r\n * display a line of lights moving around the perimeter of the 8x8 matrix\r\n * and a 2nd line of lights moving around an inner 4x4 matrix, in the opposite direction\r\n *\/\r\n\r\n\/\/ Arduino pin definitions - (ordered to keep wiring tidy)\r\nint row[] = {14,10,4,12,9,5,8,6};    \/\/rows - driven LOW for on\r\nint col[] = {17,16,13,2,15,3,7,11};  \/\/columns - driven HIGH for on\r\n\r\n\/\/ give our moving light a tail?\r\nint tailLen = 30;      \/\/ choose 2 to 54 to set length of traces\r\nint tail[54];          \/\/ number of each LED currently being lit\r\nint tailPos = 0;      \/\/ current position on leading light\r\n\r\n\/\/ a logic array to map 8x8 led matrix - #todo convert to binary\r\nint ledMatrix[64];\r\n\r\nvoid setup()\r\n{\r\n  for (int i=0; i&lt;8; i++)  \t      \/\/set arduino pins to be outputs\r\n  {\r\n    pinMode(row[i], OUTPUT);\r\n    pinMode(col[i], OUTPUT);\r\n  }\r\n\r\n  for (int i=0; i&lt;8; i++)            \/\/clear the led matrix\r\n  {\r\n    digitalWrite(row[i], HIGH);\r\n    digitalWrite(col[i], LOW);\r\n  }\r\n\r\n  for (int i=0; i&lt;=tailLen; i++)     \/\/initialise tail\r\n  {\r\n    tail[i]=-1;\r\n  }\r\n\r\n  for (int i=0; i&lt;64; i++)  \t    \/\/ clear matrix\r\n  {\r\n    ledMatrix[i]=0;\r\n  }\r\n}\r\n\r\nvoid loop()\r\n{\r\n    for (int i=0; i&lt;8; i++)\r\n    {\r\n      ledout(i);                   \/\/Trace 1 - outer 8x8 leds - clockwise\r\n      ledout(42+(i\/2));            \/\/ Trace 2 - inner 4x4 leds - anti-clockwise\r\n    }\r\n\r\n    for (int i=15; i&lt;56; i=i+8)\r\n    {\r\n      ledout(i);\r\n      ledout(45-((i\/16)*8));\r\n    }\r\n\r\n    for (int i=63; i&gt;55; i--)\r\n    {\r\n      ledout(i);\r\n      ledout(18+((i-56)\/2));\r\n    }\r\n\r\n    for (int i=48; i&gt;0; i=i-8)\r\n    {\r\n      ledout(i);\r\n      ledout(42-((i\/16)*8));\r\n    }\r\n}\r\n\r\nvoid ledout(int i)                    \/\/light requested led + variable tail of previous leds\r\n{\r\n  if (tail[tailPos] &gt; -1) ledMatrix[tail[tailPos]]=0;  \/\/ mark end of tail led to be turned off \r\n  tail[tailPos]=i;\r\n  if (tailPos++ &gt;= tailLen) tailPos=0;\r\n  ledMatrix[i]=1;\r\n\r\n  for (int j=0; j&lt;8; j++)            \/\/for each column\r\n  {\r\n    for (int k=0; k&lt;8; k++)            \/\/turn off all rows\r\n    {\r\n      digitalWrite(row[k], HIGH);\r\n    }\r\n\r\n    for (int k=0; k&lt;8; k++)            \/\/turn off all columns except current column\r\n    {\r\n      if (k==j)\r\n      {\r\n        digitalWrite(col[k], HIGH);\r\n      }\r\n      else\r\n      {\r\n        digitalWrite(col[k], LOW);\r\n      }\r\n    }\r\n\r\n    for (int k=0; k&lt;8; k++)            \/\/turn on required leds in current row\r\n    {\r\n      if (ledMatrix[((j*8)+k)]==1)\r\n      {\r\n        digitalWrite(row[k], LOW);\r\n      }\r\n    }\r\n    delay(3);\r\n  }\r\n}\r\n<\/pre>\n<p><nl><br \/>\nFinally I should point out that it doesn&#8217;t really make sense to tie-up 16 Arduino outputs for such a simple display. It would be better to use a serial interface chip (i.e. a MAX7219) or an LED matrix with a built-in serial interface. Then only 4 Arduino pins are needed and multiple LED matrices could be driven in sequence to create a moving sign. I&#8217;ll maybe do that next time&#8230;<\/p>\n\n","protected":false},"excerpt":{"rendered":"<p>For some variety I thought I&#8217;d add an electronics post to this website. This isn&#8217;t really a complete project but more of a hacking session with an 8&#215;8 LED matrix. Taking time to understand and experiment with even such a basic component is a useful way of learning tricks that can be incorporated into future [&hellip;]<\/p>\n","protected":false},"author":1,"featured_media":0,"comment_status":"closed","ping_status":"closed","sticky":false,"template":"","format":"standard","meta":[],"categories":[20],"tags":[19,23],"_links":{"self":[{"href":"https:\/\/www.benningtons.net\/index.php\/wp-json\/wp\/v2\/posts\/166"}],"collection":[{"href":"https:\/\/www.benningtons.net\/index.php\/wp-json\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/www.benningtons.net\/index.php\/wp-json\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/www.benningtons.net\/index.php\/wp-json\/wp\/v2\/users\/1"}],"replies":[{"embeddable":true,"href":"https:\/\/www.benningtons.net\/index.php\/wp-json\/wp\/v2\/comments?post=166"}],"version-history":[{"count":31,"href":"https:\/\/www.benningtons.net\/index.php\/wp-json\/wp\/v2\/posts\/166\/revisions"}],"predecessor-version":[{"id":327,"href":"https:\/\/www.benningtons.net\/index.php\/wp-json\/wp\/v2\/posts\/166\/revisions\/327"}],"wp:attachment":[{"href":"https:\/\/www.benningtons.net\/index.php\/wp-json\/wp\/v2\/media?parent=166"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/www.benningtons.net\/index.php\/wp-json\/wp\/v2\/categories?post=166"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/www.benningtons.net\/index.php\/wp-json\/wp\/v2\/tags?post=166"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}