Developer Guide - noelmkawano/InfDisplay GitHub Wiki

Overview

The system runs on four different elements:

  • The web host built from IntelliJ (and its PSQL database)
  • Processing IDE
  • Arduino IDE
  • Arduino UNO microcontroller (Display Hardware)

Installing

In order to run this web application following steps below:

  1. Install a coding environment. This repo was developed under IntelliJ IDEA 14.0.3

    • You can download IntelliJ here.
  2. Install the local GitHub and GitShell software.

    • You can download the local GitHub and GitShell client here.
  3. Fork the InfinityDisplay repository.

  4. Copy the repo into your local drive using the GitHub app.

  1. Open IntelliJ and import the project directory.

  1. In GitShell follow the same directory and test the application.

  1. Start the Play Runtime.

  1. Open a browser and access the webapp home page from url(http://localhost:9000)

Processing Code

Download the Processing IDE here.

Open the application then copy and paste the code below. Do not run the application until after uploading the Arduino code in the next section. Doing so will clog the serial port, preventing the microcontroller from being programmed.

The core concept revolves around the communication between the users input from the website and the reading of that information from the physical board. That communication is handled by the Processing IDE. The main function that we will be using is loadstrings(). Processing uses that function to call on the infdisplay.com/live page that houses the checkbox submission data. That data is read and placed into a string. That string then runs through a second function called split(). This time the code will find the last line of data, then distinguish the characters between numbers and commas. The result is an array of data points that was submitted by the last user. With this new array the values are mapped from the checkbox map (TreeMap) to an array numbering 0 to 575. Based on the location of the data point and the hard wiring of the display two values are created. For example, if the user submits checkbox (3,24) the read value should be 100. This 100 is the third checkbox from the top left so its new mapped value is 3. Now it is Processings job to notify the Arduino where it should turn on the LED. Two values are sent, the data line and the location of the LED in the data line. More on that in the next section.

/* Created by Noel Kawano 5/12/2015 */

//Import the serial library.
import processing.serial.*;

//Define the serial variable.
Serial myPort;

//Remap the TreeMap values.
int Map[] = {  0,  1,112,223,334,445,532,543,554,565,  2, 13, 24, 35, 46, 57, 68, 79, 90,101,113,124,135,146,
             157,168,179,190,201,212,224,235,246,257,268,279,290,301,312,323,335,346,357,368,379,390,401,412,
             423,434,446,457,468,479,490,501,512,523,530,531,533,534,535,536,537,538,539,540,541,542,544,545,
             546,547,548,549,550,551,552,553,555,556,557,558,559,560,561,562,563,564,566,567,568,569,570,571,
             572,573,574,575,  3,  4,  5,  6,  7,  8,  9, 10, 11, 12, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23,
              25, 26, 27, 28, 29, 30, 31, 32, 33, 34, 36, 37, 38, 39, 40, 41, 42, 43, 44, 45, 47, 48, 49, 50,
              51, 52, 53, 54, 55, 56, 58, 59, 60, 61, 62, 63, 64, 65, 66, 67, 69, 70, 71, 72, 73, 74, 75, 76,
              77, 78, 80, 81, 82, 83, 84, 85, 86, 87, 88, 89, 91, 92, 93, 94, 95, 96, 97, 98, 99,100,102,103,
             104,105,106,107,108,109,110,111,114,115,116,117,118,119,120,121,122,123,125,126,127,128,129,130,
             131,132,133,134,136,137,138,139,140,141,142,143,144,145,147,148,149,150,151,152,153,154,155,156,
             158,159,160,161,162,163,164,165,166,167,169,170,171,172,173,174,175,176,177,178,180,181,182,183,
             184,185,186,187,188,189,191,192,193,194,195,196,197,198,199,200,202,203,204,205,206,207,208,209,
             210,211,213,214,215,216,217,218,219,220,221,222,225,226,227,228,229,230,231,232,233,234,236,237,
             238,239,240,241,242,243,244,245,247,248,249,250,251,252,253,254,255,256,258,259,260,261,262,263,
             264,265,266,267,269,270,271,272,273,274,275,276,277,278,280,281,282,283,284,285,286,287,288,289,
             291,292,293,294,295,296,297,298,299,300,302,303,304,305,306,307,308,309,310,311,313,314,315,316,
             317,318,319,320,321,322,324,325,326,327,328,329,330,331,332,333,336,337,338,339,340,341,342,343,
             344,345,347,348,349,350,351,352,353,354,355,356,358,359,360,361,362,363,364,365,366,367,369,370,
             371,372,373,374,375,376,377,378,380,381,382,383,384,385,386,387,388,389,391,392,393,394,395,396,
             397,398,399,400,402,403,404,405,406,407,408,409,410,411,413,414,415,416,417,418,419,420,421,422,
             424,425,426,427,428,429,430,431,432,433,435,436,437,438,439,440,441,442,443,444,447,448,449,450,
             451,452,453,454,455,456,458,459,460,461,462,463,464,465,466,467,469,470,471,472,473,474,475,476,
             477,478,480,481,482,483,484,485,486,487,488,489,491,492,493,494,495,496,497,498,499,500,502,503,
             504,505,506,507,508,509,510,511,513,514,515,516,517,518,519,520,521,522,524,525,526,527,528,529};

//Remap the data lines to accound for the zigzag assembly.  
int Map2[] = { 0, 1, 2, 3, 4, 5, 6, 7, 8, 9,10,11,12,13,14,15,16,17,18,19,20,21,22,23,
              47,46,45,44,43,42,41,40,39,38,37,36,35,34,33,32,31,30,29,28,27,26,25,24,
              48,49,50,51,52,53,54,55,56,57,58,59,60,61,62,63,64,65,66,67,68,69,70,71};

void setup() {
  //Define draw size.
  size(200,200);

  //Open the Serial port.
  myPort = new Serial(this, Serial.list()[0], 9600);
}

void draw() {
  //Create a String of all values taken from the webpage.
  String lines1[] = loadStrings("http://www.infdisplay.com/live");
  
  //Store the last entry in a String and slipt the values by each comma read.
  String[] list1 = split(lines1[lines1.length - 3], ',');
  
  for(int i = 0; i < list1.length; i++) {
    //Turn every value of the list into an int.
    int x = int(list1[i]);
    
    //Map the list values with the zigzag assembly.
    int y = Map[x];
   
    if(y < 72) {
      //Map the list values with the zigzag assembly.
      int val = Map2[y];
      //Send 101 over serial, Defines the next value to be in the first data line.
      myPort.write(101);
      println(101);
      //Send the location of the LED in the data line.
      myPort.write(val);
      println(val);
    }
   
    if(y >=72 && y < 144) {
      //Make sure to account for the max Map2 value 72.
      int val = Map2[y-72];
      myPort.write(102);
      println(102);
      myPort.write(val);
      println(val);
    }
    
    if(y >=144 && y < 216) {
      int val = Map2[y-144];
      myPort.write(103);
      println(103);
      myPort.write(val);
      println(val);
    }
    
    if(y >=216 && y < 288) {
      int val = Map2[y-216];
      myPort.write(104);
      println(104);
      myPort.write(val);
      println(val);
    }
    
    if(y >=288 && y < 360) {
      int val = Map2[y-288];
      myPort.write(105);
      println(105);
      myPort.write(val);
      println(val);
    }
    
    if(y >=360 && y < 432) {
      int val = Map2[y-360];
      myPort.write(106);
      println(106);
      myPort.write(val);
      println(val);
    }
    
    if(y >=432 && y < 504) {
      int val = Map2[y-432];
      myPort.write(107);
      println(107);
      myPort.write(val);
      println(val);
    }
    
    if(y >=504 && y < 576) {
      int val = Map2[y-504];
      myPort.write(108);
      println(108);
      myPort.write(val);
      println(val);
    }
  }
}

Arduino

Download the Arduino IDE here.

Arduino UNOs can be purchased here.

Open the application then copy and paste the below code. Upload the code to the Arduino. Keep the device connected and run the Processing code. The LED on pin 13 should consistently flicker, indicating the flow of data.

The Arduino is the chosen microcontroller for this system. The hardware consists of 8 data lines each with 72 LEDs. The Infinity Display is a 24 by 24 matrix so every data line is folded in into 3 zigzag patterns. Serial communication between Processing and Arduino limit the values sent over Serial to be below 128. Because we are unable to send the hard value location of the LEDs above 127, Processing had to handle both the data line used and the location of the LED in the data line. This may result in a possible misalignment of variables to the incoming serial data points. If this happens, the current solution is to stop and restart the processing code.

/* Created by Noel Kawano 5/12/2015 */

//Import the Adafruit library.
#include <Adafruit_NeoPixel.h>

//Define the eight data lines and their repective pins to the Arduino Uno.
Adafruit_NeoPixel strip1 = Adafruit_NeoPixel(72, 2, NEO_GRB + NEO_KHZ800);
Adafruit_NeoPixel strip2 = Adafruit_NeoPixel(72, 3, NEO_GRB + NEO_KHZ800);
Adafruit_NeoPixel strip3 = Adafruit_NeoPixel(72, 4, NEO_GRB + NEO_KHZ800);
Adafruit_NeoPixel strip4 = Adafruit_NeoPixel(72, 5, NEO_GRB + NEO_KHZ800);
Adafruit_NeoPixel strip5 = Adafruit_NeoPixel(72, 6, NEO_GRB + NEO_KHZ800);
Adafruit_NeoPixel strip6 = Adafruit_NeoPixel(72, 7, NEO_GRB + NEO_KHZ800);
Adafruit_NeoPixel strip7 = Adafruit_NeoPixel(72, 8, NEO_GRB + NEO_KHZ800);
Adafruit_NeoPixel strip8 = Adafruit_NeoPixel(72, 9, NEO_GRB + NEO_KHZ800);

//Define the serial varibales.
char val;
char val2;

//Define the counter variable.
int counter = 0;

void setup() {
  //Define the baud rate.
  Serial.begin(9600);
  
  //Begin communication to the data lines.
  strip1.begin();
  strip1.show();
  strip2.begin();
  strip2.show();
  strip3.begin();
  strip3.show();
  strip4.begin();
  strip4.show();
  strip5.begin();
  strip5.show();
  strip6.begin();
  strip6.show();
  strip7.begin();
  strip7.show();
  strip8.begin();
  strip8.show();
}

void loop() {
  //Wait to recieve something.
  if (Serial.available()) {
    //Read the first value as the data line id.
    val = Serial.read();
    delay(10);
    
    //Read the second value as the LED location.
    val2 = Serial.read();
    delay(10);
  }
  
  //If the first value is 101 activate strip1 (data line 2).
  if (val == 101) {
    //Take the second value and turn the respective LED on.
    strip1.setPixelColor(val2, strip1.Color(255,255,255));
    strip1.show();
  }

  //If the first value is 102 activate strip1 (data line 3).
  if (val == 102) {
    strip2.setPixelColor(val2, strip2.Color(255,255,255));
    strip2.show();
  }
  
  //If the first value is 103 activate strip1 (data line 4).
  if (val == 103) {
    strip3.setPixelColor(val2, strip3.Color(255,255,255));
    strip3.show();
  }
  
  //If the first value is 104 activate strip1 (data line 5).
  if (val == 104) {
    strip4.setPixelColor(val2, strip4.Color(255,255,255));
    strip4.show();
  }
  
  //If the first value is 105 activate strip1 (data line 6).
  if (val == 105) {
    strip5.setPixelColor(val2, strip5.Color(255,255,255));
    strip5.show();
  }
  
  //If the first value is 106 activate strip1 (data line 7).
  if (val == 106) {
    strip6.setPixelColor(val2, strip6.Color(255,255,255));
    strip6.show();
  }
  
  //If the first value is 107 activate strip1 (data line 8).
  if (val == 107) {
    strip7.setPixelColor(val2, strip7.Color(255,255,255));
    strip7.show();
  }
  
  //If the first value is 108 activate strip1 (data line 9).
  if (val == 108) {
    strip8.setPixelColor(val2, strip8.Color(255,255,255));
    strip8.show();
  }
  
  //Add one to the counter
  counter=counter++;
  
  //If the counter is at 10000 wipe the board to black.
  if (counter == 10000) {
    for (int i=0; i < 72; i++) {
      strip1.setPixelColor(i, strip1.Color(0,0,0));
      strip2.setPixelColor(i, strip2.Color(0,0,0));
      strip3.setPixelColor(i, strip3.Color(0,0,0));
      strip4.setPixelColor(i, strip4.Color(0,0,0));
      strip5.setPixelColor(i, strip5.Color(0,0,0));
      strip6.setPixelColor(i, strip6.Color(0,0,0));
      strip7.setPixelColor(i, strip7.Color(0,0,0));
      strip8.setPixelColor(i, strip8.Color(0,0,0));
    }
    
    strip1.show();
    strip2.show();
    strip3.show();
    strip4.show();
    strip5.show();
    strip6.show();
    strip7.show();
    strip8.show();
    
    //Reset the counter.
    counter=0;
  }
}

Build

In this section I will briefly describe the build process of the physical Infinity Display.

The frame was made out of MDF and press board wood. I bought these at Home Depot and had them cut to exact size at Min Plastics.

The wood pieces were connected using metal brackets and long wood screws to hold the 3' x 3' structure. The image below represents the front frame.

After the front frame was assembled a 3' x 3' glass piece was placed inside. The glass was bought at Glass Guru and Tinted to become a two-way mirror at TNT Tinting.

Next, the inner frame was assembled and painted black. Depending on the application, black LED strips on a black background help to distinguish the individual pixels.

These bars were screwed into the frame on top of the first glass. I don't have a picture but the next piece of glass was placed above the inner frame. This completed the infinity mirror.

Next, I would construct the housing for the LED display. This was done using a flat piece of press board and 24 rows of balsa wood. I like to use balsa wood as a shelf to keep my LEDs aligned and to also protect them from the frame's pressure.

This was also painted black for the same reason as the inner frame.

The LED strips were glued to the housing. There is no particular reason for the zebra pattern. I simply did not have enough money to buy all black LED strips.

These strips have three pins, power (5V), data, and ground. Each of these were soldered on to flexable wires and color coded for organization.

The mess of wires were bunched using zip ties.

The finished wiring job assembled all power lines into one breadboard and ground into another (parallel). This helps to preserve the life of the LEDs. The eight data lines were placed apart and connected to their respective pins on the micro controller.

The result was a 24 x 24 LED display with functional animations run by a sample processing code.

The finished design was showcased at the 2015 College of Engineering Banquet.