{"id":257,"date":"2017-09-01T00:15:08","date_gmt":"2017-09-01T00:15:08","guid":{"rendered":"http:\/\/digm.drexel.edu\/uxid\/?p=257"},"modified":"2018-03-18T18:19:36","modified_gmt":"2018-03-18T18:19:36","slug":"web-controlled-8x8-led-matrix","status":"publish","type":"post","link":"https:\/\/philsinatra.net\/branches\/uxid\/2017\/09\/01\/web-controlled-8x8-led-matrix\/","title":{"rendered":"Web controlled 8&#215;8 LED Matrix"},"content":{"rendered":"<p><img loading=\"lazy\" class=\"alignleft size-medium wp-image-104\" src=\"http:\/\/tfinamore.com\/wp-content\/uploads\/2017\/07\/1@2x-300x225.jpg\" alt=\"\" width=\"300\" height=\"225\" \/>My goal for this project was to create a web page that could control an 8&#215;8 LED Matrix.\u00a0I picked up an <a href=\"https:\/\/www.amazon.com\/kuman-Complete-Detailed-Components-breadboard\/dp\/B016D5KUHS\/ref=sr_1_3?ie=UTF8&amp;qid=1504181806&amp;sr=8-3&amp;keywords=kuman+sensor+kit+arduino\">arduino started kit<\/a> from Amazon, and initiated the project by working through the 8&#215;8 Led Matrix Tutorial that came with the kit.<\/p>\n<p>I found ygricks&#8217;s Pen &#8216;<a href=\"https:\/\/codepen.io\/ygricks\/details\/RPPvMg#forks\">arduino custom chars creator<\/a>&#8216; which was close to what I wanted to do, but not exactly. This pen uses a 5&#215;8 grid, and I needed an 8&#215;8 Grid. So I forked it and started tweaking the layout so that it would look better in a smartphone browser and match the look of the LED Matrix I would be using.<\/p>\n<p class=\"codepen\" data-height=\"600\" data-theme-id=\"0\" data-slug-hash=\"prdPmV\" data-default-tab=\"result\" data-user=\"findes\" data-embed-version=\"2\" data-pen-title=\"Arduino 8x8 LED Controller\">See the Pen <a href=\"https:\/\/codepen.io\/findes\/pen\/prdPmV\/\">Arduino 8&#215;8 LED Controller<\/a> by Troy Finamore (<a href=\"https:\/\/codepen.io\/findes\">@findes<\/a>) on <a href=\"https:\/\/codepen.io\">CodePen<\/a>.<\/p>\n<p><script async src=\"https:\/\/production-assets.codepen.io\/assets\/embed\/ei.js\"><\/script><\/p>\n<p>In the LED Matrix tutorial HEX numbers are used in an array to write the LED sequencing to the matrix. Af few edits to the JavaScript in the pen I forked and I had a function that would convert the binary bits to hex. The convertHex() function is still in the CodePen file, but in the end I went back to the binary code.<\/p>\n<p>Next I went back to the method I used for my <a href=\"http:\/\/digm.drexel.edu\/uxid\/2017\/08\/15\/internet-controlled-arduino-led-via-usb\/\">Internet Controlled Arduino LED via USB<\/a> which uses processing to read a text file from a web server and to load the contents into the computers serial communication port.<\/p>\n<p>Since I was now sending a string of data instead of a single integer, I had to make some tweaks in the Processing sketch to test to make sure the string was changed before updating the variable in the communications port.<\/p>\n<p>Then to add the code to the arduino tutorial file to read the string and control the LED Matrix. If only it were that simple. I was running into errors trying to convert a string to hex format. Thinking it would be easier to just use the binary format, I rewrote the code and tried that for a while, but still had the errors of trying to convert string to binary. After a week of frustration I decided to reach out to the <a href=\"https:\/\/forum.arduino.cc\/index.php?topic=497067.\">arduino community<\/a> but go not love there. So I started talking to other faculty with arduino experience to see if they had any ideas. Then one recommended that instead of trying to convert the string to binary, why use an if statement to test if string == &#8220;1&#8221; then set binary = 1. While this was not my final solution it did set me on the track that would eventually lead to the final solution. Back to the interwebs looking for alternative approaches that may help, I eventually found code that controls the grounding of the individual leds, now by testing the string I could control the ground and it worked!<\/p>\n<p>By tweaking my JS file to remove the commas and just pull in the binary string, I could then loop through the string in the Arduino and create a multi-dimensional array similar to the structure of the matrix, then loop through that new array and control the grounding of the individual LEds.<\/p>\n<figure class=\"wp-block-embed wp-block-embed-youtube is-type-video is-provider-youtube\"><div class=\"wp-block-embed__wrapper\"><iframe  id=\"_ytid_28418\"  width=\"326\" height=\"183\"  data-origwidth=\"326\" data-origheight=\"183\" src=\"https:\/\/www.youtube.com\/embed\/mQ5XiohnVvQ?enablejsapi=1&autoplay=0&cc_load_policy=0&cc_lang_pref=&iv_load_policy=1&loop=0&modestbranding=0&rel=1&fs=1&playsinline=0&autohide=2&theme=dark&color=red&controls=1&\" class=\"__youtube_prefs__  no-lazyload\" title=\"YouTube player\"  allow=\"accelerometer; autoplay; clipboard-write; encrypted-media; gyroscope; picture-in-picture\" allowfullscreen data-no-lazy=\"1\" data-skipgform_ajax_framebjll=\"\"><\/iframe><\/div><\/figure>\n<h3>HTML Code<\/h3>\n<pre class=\"EnlighterJSRAW\" data-enlighter-language=\"html\">&lt;!DOCTYPE html&gt;\r\n&lt;html&gt;\r\n&lt;head&gt;\r\n  &lt;meta charset=\"utf-8\"&gt;\r\n  &lt;meta name=\"viewport\" content=\"width=device-width, initial-scale=1.0, maximum-scale=1.0, user-scalable=no\"&gt;\r\n  &lt;title&gt;Arduino 8x8 LED Controller&lt;\/title&gt;\r\n  &lt;link rel=\"stylesheet\" href=\"main.css\"&gt;\r\n  &lt;script src=\"https:\/\/ajax.googleapis.com\/ajax\/libs\/jquery\/2.1.3\/jquery.min.js\"&gt;&lt;\/script&gt;\r\n&lt;\/head&gt;\r\n&lt;body&gt;\r\n  &lt;table width=\"300\" height=\"300\"&gt;\r\n    &lt;tr data-row=\"1\"&gt;\r\n      &lt;td data-col=\"1\"&gt;&lt;\/td&gt;\r\n      &lt;td data-col=\"2\"&gt;&lt;\/td&gt;\r\n      &lt;td data-col=\"3\"&gt;&lt;\/td&gt;\r\n      &lt;td data-col=\"4\"&gt;&lt;\/td&gt;\r\n      &lt;td data-col=\"5\"&gt;&lt;\/td&gt;\r\n      &lt;td data-col=\"6\"&gt;&lt;\/td&gt;\r\n      &lt;td data-col=\"7\"&gt;&lt;\/td&gt;\r\n      &lt;td data-col=\"8\"&gt;&lt;\/td&gt;\r\n    &lt;\/tr&gt;\r\n    &lt;tr data-row=\"2\"&gt;\r\n      &lt;td data-col=\"1\"&gt;&lt;\/td&gt;\r\n      &lt;td data-col=\"2\"&gt;&lt;\/td&gt;\r\n      &lt;td data-col=\"3\"&gt;&lt;\/td&gt;\r\n      &lt;td data-col=\"4\"&gt;&lt;\/td&gt;\r\n      &lt;td data-col=\"5\"&gt;&lt;\/td&gt;\r\n      &lt;td data-col=\"6\"&gt;&lt;\/td&gt;\r\n      &lt;td data-col=\"7\"&gt;&lt;\/td&gt;\r\n      &lt;td data-col=\"8\"&gt;&lt;\/td&gt;\r\n    &lt;\/tr&gt;\r\n    &lt;tr data-row=\"3\"&gt;\r\n      &lt;td data-col=\"1\"&gt;&lt;\/td&gt;\r\n      &lt;td data-col=\"2\"&gt;&lt;\/td&gt;\r\n      &lt;td data-col=\"3\"&gt;&lt;\/td&gt;\r\n      &lt;td data-col=\"4\"&gt;&lt;\/td&gt;\r\n      &lt;td data-col=\"5\"&gt;&lt;\/td&gt;\r\n      &lt;td data-col=\"6\"&gt;&lt;\/td&gt;\r\n      &lt;td data-col=\"7\"&gt;&lt;\/td&gt;\r\n      &lt;td data-col=\"8\"&gt;&lt;\/td&gt;\r\n    &lt;\/tr&gt;\r\n    &lt;tr data-row=\"4\"&gt;\r\n      &lt;td data-col=\"1\"&gt;&lt;\/td&gt;\r\n      &lt;td data-col=\"2\"&gt;&lt;\/td&gt;\r\n      &lt;td data-col=\"3\"&gt;&lt;\/td&gt;\r\n      &lt;td data-col=\"4\"&gt;&lt;\/td&gt;\r\n      &lt;td data-col=\"5\"&gt;&lt;\/td&gt;\r\n      &lt;td data-col=\"6\"&gt;&lt;\/td&gt;\r\n      &lt;td data-col=\"7\"&gt;&lt;\/td&gt;\r\n      &lt;td data-col=\"8\"&gt;&lt;\/td&gt;\r\n    &lt;\/tr&gt;\r\n    &lt;tr data-row=\"5\"&gt;\r\n      &lt;td data-col=\"1\"&gt;&lt;\/td&gt;\r\n      &lt;td data-col=\"2\"&gt;&lt;\/td&gt;\r\n      &lt;td data-col=\"3\"&gt;&lt;\/td&gt;\r\n      &lt;td data-col=\"4\"&gt;&lt;\/td&gt;\r\n      &lt;td data-col=\"5\"&gt;&lt;\/td&gt;\r\n      &lt;td data-col=\"6\"&gt;&lt;\/td&gt;\r\n      &lt;td data-col=\"7\"&gt;&lt;\/td&gt;\r\n      &lt;td data-col=\"8\"&gt;&lt;\/td&gt;\r\n    &lt;\/tr&gt;\r\n    &lt;tr data-row=\"6\"&gt;\r\n      &lt;td data-col=\"1\"&gt;&lt;\/td&gt;\r\n      &lt;td data-col=\"2\"&gt;&lt;\/td&gt;\r\n      &lt;td data-col=\"3\"&gt;&lt;\/td&gt;\r\n      &lt;td data-col=\"4\"&gt;&lt;\/td&gt;\r\n      &lt;td data-col=\"5\"&gt;&lt;\/td&gt;\r\n      &lt;td data-col=\"6\"&gt;&lt;\/td&gt;\r\n      &lt;td data-col=\"7\"&gt;&lt;\/td&gt;\r\n      &lt;td data-col=\"8\"&gt;&lt;\/td&gt;\r\n    &lt;\/tr&gt;\r\n    &lt;tr data-row=\"7\"&gt;\r\n      &lt;td data-col=\"1\"&gt;&lt;\/td&gt;\r\n      &lt;td data-col=\"2\"&gt;&lt;\/td&gt;\r\n      &lt;td data-col=\"3\"&gt;&lt;\/td&gt;\r\n      &lt;td data-col=\"4\"&gt;&lt;\/td&gt;\r\n      &lt;td data-col=\"5\"&gt;&lt;\/td&gt;\r\n      &lt;td data-col=\"6\"&gt;&lt;\/td&gt;\r\n      &lt;td data-col=\"7\"&gt;&lt;\/td&gt;\r\n      &lt;td data-col=\"8\"&gt;&lt;\/td&gt;\r\n    &lt;\/tr&gt;\r\n    &lt;tr data-row=\"8\"&gt;\r\n      &lt;td data-col=\"1\"&gt;&lt;\/td&gt;\r\n      &lt;td data-col=\"2\"&gt;&lt;\/td&gt;\r\n      &lt;td data-col=\"3\"&gt;&lt;\/td&gt;\r\n      &lt;td data-col=\"4\"&gt;&lt;\/td&gt;\r\n      &lt;td data-col=\"5\"&gt;&lt;\/td&gt;\r\n      &lt;td data-col=\"6\"&gt;&lt;\/td&gt;\r\n      &lt;td data-col=\"7\"&gt;&lt;\/td&gt;\r\n      &lt;td data-col=\"8\"&gt;&lt;\/td&gt;\r\n    &lt;\/tr&gt;\r\n  &lt;\/table&gt;\r\n  &lt;div&gt;\r\n    &lt;button class=\"on\"&gt;ON&lt;\/button&gt;\r\n    &lt;button class=\"off\"&gt;OFF&lt;\/button&gt;\r\n    &lt;button class=\"invert\"&gt;INVERT&lt;\/button&gt;\r\n  &lt;\/div&gt;\r\n  &lt;script src=\"main.js\"&gt;&lt;\/script&gt;\r\n&lt;\/html&gt;<\/pre>\n<p>&nbsp;<\/p>\n<h3>CSS Code<\/h3>\n<pre class=\"EnlighterJSRAW\" data-enlighter-language=\"css\">html {\r\n  background: #07294D;\r\n  margin: auto;\r\n}\r\ntd {\r\n  width: 30px;\r\n  height: 30px;\r\n  background: #000;\r\n}\r\n.select {\r\n  background: #FFF;\r\n  border-radius: 100px\r\n}\r\n\r\ntable {\r\n  margin: 1em auto;\r\n  padding: 1em;\r\n  display: block;\r\n  width: 300px;\r\n  height: 300px;\r\n  resize: none;\r\n  border-spacing: 5px;\r\n}\r\n.export {\r\n  height: 270px;\r\n  border: none;\r\n  font-family: monospace;\r\n}\r\ndiv {\r\n  text-align: center;\r\n}\r\nbutton {\r\n  padding: 1em;\r\n}<\/pre>\n<p>&nbsp;<\/p>\n<h3>JavaScript Code<\/h3>\n<pre class=\"EnlighterJSRAW\" data-enlighter-language=\"js\">var a = [];\r\n\r\nfor (var i = 1; i &lt;= 9; i++) {\r\n a[i] = [];\r\n for (var e = 1; e &lt;= 8; e++) a[i][e] = \"null\";\r\n}\r\n\r\n$(document).ready(function () {\r\n $(\"table\").click();\r\n});\r\n\r\n$(\".off\").click(function () {\r\n $(\".select\").removeClass(\"select\");\r\n $(\"table\").click();\r\n});\r\n\r\n$(\".on\").click(function () {\r\n $(\"td\").addClass(\"select\");\r\n $(\"table\").click();\r\n});\r\n\r\n$(\".invert\").click(function () {\r\n $(\"td\").toggleClass(\"select\");\r\n $(\"table\").click();\r\n});\r\n\r\n$(\"td\").click(function () {\r\n if ($(this).hasClass(\"select\")) {\r\n $(this).removeClass(\"select\");\r\n } else {\r\n $(this).addClass(\"select\");\r\n }\r\n});\r\n\r\n$(\"table\").click(function () {\r\n var t = $(\"table\").first();\r\n var cols = t.find(\"tr\");\r\n   cols.each(function () {\r\n   var rows = $(this).find(\"td\");\r\n   rows.each(function () {\r\n     a[$(this).parent().data(\"row\")][$(this).data(\"col\")] = $(this).hasClass(\r\n     \"select\"\r\n     ) ?\r\n     1 :\r\n     0;\r\n   });\r\n });\r\n var c = convertBin();\r\n});\r\n\r\nfunction convertBin() {\r\n var binaryArt = \"\";\r\n for (var i = 1; i &lt;= 8; i++) {\r\n   var row = \"\";\r\n   for (var j = 1; j &lt;= 8; j++) {\r\n     row += a[i][j] + \"\";\r\n   }\r\n   row += \"\"\r\n   binaryArt += row;\r\n }\r\n js2php(binaryArt);\r\n}\r\n\r\nfunction js2php(qData) {\r\n \/\/console.log(\"js2php called \" + qData);\r\n var xmlhttp = new XMLHttpRequest();\r\n xmlhttp.open(\"GET\", \"main.php?q=\" + qData, true);\r\n xmlhttp.send();\r\n}<\/pre>\n<p>&nbsp;<\/p>\n<h3>PHP Code<\/h3>\n<pre class=\"EnlighterJSRAW\" data-enlighter-language=\"php\">&lt;?php\r\n  $q = $_REQUEST[\"q\"];\r\n  if ($q !== \"\") {\r\n    \/\/ 170821 .. jwt .. Open, Create text file and WRITE the q parameter data to it\r\n    $dataFileObj = fopen(\"ascii-art.txt\", \"w\") or die(\"Unable to open file\");\r\n    fwrite($dataFileObj, $q);\r\n    fclose($dataFileObj);\r\n  }\r\n?&gt;<\/pre>\n<p>&nbsp;<\/p>\n<h3>Processing Code<\/h3>\n<pre class=\"EnlighterJSRAW\">import java.util.Arrays;\r\nimport processing.serial.*;\r\nSerial ComPort;\r\nString input[], prev[];\r\nString current;\r\nString last = \"0\";\r\n\r\nvoid setup() {\r\n String portName = Serial.list()[1];\r\n ComPort = new Serial(this, portName, 9600);\r\n println(ComPort);\r\n ComPort.bufferUntil('\\n');\r\n}\r\n\r\nvoid draw() {\r\n input = loadStrings(\"url to ascii-art.txt goes here\");\r\n current = input[0];\r\n if (Arrays.equals(input, prev)) {\r\n } else {\r\n   ComPort.write(current);\r\n   last = current;\r\n   print(current + \"\\n\\n\");\r\n   prev = input.clone();\r\n }\r\n input = null;\r\n delay(50);\r\n}<\/pre>\n<p>&nbsp;<\/p>\n<h3>Arduino Code<\/h3>\n<pre class=\"EnlighterJSRAW\">const int columnPins[] = { 6, 7, 8, 9, 10, 11, 12, 13};\r\nconst int rowPins[] = { 2, 3, 4, 5, 17, 16, 15, 14};\r\nString newData, prevData, tempChar;\r\nString displayArt[8][8];\r\nint col = 0, row = 0;\r\nvoid setup() {\r\n  Serial.begin(9600);\r\n  Serial.print(newData + \"\\n\\n\");\r\n  for (int i = 0; i &lt; 8; i++) {\r\n    pinMode(rowPins[i], OUTPUT); \/\/ make all the LED pins outputs\r\n    pinMode(columnPins[i], OUTPUT);\r\n    digitalWrite(columnPins[i], HIGH); \/\/ disconnect column pins from Ground\r\n  }\r\n}\r\nvoid loop() {\r\n  if (Serial.available()) {\r\n    newData = Serial.readString();\r\n    if (newData != prevData) {\r\n      for (int row = 0; row &lt; 8; row++) {\r\n        for (int col = 0; col &lt; 8; col++) {\r\n          tempChar = newData.charAt((row * 8) + col);\r\n          displayArt[row][col] = tempChar;\r\n        }\r\n      }\r\n      prevData = newData;\r\n    }\r\n  }\r\n  show();\r\n}\r\nvoid show() {\r\n  for (int row = 0; row &lt; 8; row++) {\r\n    digitalWrite(rowPins[row], HIGH); \/\/ connect row to +5 volts\r\n    for (int column = 0; column &lt; 8; column++) {\r\n      if (displayArt[row][column] == \"1\" ) {\r\n        digitalWrite(columnPins[column], LOW); \/\/ connect column to Gnd\r\n      }\r\n      \/\/delayMicroseconds(300); \/\/ a small delay for each LED\r\n      digitalWrite(columnPins[column], HIGH); \/\/ disconnect column from Gnd\r\n    }\r\n    digitalWrite(rowPins[row], LOW); \/\/ disconnect LEDs\r\n  }\r\n}<\/pre>\n<p>&nbsp;<\/p>\n<h3>Wiring Schematic<\/h3>\n<p><a href=\"http:\/\/tfinamore.com\/wp-content\/uploads\/2017\/08\/LED-Matrix-Wiring.png\" rel=\"lightbox\"><img loading=\"lazy\" class=\"aligncenter size-medium wp-image-139\" src=\"http:\/\/tfinamore.com\/wp-content\/uploads\/2017\/08\/LED-Matrix-Wiring-300x220.png\" alt=\"\" width=\"300\" height=\"220\" \/><\/a><\/p>\n<h3>What&#8217;s next?<\/h3>\n<p>Maybe add 3 more arrays so the drawing pad is 16&#215;16? or use an RGB Led Array and add a color picker. Ada Fruit has two possibilities, an <a href=\"https:\/\/www.adafruit.com\/product\/3444?gclid=EAIaIQobChMI6qLU7cqB1gIVDTaBCh3qqQGxEAYYBSABEgKnp_D_BwE\">8&#215;8 RGB LED Pixel Matrix<\/a> or the <a href=\"https:\/\/www.adafruit.com\/product\/2547?gclid=EAIaIQobChMI6qLU7cqB1gIVDTaBCh3qqQGxEAYYASABEgJbjvD_BwE\">Flexible 16&#215;16 NeoPixel RGB LED Matrix<\/a><\/p>\n<div style=\"width: 326px;\" class=\"wp-video\"><!--[if lt IE 9]><script>document.createElement('video');<\/script><![endif]-->\n<video class=\"wp-video-shortcode\" id=\"video-257-1\" width=\"326\" height=\"183\" preload=\"metadata\" controls=\"controls\"><source type=\"video\/mp4\" src=\"https:\/\/cdn-shop.adafruit.com\/product-videos\/1024x768\/2547-00.mp4?_=1\" \/><a href=\"https:\/\/cdn-shop.adafruit.com\/product-videos\/1024x768\/2547-00.mp4\">https:\/\/cdn-shop.adafruit.com\/product-videos\/1024x768\/2547-00.mp4<\/a><\/video><\/div>\n<p>This is also dependent upon a lot of technologies. Maybe my next step should be looking into using an <a href=\"https:\/\/store.arduino.cc\/usa\/arduino-ethernet-shield-2\">ethernet shield<\/a> or an <a href=\"https:\/\/store.arduino.cc\/usa\/arduino-ethernet-rev3-without-poe\">Arduino Ethernet<\/a> and create it as a stand alone thing.<\/p>\n","protected":false},"excerpt":{"rendered":"<p>My goal for this project was to create a web page that could control an 8&#215;8 LED Matrix.\u00a0I picked up an arduino started kit from Amazon, and initiated the project by working through the 8&#215;8 Led Matrix Tutorial that came with the kit. I found ygricks&#8217;s Pen &#8216;arduino custom chars &hellip;<\/p>\n","protected":false},"author":2,"featured_media":260,"comment_status":"closed","ping_status":"closed","sticky":false,"template":"","format":"standard","meta":[],"categories":[5,11],"tags":[21],"_links":{"self":[{"href":"https:\/\/philsinatra.net\/branches\/uxid\/wp-json\/wp\/v2\/posts\/257"}],"collection":[{"href":"https:\/\/philsinatra.net\/branches\/uxid\/wp-json\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/philsinatra.net\/branches\/uxid\/wp-json\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/philsinatra.net\/branches\/uxid\/wp-json\/wp\/v2\/users\/2"}],"replies":[{"embeddable":true,"href":"https:\/\/philsinatra.net\/branches\/uxid\/wp-json\/wp\/v2\/comments?post=257"}],"version-history":[{"count":5,"href":"https:\/\/philsinatra.net\/branches\/uxid\/wp-json\/wp\/v2\/posts\/257\/revisions"}],"predecessor-version":[{"id":270,"href":"https:\/\/philsinatra.net\/branches\/uxid\/wp-json\/wp\/v2\/posts\/257\/revisions\/270"}],"wp:featuredmedia":[{"embeddable":true,"href":"https:\/\/philsinatra.net\/branches\/uxid\/wp-json\/wp\/v2\/media\/260"}],"wp:attachment":[{"href":"https:\/\/philsinatra.net\/branches\/uxid\/wp-json\/wp\/v2\/media?parent=257"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/philsinatra.net\/branches\/uxid\/wp-json\/wp\/v2\/categories?post=257"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/philsinatra.net\/branches\/uxid\/wp-json\/wp\/v2\/tags?post=257"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}