dotmatrixdesign: Twitter LED Scroller Build Log

davidnin1 [ at ] gmail.com
Jan 26
Permalink
Dec 04
Permalink

Here’s 4 seconds of it in action. It should be longer but youtube doesn’t like it for some reason. You can see a few letters of a message.

Permalink
Permalink
Permalink

Then I write a bit of Arduino code:



//Very initial code borrowed from this example:
//**************************************************************//
//  Name    : shiftOutCode, Hello World                         //
//  Author  : Carlyn Maw,Tom Igoe                               //
//  Date    : 25 Oct, 2006                                      //
//  Version : 1.0                                               //
//  Notes   : Code for using a 74HC595 Shift Register           //
//          : to count from 0 to 255                            //
//****************************************************************

//Pin connected to ST_CP of 74HC595
int latchPin = 9;
//Pin connected to SH_CP of 74HC595
int clockPin = 8;
////Pin connected to DS of 74HC595
int dataPin = 11;

int enablePin = 10; //Active Low!

//int col[5] = {6,5,2,3,4};
int col[5] = {4,3,2,5,6};

byte row;

byte pattern[80];

byte frame[5] =  {B00010000,
                  B00010000,
                  B00010000,
                  B00010000,
                  B00010000,
                 };

int i;
int cycles = 0;
int framenum = 0;

int totalframes = 100;

int newline;
int reading_flag = 0;
int readindex = 0;
unsigned long read_timeout;
unsigned long req_timeout = 0;
int nextcheck = 1000;

//——States——
int state = 0;

void setup() {
  //set pins to output because they are addressed in the main loop
  pinMode(latchPin, OUTPUT);
  pinMode(clockPin, OUTPUT);
  pinMode(dataPin, OUTPUT);
  pinMode(enablePin, OUTPUT);

  for(i = 0; i    pinMode(col[i], OUTPUT);
  } 
 
 
    Serial.begin(9600);
}

void loop() {


      for (int j = 0; j  
        //Set all the column registers high, except the columnwe want to show
        for(i = 0; i          digitalWrite(col[i], HIGH);
        } 
        digitalWrite(col[j],LOW);
       
        //ground latchPin and hold low for as long as you are transmitting
        digitalWrite(latchPin, LOW); 
        //disable the outputs while we are shifting
        digitalWrite(enablePin, HIGH);
   
        shiftOut(dataPin, clockPin, MSBFIRST, frame[j]);
        //return the latch pin high to signal chip that it
        //no longer needs to listen for information
        digitalWrite(latchPin, HIGH);
        //enable the outputs
        digitalWrite(enablePin, LOW);
        delay(1);
        //digitalWrite(col[j],HIGH);
       
      }//done displaying frame
     

      if (Serial.available() > 0) {
        newline = Serial.read();
        for (int j = 0; j            frame[j] = frame[j]         }
     
        frame[0] = frame[0] | (newline & 1) == 1;
        frame[1] = frame[1] | (newline & 2) == 2;
        frame[2] = frame[2] | (newline & 4) == 4;
        frame[3] = frame[3] | (newline & 8) == 8;
        frame[4] = frame[4] | (newline & 16) == 16;
     
      }
 
}

Permalink

Then I write a little (okay, a LOT of) Processing code:

import processing.serial.*;


class twit {
  String description;
  int[] bytes = new int[len*5];
  int pxlength;
 
  twit () { 
    description = “”;
    pxlength = 0;
  }

  void update () {
    nextpos = 0;
    for(int c = 0; c       description = description.toLowerCase();
      bytes = addLetter(description.charAt(c), bytes, nextpos+1);
    }
    pxlength = nextpos;
  }
 
  void drawpx (int xref, int yref) {
    for(int x = 0; x        if((bytes[x] & 1) == 1) {point(x+xref, yref+0);}
       if((bytes[x] & 2) == 2) {point(x+xref, yref+1);}
       if((bytes[x] & 4) == 4) {point(x+xref, yref+2);}
       if((bytes[x] & 8) == 8) {point(x+xref, yref+3);}
       if((bytes[x] & 16) == 16) {point(x+xref, yref+4);}
    }
  }
}


int bits=5;
int len=200;

