This project was a collaboration with my roommate, friend, and fellow hacker rishi2. Living in New York, we both use public transportation daily, so we thought it would be cool to have a ticker to display bus and subway times from the internet. This is the result.
1) Arduino Yun Microcontroller - http://www.arduino.cc/en/Main/ArduinoBoardYun?from=Main.ArduinoYUN
Our Yun is requesting messages from our web server over the internet and passing those message to the LED matrices. Both steps of the procedure are coded in a single loop that makes use of different libraries for sending/processing HTTP requests and controlling NeoMatrix matrices.
We started by reading the docs at the link above, then read through this getting started guide: https://www.twilio.com/blog/2015/02/arduino-wifi-getting-started-arduino-yun.html
2) Adafruit Neomatrix LED matrices (3) - https://www.adafruit.com/products/1487
The LED matrices display whatever we send to them from the Arduino. Each matrix has 64 individually addressable pixels that can be set to color on the RGB (255, 255, 255) scale. They are big time fun to play with.
If you want to use them in a project...
Absolute must read: https://learn.adafruit.com/adafruit-neopixel-uberguide/overview
Very helpful tutorial we followed: https://learn.adafruit.com/led-art-with-fadecandy/wiring-your-leds
Components and materials we used...
Tools we used...
Sorry no schematics here yet - will draw and add some hopefully in the next few days.
Two things to point out. First, we wired our matrices for power in a parallel circuit - meaning each matrices was wired for power from the source, rather than passing current from one matrix to the next. Second, we soldered a capacitor between the 5v and ground terminals on our DC power jack. According to the literature, this capacitor protect the LEDs from the initial onrush of current when we supply power.
1) We read the following guide several times https://learn.adafruit.com/adafruit-neopixel-uberguide/power
2) Soldered our capacitor between the + and - terminals of our DC power jack.
3) Soldered wires to the + and - terminals of aforementioned power jack.
4) Split both + and - wires three ways, soldered, and wrapped in electrical tape
5) Soldered a + and - wires to the 5v and ground pads on each NeoMatrix.
Each NeoMatrix board has a data-in pad on one corner and a data-out pad on the opposite corner. The matrices accept a 5v signal via a single wire protocol (you don't need to know much about this to get started - the NeoPixel NeoMatrix code libraries do the heavy lifting here). When tiling, data is passed between matrices from data-out to data-in. One thing to note is the resistor placed before the first matrix's data-in - this supposedly prevents voltage spikes from burning out the first pixel.
1) Soldered a resistor directly to the data input pad on one of the matrices, soldered a wire onto that resistor. This is the wire that connects to whatever pin is outputting data on from you Arduino.
2) Wired the data out pad of the first matrix to the data in pad of the second matrix.
3) Ditto from the second matrix to the third
2) Soldered a wire to the ground pad adjacent to the data in pad. This wire will go to the ground pin on the Arduino.
3) Wired all grounds pads together.
Before mounting our matrices on our stand, we taped them together with some electrical tape. While we were at it, we taped down the wires passing data between the boards and connecting their grounds.
At this point, we were excited to have working LED matrices, knew the info ticker would be housed in our TV cabinet drawer, and didn't want to get bogged down building an elaborate case or mounting system. So, we went the quick and dirty route.
To build our base we...
As we were working on wiring everything up and writing our code, we started thinking about where the info ticker should live. The LED matrices can be extremely bright, so we thought it would be nice to put them behind some glass or plastic to diffuse the light. We looked around our apartment and EUREKA! we saw the frosted-glass-fronted drawers in our TV stand.
In the Arduino world, programs are called sketches. In essence, our sketch only needed to do two things.
1) Make an HTTP request to an endpoint we set up to return a message.
2) Relay that message to our LED matrices in the correct format.
In writing our sketch, we worked mostly from two examples.
1) An example sketch for the Yun makes request to an endpoint and does something with the response
2) An example sketch for the NeoMatrix library that scrolls text across an LED matrix
By mashing those two sketches together, we got our infoTicker sketch.
General design for server software
For the server side code that generates status messages, we used a simple set of PHP scripts. The arduino periodically requests a message from the server to display. We have two types of scripts in our design. "Data gathering" scripts, and a single "Data consolidator" script.
The data gatheringscripts have one task. Whenever they are run, they grab the latest data for something you want to track. For example, say you care about the price of Bitcoin. The data gathering script for Bitcoin price gets the latest price and saves it in a file. Every time it gets the latest price of Bitcoin, it overwrites the contents of the file. The scripts can be run at an interval that you choose.
The data consolidator is run whenever the ticker wants the latest message. It simply looks at all the latest data written by the gathering scripts, consolidates it into one message and echo's it back. This is the message that the Arduino periodically grabs and displays.
The last piece of the puzzle is making sure the data gathering scripts are run as often as you want the data to be updated. (It makes sense to update subway data every minute, but not weather, for example). This is ideally handled by setting up cronjobs on your server, but for a quick and user friendly option we used a service called UptimeRobot. With it, you can configure urls that UptimeRobot will ping at intervals you specify. UptimeRobot automatically made requests from then on, ensuring that the data was updated. The image above shows an screen shot from our UptimeRobot dashboard.
In our case, we cared about 5 things:
1. What is the weather forecast?
2. When does the next subway train depart from the station around the corner?
3. How far away are certain busses from the stop around the corner?
4. What is the latest price of Bitcoin?
5. How many CitiBikes (New York Bike Share program) are available at the bike stand around the corner?
You can choose to display whatever you care about on your ticker. The only requirement is that you can get that data programmatically somehow. For each of the items above we wrote a data gathering script.
Writing the data gathering scripts:
1. Identify a data source / API.
2. Make a request to that data source.
3. Parse and extract the part you care about
4. Write it to specific, hard coded location on the server. The consolidator script will read from this location.
The image above shows a sample php script that grabs bitcoin price data.
Writing the data consolidator script:
1. Read from all of the data sources.
2. Consider generating a date and time to add to your message.
3. Mash them together into a simple text that you want to display.
In our case the output from the data generator script was something like this: Monday, May 18 2015 22:54:59. Light rain starting later tonight. 59F, Rain: 0%, Wind: 4mph. Subway: A train departs 10:57pm. Bus (Stops Away) B25: 9 B44: 1. BTC: $233. Citibikes: 11.
The arduino code controls how often you will call this script for an update. You will hard code the url of the consolidator script in the arduino code.
The image above shows a sample php script that consolidates data and produces a message.
There are three main reasons for this design.
1. Allows us to independently control how often each data source is updated.
2. The latest data is already available when the consolidator tries to get it. If the gathering scripts and consolidator script were in one big script it would take longer to generate each message. The image above shows how long it takes to get our bus data. By having the data gatherer separate in this case we save upto 2.5 secs everytime we load the message.
3. If a data gathering script fails, the consolidator does not fail and text is still generated. This is a high level overview of what we did and why, but ultimately this part of the project would work with any code that outputs text whenever run.
If you want to see our actual code, check out the repo on github: https://github.com/rgho/infoTickerServerPHP
The authors at work.
Thanks for reading!