Arduino LED Startup Counter

Intro

Since we were out of commission during the Chinese New Year, I thought I’d get around to a project that I’ve always wanted to do, and that would help motivate the Nix team. In this post, I will give you step-by-step instructions on how to build your own Arduino-powered, internet-connected LED matrix display.

The display can connect to the internet and pull data from various sources like the weather, stock prices, news feeds etc. Since we are building this for the Nix office, we are going to set it up to display our Facebook Likes, Twitter followers, and our “startup ranking”.

The Brain of the Project

The brain of the LED display will be the Arduino Leonardo. I picked this particular device because it’s quite powerful. I had a few lying around, and it uses the same microprocessor found in the Nix Color Sensor! (www.nixsensor.com) Here are some specs taken (copied directly) from the official Arduino page (http://arduino.cc/en/Main/arduinoBoardLeonardo). Note* Always support the Arduino Team by buying from an official distributor.

Overview

The Arduino Leonardo is a microcontroller board based on the ATmega32u4 (http://www.atmel.com/devices/atmega32u4.aspx). It has 20 digital input/output pins (of which 7 can be used as PWM outputs and 12 as analog inputs), a 16 MHz crystal oscillator, a micro USB connection, a power jack, an ICSP header, and a reset button. It contains everything needed to support the microcontroller; simply connect it to a computer with a USB cable or power it with a AC-to-DC adapter or battery to get started. The Leonardo differs from all preceding boards in that the ATmega32u4 has built-in USB communication, eliminating the need for a secondary processor. This allows the Leonardo to appear on a connected computer as a mouse and keyboard and a virtual (CDC) serial / COM port. It also has other implications for the board’s behavior; these are detailed on the getting started page.

Specs

Microcontroller

ATmega32u4

Operating Voltage

5V

Input Voltage (recommended)

7-12V

Input Voltage (limits)

6-20V

Digital I/O Pins

20

PWM Channels

7

Analog Input Channels

12

DC Current per I/O Pin

40 mA

DC Current for 3.3V Pin

50 mA

Flash Memory

32 KB (ATmega32u4) of which 4 KB used by the bootloader

SRAM

2.5 KB (ATmega32u4)

EEPROM

1 KB (ATmega32u4)

Clock Speed

16 MHz

Communications

Our LED display will need two main methods of communication: hardware serial and a network connection. We will also use the USB software serial port on the Arduino for debugging. The hardware serial connection will be used for communicating with the LED matrix control IC. The network connection polls data from the internet to populate the display. Hardware serial is a built-in feature of the Arduino Leonardo, so we have that covered. However, how do we connect to the internet? It seems like a tough task at first, but luckily, the Arduino team has us covered once again with the Arduino Ethernet Shield. (http://arduino.cc/en/Main/ArduinoEthernetShield) The Arduino Ethernet Shield snaps on top of the Arduino Leonardo and provides an Ethernet jack and an SD card slot (for saving larger amounts of data). Having all the hardware in one relatively small package is great, but the software libraries that Arduino provides make it such a stellar product. All you have to do to get up and running is:

  1. Install the Arduino IDE
  2. Plug in the Arduino Leonardo VIA USB
  3. Let the drivers install automatically (On Windows at least)
  4. Pop on the Ethernet Shield
  5. Load the example sketch named “WebClient”
  6. Program the Arduino!
  7. Plug in your Ethernet cable.
  8. Open the serial monitor in the Arduino IDE
  9. Watch in amazement as your Arduino spews data from www.google.com to your serial monitor.

It’s that easy!

Modifying the Example Code

Although the example code was super cool and it shows you how fast you can get connected to the internet with an Arduino, for our particular example we would like to get information from other sources so we are going to have to modify the code. Luckily, this part is fairly easy as well. I’ll show you an example using Twitter.

Ex.

Recently Twitter has made a move to secure all traffic to and from its servers. This is great for everyday users ,but since the Arduino Ethernet library doesn’t support secured connections, we can’t connect to Twitter directly. We will have to connect to an affiliate site where the data we are looking for is still available. I’m using http://twittercounter.com/nixsensor, and it works out better than twitter.com because it keeps track of daily changes in our follower count, so I don’t have to! Find the code below in the example Arduino sketch.

 // if you don’t want to use DNS (and reduce your sketch size)

// use the numeric IP instead of the name for the server:

//IPAddress server(74,125,232,128);  // numeric IP for Google (no DNS)

char server[] = “www.google.com”;    // name address for Google (using DNS)

This is where the server address to which the Arduino will attempt a connection is located. Modify the code for twitter by replacing www.google.com with www.twittercounter.com. I will use:

 char server[] = ” www.twittercounter.com”;

Now that the Arduino knows where to attempt a connection, we also have to make sure that it knows what to “ask for” from the server. Find the code below in the example Arduino sketch. // Make a HTTP request:

  // Make a HTTP request: client.println(“GET /search?q=arduino HTTP/1.1”); client.println(“Host: www.google.com”); client.println(“Connection: close”); client.println();

What you see here is actually a HTTP GET request (http://en.wikipedia.org/wiki/Hypertext_Transfer_Protocol) We need to modify the request to ask for the nixsensor page. The modification looks like this:

 client.println(“GET /nixsensor HTTP/1.1”); client.println(“Host: twittercounter.com”); client.println(“Connection: close”); client.println();

The code asks the server to “GET” the page at /nixsensor If all goes well you should receive a massive (1000+ lines) of code from the server and it should display on your serial monitor. Awesome!

Saving and Parsing Data

Now, the problem is that the Arduino itself can’t store the massive amount of data received from the server. We are going to have to use the on board SD card to save incoming data to be parsed later… or are we…? I stumbled across the TextFinder library (http://playground.arduino.cc/Code/TextFinder) which allows you to parse streams of data live. It’s great, but it has just one problem: it doesn’t use a buffer, and that means it can’t parse backward. This means we will have to find a unique identifier for our relevant information that comes before the actual information. It could be tough… let’s give it a try. First you have to view the source code of http://twittercounter.com/nixsensor. You can go about this 2 ways, the first is through the Arduino Serial Monitor (in the previous step) and the second (fastest and easiest) way is through your browser. (Right-click and then view the page source in Chrome) Once you have the source code open, you have to find the location(s) where the data you are looking for resides.

 <div class=”col2 left”> <section class=”clr margin-s” id=”main-stats”> <div class=”left stat-item up”> <i class=”ss-up”></i> <span class=”counter num”>1,689</span> <span class=”metric”>Followers</span> <span class=”mutation”><b> +5 </b> yesterday</span>

I found that

  <div class=”col2 left”>

occurs only once and right before the number of followers (1,689) and the daily change in followers (+5). Now we have to include and set up the TextFinder library. First, we include the header file with:

 #include <TextFinder.h>

Then we use:

 TextFinder finder( client );

before setup() is called. Finally we have to actually implement the parsing algorithm seen here.

  if (client.connected())

 {

    long followers = 0; // reset follower count

    long changeInFollowers =0; // reset changeInFollowers count

    if(finder.find(“<div class=\”col2 left\”>”))

    {

      if(finder.find(“\”counter num\”>”))

      {

       followers = finder.getValue(‘,’); //remove any commas in number

       if(finder.find(“<b>”))

         {

           changeInFollowers = finder.getValue(‘+’); //Skip ‘+’ symbol (‘-‘ is automatically used to make number negative) this might break if over 999 new followers because doesn’t check for commas

         }

      }

         ////PRINT OUT DATA/////

         Serial.print(followers);

         Serial.print(” Followers Change:”);

         Serial.println(changeInFollowers);

        }

  }

This little chunk of code is actually quite simple. After checking to see if the client is successfully connected the algorithm looks for the unique string “<div class=\”col2 left\”>”. This signifies that we are in the vicinity of our desired data. We then look for “\”counter num\”>” (notice the use of \” we use the backslash character to allow the use of quotes within the string). Since “\”counter num\”>” is right before the number of followers we then call finder.getValue(‘,’); which retrieves the number of followers and removes any commas that might be present. Finally we look for the <b> tag which comes right before the value of the change in followers for the day. Since this value could have a ‘+’ or ‘-‘symbol preceding it we must call finder.getValue(‘+’); This removes the ‘+’ and also inherently takes into account negative numbers. We then print the data out VIA the USB Serial port for testing.

 connecting… connected 1688 Followers Change: 4 disconnecting.

Sweet! Everything works!

Timing

At the moment our code only runs one time right after connection to the serial port. This is great for testing, but we want the code to update on a regular basis to eventually update the LED display. To do this, we must use a timer interrupt. After including

 #include <TimerOne.h> 

at the beginning of our code we initialize Timer1 with:

 Timer1.initialize(10000000); // in us = 10 Seconds Timer1.attachInterrupt(setFlag); //Calls setFlag() when interrupt is triggered

The interrupt code is run within an interrupt service routine. In general I like to keep the code inside the interrupt service routine as short as possible and get back to the main loop ASAP. Since we would like to poll the HTML sources at a slower rate than 10 seconds (the interrupt timing) we increment a counter within the ISR which in turn raises a flag when a predetermined amount of 10 second increments have passed. In our case the counter is set to raise the flag after 60, 10 second increments have passed or, 10 minutes of time has elapsed.

 void setFlag()

{

  if(counter>=60)//60*10s = 10 min

  {

    intFlag = true; // flag is set to false in main loop

    counter=0; //reset counter

  }

  counter++;

}

In the main loop I’ve wrapped the entire HTML GET and parsing algorithm in an if statement checking the status of the flag as seen below.

if(intFlag==true)

{ Serial.println(“in interrupt routine”);

  //GET the HTML Data and parse////////////

   if (client.connected())

 {

    long followers = 0; // reset follower count

    long changeInFollowers =0; // reset changeInFollowers count

    if(finder.find(“<div class=\”col2 left\”>”))

    {

      if(finder.find(“\”counter num\”>”))

      {

       followers = finder.getValue(‘,’); //remove any commas in number

       if(finder.find(“<b>”))

         {

           changeInFollowers = finder.getValue(‘+’); //Skip ‘+’ symbol (‘-‘ is automatically used to make number negative) this might break if over 999 new followers because doesnt check for commas

         }

      }

         ////PRINT OUT DATA/////        

Serial.print(followers); Serial.print(” Followers Change:”); Serial.println(changeInFollowers);

    }

  }

  ////////////////////////

  intFlag=false;//reset the interrupt flag

}

Display

Now that we have our data pulled from the internet VIA HTML and parsed through our algorithm, it’s time to display the information in an easy-to-read and fun way. Previously we have been using the serial port (boring); now it’s time to move our code over to the LED matrix display! I decided to use a prebuilt 80×8 pixel display fromwww.embeddedadventures.com/LED_matrix_display_LDP-8008.html . It’s relatively cheap and most importantly has an available hardware display driver (www.embeddedadventures.com/led_matrix_display_driver_plt-1001v4.html). The display driver is essential for our project because it takes care of all the heavy lifting regarding updating and controlling the display. Without the driver, the code needed for the multiplexing and font algorithms for such a large display would probably take up most of the Leonardo’s memory and can be quite complicated. After soldering a few headers on the display driver and connecting to the display I also wired up the 5v power rails to a USB cable that I cut off one end and stripped the wires. Since the display is quite large, I had to find a high-power USB charger (over 2.5A) to connect to the USB cable. I then connected the Arduino and Ethernet shield to the back of the display with 3M VHB double-sided tape (powerful stuff, worth checking out). Finally, I wired the Arduino to the display driver by connecting pins 2 and 3 (TX and RX) to the opposite pins labeled on the display driver. (TX to RX, RX to TX). The LED matrix driver board takes commands in the form of text sent at 115200 baud over the hardware serial port. These signals are sent at 5v so no voltage translation is needed. I found that the commands were unintuitive and suffered horribly from overflow if large strings were sent too fast. I quickly put together a library of basic functions HERE if anybody is interested. The last thing we have to do is build the display algorithm. Most of this consists of building strings with the relevant data, writing these strings to the display, pausing between writes, and clearing the display. (All taken care of by my library). The display code is run within the main function so that it is constantly updating the display in a patterned loop. Only when the timer interrupt is triggered does the loop stop (briefly) while new data is collected and updated. The code looks something like this:

 ///////////TWITTER/////////// clearText(); writeText(” TWITTER”,2,2); delay(PAUSETIME);clearText(); writeText(“FOLLOWERS: “,2,2); delay(PAUSETIME);

String followerString =””; char followerStringBuff[20];

if(changeInFollowers >0){ clearText(); followerString = followerString + followers +” (+”+ changeInFollowers + “)”; followerString.toCharArray(followerStringBuff,20); } else{

clearText(); followerString = followerString + followers +” (“+ changeInFollowers + “)”; followerString.toCharArray(followerStringBuff,20); }

clearText(); writeText(followerStringBuff,2,2); delay(PAUSETIME);

Try it out yourself and fool around with spacing and different data types.

Results

As you can see, the display came out quite nicely. The code is stable, and the build is neat and tidy. It shouldn’t look too out of place on my bookshelf 😉

 

 

Conclusion

Building your own Arduino-powered, internet-connected display can be a great weekend project for an intermediate maker. With some off-the-shelf parts combined with a cool display, the build process is mostly a software one, and thanks to the Arduino team, most of the hard work has been taken care of for us. I’ll leave it to you, the reader, to modify the code in this post to build your own project. Maybe a stock ticker that dispenses candy if your portfolio is down for the day? Or a confetti launcher that goes off after 10,000 Facebook likes?