int i = 0, j = 0;
int sqrsize = 5;
int centerx, centery;
float avg;
float bias = .1;
int xpos, ypos;
float h = random(0,255);
int rowint[] = new int[len];
String lines[] = new String[20];
String new_lines[] = new String[20];
twit tweets[] = new twit[20];
int black = 0;
int nextpos = 0;

int next_tw_refresh = 30*60;
int current_twitter = 0;
int next_line = 0;
int rate = 15;

Serial myPort;


void setup()
{
  background(255);
  colorMode(RGB, 255);
  ellipseMode(CORNERS);
  strokeWeight(1);
  noSmooth();
  frameRate(30);
 
  centerx = width/2;
  centery = height/2;

   
  println(Serial.list());
  myPort = new Serial(this, Serial.list()[0], 9600);
 
  for(i = 0; i     tweets[i] = new twit();
  }
 
  update_twits();
 
  size(len*sqrsize, lines.length*sqrsize+1);  // Size should be the first statement 
}

void draw()
{

  background(255);
 
  stroke(255,0,0);
  line(125,0,125,400);

  stroke(0);
  for(int count = 0; count     tweets[count].drawpx(0,count*(sqrsize+1));
  }
 
   if(frameCount > next_tw_refresh) {
     println(“Refreshing messages…”);
     next_tw_refresh = frameCount + 3000; //30 fps x 60 seconds
     print(frameCount);
     update_twits();
   }
  
   if(frameCount > next_line_time) {
      myPort.write(tweets[current_twitter].bytes[nextline]);
      nextline++;
      if(nextline >= tweets[current_twitter].pxlength) {current_twitter++;}
       if(current_twitter >= 20) {current_twitter = 0;}
   }
}

void update_twits() {
  new_lines = loadStrings(“http://linuxbox.dotmatrixdesign.net/~david/twit.php”);
  if(new_lines[0] != lines[0]) {
    lines = new_lines;
    current_twitter = 0;
    for (int i=0; i       tweets[i].description = lines[i];
      tweets[i].update();
    }
    println(“new Twitters downloaded”);
  }
}


void write_to_arduino (twit tosend) {
     myPort.write(‘w’);
     /*for(i = 0; i         myPort.write(byte(tosend.bytes[i]));
        print(tosend.bytes[i]);
        print(” “);
        delay(15);
     }*/
     myPort.write(byte(tosend.bytes));
     print(byte(tosend.bytes));
    println(“sent”);
       
}//end write



int[] addLetter(char letter, int bytes[], int startpos) {
  int col[] = new int[8];
  String colstr[] = new String[8];
  int letter_length;
  String zeros = “000”;
 
  switch (letter) {
    case ‘a’:
      colstr[0] = “11110”;     
      colstr[1] = “00101”;
      colstr[2] = “11110”;
      letter_length = 3;
      break;
    case ‘b’:
      colstr[0] = “11111”;     
      colstr[1] = “10101”;
      colstr[2] = “01010”;
      letter_length = 3;
      break;
    case ‘c’:
      colstr[0] = “01110”;     
      colstr[1] = “10001”;
      colstr[2] = “10001”;
      letter_length = 3;
      break;
    case ‘d’:
      colstr[0] = “11111”;     
      colstr[1] = “10001”;
      colstr[2] = “01110”;
      letter_length = 3;
      break;
    case ‘e’:
      colstr[0] = “11111”;     
      colstr[1] = “10101”;
      colstr[2] = “10101”;
      letter_length = 3;
      break;
    case ‘f’:
      colstr[0] = “11111”;     
      colstr[1] = “00101”;
      colstr[2] = “00101”;
      letter_length = 3;
      break;
    case ‘g’:
      colstr[0] = “01110”;     
      colstr[1] = “10001”;
      colstr[2] = “10101”;
      colstr[3] = “11101”;
      letter_length = 4;
      break;
    case ‘h’:
      colstr[0] = “11111”;     
      colstr[1] = “00100”;
      colstr[2] = “11111”;
      letter_length = 3;
      break;
    case ‘i’:
      colstr[0] = “10001”;     
      colstr[1] = “11111”;
      colstr[2] = “10001”;
      letter_length = 3;
      break;
    case ‘j’:
      colstr[0] = “11100”;     
      colstr[1] = “10000”;
      colstr[2] = “11111”;
      letter_length = 3;
      break;
    case ‘k’:
      colstr[0] = “11111”;     
      colstr[1] = “00100”;
      colstr[2] = “01010”;
      colstr[3] = “10001”;
      letter_length = 4;
      break;
    case ‘l’:
      colstr[0] = “11111”;     
      colstr[1] = “10000”;
      colstr[2] = “10000”;
      letter_length = 3;
      break;
    case ‘m’:
      colstr[0] = “11110”;     
      colstr[1] = “00001”;
      colstr[2] = “11110”;
      colstr[3] = “00001”;
      colstr[4] = “11110”;
      letter_length = 5;
      break;
    case ‘n’:
      colstr[0] = “11111”;     
      colstr[1] = “00010”;
      colstr[2] = “00100”;
      colstr[3] = “11111”;
      letter_length = 4;
      break;
    case ‘o’:
      colstr[0] = “11111”;     
      colstr[1] = “10001”;
      colstr[2] = “11111”;
      letter_length = 3;
      break;
    case ‘p’:
      colstr[0] = “11111”;     
      colstr[1] = “00101”;
      colstr[2] = “00111”;
      letter_length = 3;
      break;
    case ‘q’:
      colstr[0] = “11111”;     
      colstr[1] = “10001”;
      colstr[2] = “11111”;
      colstr[3] = “01000”;    
      letter_length = 4;
      break;
    case ‘r’:
      colstr[0] = “11111”;     
      colstr[1] = “00101”;
      colstr[2] = “11010”;
      letter_length = 3;
      break;
    case ‘s’:
      colstr[0] = “10111”;     
      colstr[1] = “10101”;
      colstr[2] = “11101”;
      letter_length = 3;
      break;
    case ‘t’:
      colstr[0] = “00001”;     
      colstr[1] = “11111”;
      colstr[2] = “00001”;
      letter_length = 3;
      break;
    case ‘u’:
      colstr[0] = “11111”;     
      colstr[1] = “10000”;
      colstr[2] = “11111”;
      letter_length = 3;
      break;
    case ‘v’:
      colstr[0] = “00111”;     
      colstr[1] = “11000”;
      colstr[2] = “00111”;
      letter_length = 3;
      break;
    case ‘w’:
      colstr[0] = “01111”;     
      colstr[1] = “10000”;
      colstr[2] = “01111”;
      colstr[3] = “10000”;
      colstr[4] = “01111”;
      letter_length = 5;
      break;
    case ‘x’:
      colstr[0] = “11011”;     
      colstr[1] = “00100”;
      colstr[2] = “11011”;
      letter_length = 3;
      break;
    case ‘y’:
      colstr[0] = “00111”;     
      colstr[1] = “11100”;
      colstr[2] = “00111”;
      letter_length = 3;
      break;
    case ‘z’:
      colstr[0] = “11001”;     
      colstr[1] = “10101”;
      colstr[2] = “10011”;
      colstr[3] = “10001”;
      letter_length = 4;
      break;
 
 
      case ‘0’:
      colstr[0] = “01110”;     
      colstr[1] = “10001”;
      colstr[2] = “01110”;           
      letter_length = 3;
      break;
     case ‘1’:
      colstr[0] = “00010”;     
      colstr[1] = “11111”;
      letter_length = 2;
      break;
     case ‘2’:
      colstr[0] = “11010”;     
      colstr[1] = “10101”;
      colstr[2] = “10010”;     
      letter_length = 3;
      break;
     case ‘3’:
      colstr[0] = “10101”;     
      colstr[1] = “10101”;
      colstr[2] = “11111”;
      letter_length = 3;
      break;
     case ‘4’:
      colstr[0] = “00111”;     
      colstr[1] = “00100”;
      colstr[2] = “11111”;           
      letter_length = 3;
      break;
     case ‘5’:
      colstr[0] = “10111”;     
      colstr[1] = “10101”;
      colstr[2] = “01001”;           
      letter_length = 3;
      break;
     case ‘6’:
      colstr[0] = “11111”;     
      colstr[1] = “10101”;
      colstr[2] = “11101”;           
      letter_length = 3;
      break;
     case ‘7’:
      colstr[0] = “11001”;     
      colstr[1] = “00101”;
      colstr[2] = “00011”;
      letter_length = 3;
      break;
     case ‘8’:
      colstr[0] = “11111”;     
      colstr[1] = “10101”;
      colstr[2] = “11111”;
      letter_length = 3;
      break;
     case ‘9’:
      colstr[0] = “00111”;     
      colstr[1] = “00101”;
      colstr[2] = “11111”;
      letter_length = 3;
      break;
 
 
    case ’ ‘:
      colstr[0] = “00000”;     
      colstr[1] = “00000”;
      letter_length = 2;
      break;
    case ‘!’:
      colstr[0] = “10111”;     
      letter_length = 1;
      break;
    case ‘.’:
    case ‘,’:
      colstr[0] = “10000”;     
      letter_length = 1;
      break;
    case ‘:’:
      colstr[0] = “01010”;     
      letter_length = 1;
      break;
    case ‘/’:
      colstr[0] = “11000”;     
      colstr[1] = “00100”;     
      colstr[2] = “00011”;     
      letter_length = 3;
      break;     
    case ‘\’:
      colstr[0] = “00011”;     
      colstr[1] = “00100”;     
      colstr[2] = “11000”;     
      letter_length = 3;
      break;     
    case ‘+’:
      colstr[0] = “00100”;     
      colstr[1] = “01110”;     
      colstr[2] = “00100”;     
      letter_length = 3;
      break;     
    case ‘-‘:
      colstr[0] = “00100”;     
      colstr[1] = “00100”;     
      colstr[2] = “00100”;     
      letter_length = 3;
      break;     
    case ‘@’:
      colstr[0] = “11111”;     
      colstr[1] = “10001”;     
      colstr[2] = “11101”;     
      colstr[3] = “11101”;     
      letter_length = 4;
      break;     
    case ‘?’:
      colstr[0] = “00001”;     
      colstr[1] = “10101”;     
      colstr[2] = “00111”;          
      letter_length = 3;
      break; 
    case ‘'’:
      colstr[0] = “00011”;     
      letter_length = 1;
      break;
   case ‘*’:
      colstr[0] = “00010”;     
      colstr[1] = “00111”;     
      colstr[2] = “00010”;     
      letter_length = 3;
      break;  
   case ‘(‘:
      colstr[0] = “01110”;     
      colstr[1] = “10001”;     
      letter_length = 2;
      break;
   case ‘)’:
      colstr[0] = “10001”;     
      colstr[1] = “01110”;     
      letter_length = 2;
      break;      
     
    default:
      colstr[0] = “11111”;     
      colstr[1] = “11111”;
      colstr[2] = “11111”;
      letter_length = 3;
      break;
  }
 
  for(int ch = 0; ch     colstr[ch] = zeros.concat(colstr[ch]);
    bytes[startpos+ch] = unbinary(colstr[ch]);
  }
 
  nextpos = startpos + letter_length;
 
  return(bytes);
}


Permalink
Permalink

So I write a little PHP code


$ch = curl_init();

// set URL and other appropriate options
$test_str = “http://twitter.com/statuses/friends_timeline/davidnin.xml”;
curl_setopt($ch, CURLOPT_URL, $test_str);
curl_setopt($ch, CURLOPT_HTTPAUTH, CURLAUTH_BASIC);
curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
curl_setopt($ch, CURLOPT_HEADER, false);

// grab URL and pass it a string
$str = curl_exec($ch);

// close cURL resource, and free up system resources
curl_close($ch);


if (!$myxml=simplexml_load_string($str)) {
    echo ‘Error reading the XML file’;
}

foreach($myxml as $status){

    echo $status->{‘user’}->{‘screen_name’} . “: ” . $status->{‘text’} . “\n”;

} //end for each status

?>

Permalink
Permalink

And it actually works!

P1030248.JPG

 …with a couple of slight tweaks of course. (note the tiny green and yellow wires)

Permalink
Permalink
Another shot from their confirmation

Another shot from their confirmation

Permalink
You send them your board designs, they send you back a cool acknowledgement generated by their DRC bot.

You send them your board designs, they send you back a cool acknowledgement generated by their DRC bot.

Permalink
Permalink