Raspberry Pi Scrolling Sign

by BigjBehr in Circuits > Raspberry Pi

27412 Views, 51 Favorites, 0 Comments

Raspberry Pi Scrolling Sign

DSCN1988

This project is for a Raspberry Pi controlled scrolling sign using a 32x64 matrix of RGB LEDs. The sign scrolls information on two rows. The upper row shows current time and date. The lower row shows; jokes, quote of the day, weather information, environment information, headlines, birthday greetings and holiday greetings. A BME280 environmental sensor array is used to obtain temperature, humidity and barometric pressure information. The birthday and holiday greetings are read from two .xml files that you can edit to add the birthdays, holidays and greetings of your choice. Everything else is obtained from various web sites.

RGB LED matrices come in a variety of pixel sizes, pixel densities and interface configurations. Pixel size refers to the number of rows and columns of RGB LEDs. Pixel density refers to how close the RGB LEDs are to each other. The pixel density of a display is stated by a 'Pn' designation. P4 refers to a display with 4mm spacing between the RGB LEDs. Lower 'P' numbers are higher density. The lower the 'P' number, the closer you can view the display. If you are too close then your eye will not blend the pixels properly. For this project you will need an RGB LED matrix with a Hub75 (the most common) interface. The Hub75 interface defines the connector used, the signals used and the wiring. I used a 32x64 pixel matrix with 4mm density (P4-64x32-16S). The matrix has 32 rows with 64 columns of RGB LEDs. This type of matrix can be purchased from Adafruit or on Ebay. The driver library used can handle longer displays (more columns or fewer columns) and can drive up to three displays. I chose to limit it to one display with a maximum of 32 rows.

Adafruit sells a HAT for the Raspberry Pi for controlling a Hub75 RGB LED matrix. I chose to design my own board to mate with a Raspberry Pi Zero W (RPiW). My board has all of the GPIO pins not used to drive the matrix broken out to headers. The I2C and Console (Serial) ports are also broken out. An optional 3.3V regulator can be added if you need more power for peripherals. Except for the matrix driver library, all the coding was done using Python. My Hub75 interface board will work with any Raspberry Pi with a 40 pin GPIO header. However, if used with a Raspberry Pi other than an RPiW there may be interference issues. You may have to leave out the unused GPIO headers or swap them for right angle headers. Why use a $35.00 Pi when a $10.00 Pi will do the job? If you do not use an RPiW then you will need to add a USB WiFi dongle and possibly an adapter to convert it to micro USB. WiFi dongles and adapters are cheap, but when you add it to the cost of the Raspberry Pi you might as well buy the RPiW.

The driver for the RGB LED Matrix drives two rows of RGB LEDs at a time. All of the rows are time multiplexed to yield the display. This means that at any given point in time, only two rows of LEDs are drawing current. Each pixel consists of three LEDs. One red, one green and one blue. Each individual LED in a pixel draws approximately 20mA when lit up. So each pixel will draw around 60mA if all three LEDs are turned on. Multiply that by the number of pixels in a single row (64 in my case) and you get a maximum current per row of 3840 mA or 3.84 Amps. Multiply that by two because two rows are driven at the same time and the maximum current jumps to 7.68 Amps. Bottom line, if every LED on the display is being told to be on then it will draw in the neighborhood of eight Amps. This calculation does not take into consideration the power requirements of the Raspberry Pi used. An RPiW needs about 180mA when using WiFi, So an 8 Amp @ 5V power supply will suffice. A full sized Raspberry Pi 2 or 3 requires around 2.5Amps. You would need a 10Amp power supply for a full sized Raspberry Pi. Keep in mind that this represents a worst case scenario. For a scrolling sign most of the LEDs are turned off so you should be able to use a lower rated supply. But, do you really want your display to mysteriously reset because too many LEDs are turned on?

The amount of work to build one of these scrolling signs depends a great deal on what parts you buy. For the Adafruit Hub75 HAT, all you need to do is solder a few connectors in place. If you decide to build one of my boards then you will need to be skilled at hand soldering surface mount components. Or you can decide to use the schematic of my board to hand wire a Hub75 interface board. I highly recommend using someone's Hub75 interface board because the RGB matrices are 5V and the RPi is 3.3V. Adafruit's board and my board use level shifters to convert the RPi's 3.3V signals to 5V for the matrix.

Configuring the RPi for WiFi, auto boot into the Python script, installing the matrix driver library and installing the Python libraries used can be a daunting task. I have laid out step by step instructions for doing this that should make it fairly easy to do. This project assumes that you are familiar with using Putty and WinSCP or equivalent programs and working with the Linux command line.

What You Will Need to Build One

DSCN1873.JPG
DSCN1872.JPG
DSCN1881.JPG
Top Full marked up.jpg
DSCN1868.JPG
Brick 8A.jpg
BME280 face.JPG
  • A Raspberry Pi Zero W.
    • If you are using another Raspberry Pi then you will also need;
      • A USB WiFi dongle compatible with the Raspberry Pi.
      • if using a Raspberry Pi Zero, a micro USB to full size USB adapter.
  • A micro SD card with a capacity of at least 4GB.
  • A micro SD to full size SD card adapter or an SD card reader/writer that can accept a micro SD card.
  • A USB cable with a micro USB connector on one end. This is used only during setup and development.
  • A 32x64 RGB LED matrix display with a Hub75 interface.
    • any RGB LED matrix that has 16 or 32 rows and a Hub75 interface.
  • The power harness that came with the RGB LED matrix. The flat cable is not used.
  • A 5V, 8 Amp minimum power brick.
    • 5V, 10Amp power supply if using a full sized Raspberry Pi.
  • Power jack that mates with your power supply.
  • A Hub75 interface board that accepts a Raspberry Pi 40 pin connector.
    • Adafruit sells one
    • I designed my own for this project. Mine has the unused GPIO broken out to headers as well as headers for SPI, Serial and I2C. See BOM for my board or if you hand wire your own
  • Four optional 2.5x11mm standoffs.
  • Eight optional 2.5x6mm screws for the standoffs.
  • Optional, for obtaining environmental information.
    • BME280 sensor array board.
      • Two, four pin DuPont shells.
      • Eight DuPont female crimps.
      • Four lengths of 22-28 awg stranded wire.
      • Or you could use four female to female jumper wires

RGB LED Matrix displays are available on Ebay or from Adafruit. Just make sure it uses a Hub75 interface. You can buy a ready to run Hub75 interface board from Adafruit. They sell one for the Raspberry Pi and one for the Teensy. As this is a Raspberry Pi project, buy the one for the Raspberry Pi. I have included the Eagle files needed to have one of my custom Hub75 interface boards manufactured. I use AllPCB.com to have my boards fabricated. As of this writing, AllPCB.com is charging $5.00 with free shipping to the USA for ten boards. The last order that I placed took about ten days from time of order to delivery to my door. Of course, if you are truly adventurous, you can hand wire your own board from the PDF of the schematic. I also have some rev 1.1 boards left over from my order and some rev 1.0 boards. Contact me if you are interested in a blank board.

A 32x64 RGB LED matrix requires at least an 8 Amp power supply. If you decide to daisy chain in a second or third matrix to extend the length of the display, you will need an additional 8 Amps for each 32x64 panel that you add.

Matrix display panels are specified by the pixel (tri-color LED) density, number of columns and rows. A P4-64x32-16S display has a pixel spacing of 4mm. A P5-32x16-8S display has a pixel spacing of 5mm. Displays with a lower pixel density (higher P number) require a greater viewing distance for the human eye to blend the pixels. They are also usually a little less expensive. The display shown above is a P4-64x32-16S. The pixel density will also determine the actual physical dimensions of the display. The -16S indicates the number of rows that can be selected, 16S indicates 16 rows (four signals), 8S indicates 8 rows (three signals). It also indicates that the refresh is done 16 or 8 times for per panel. A panel has an upper and a lower half with one row from each half being refreshed simultaneously. So -16S is a 32 row panel and -8S is a 16 row panel.

Hub75 Interface Board BOM

DSCN1943.JPG
40 pin cut down.jpg
optional headers.jpg
DSCN1959.JPG
regulator.jpg

You can ignore this if you purchased the Adafruit Hub75 Interface board. If you are hand wiring your own board then you may want to use through hole parts instead of the surface mount parts called for. In that case consider this more of a guideline. The BOM is detailed as two assemblies, a bare minimum and the ad-hoc optional assemblies. The first picture above shows the minimum parts required.

Minimum Build:
Reference - Description ------------------------- Mouser P/N ------------- Digikey P/N
TB1       - 2 position Terminal block, 5mm pitch, 651-1792863,      $0.30, 277-2518-ND,   $0.30
IC1, IC2  - 74HC245DWR,                           595-SN74HC245DWR, $0.50, 296-1197-1-ND, $0.52
J9        - 2 - 1x20 Socket strips,               855-M20-7822046,  $1.90, 952-1905-ND,   $1.89
J8        - 2x10 Socket                           855-M20-7830546,  $1.38, 609-3573-ND,   $1.43

The BOM calls out for 74HC245DWR. Any part 74*245DWR will work. So 74LS245, 75ALS245 or 74AHC245 will all work. The important thing is that it is 74xxx series, 245 (indicates an octal bus transciever) and that the wide surface mount package is used (DW indicates SOIC-20W package). CMOS (HC or AHC) is preferred over TTL (LS or ALS).

If you do the minimum build and leave out the AS1117-3.3 regulator then you need to solder a jumper wire to the two holes of J18. Doing this allows the 3.3V from the Raspberry Pi to connect with the 3.3V pins of the I2C headers and the 3.3V header associated with the unused GPIO. Leave the jumper out if you add the AS1117-3.3 regulator. When the jumper is left out the AS1117-3.3 handles the load for the added peripherals. It prevents overloading the Raspberry Pi's 3.3V regulator.

For the minimum build you should also place a jumper from the center pin to either of the outer pins of J11. This jumper selects 32 row or 16 row operation. Place the jumper to correspond with the RGB LED matrix that you are using. If you leave out the jumper then your display will look very weird. In place of a wire jumper, you could add a three pin post strip and then use a two pin shorting plug to select 32 or 16 rows.

Tip: You may find that you can save about a dollar by using two 2x10 sockets for J9 instead of two 1x20 socket strips.

Tip: Buying all your parts from one vendor will save you shipping costs.

Tip: I prefer to buy forty pin female socket strips and cut them down to the size that I need. You sacrifice one position each time you make a cut, so a forty pin strip will not yield two twenty pin strips. However, two forty pin strips, each cut twice (cut at 21 then cut the 19 pin piece at 11), will yield two twenty pin strips, two ten pin strips and leave you with two eight pin strips to use someplace else. After cutting I like to use a small file to cleanup the cut end. The second picture above shows a 40 pin strip that has been cut into a 20 pin strip and a 19 pin strip (red box). The green box shows a 19 pin strip and the 10 pin and 8 pin strips that result from cutting it down.

Adafruit sells several 2x20 female headers. They vary in height (8.5mm or 13mm) and in the length of the solder pins. Stacking connectors have extra long pins so that you can stack another HAT on top. For this project, the standard 2x20 female header (Adafruit P/N 2222, $1.50) is the best choice. If you buy the 13mm version then you will need to get longer standoffs (13mm instead of 11mm).

A 2x10 socket is used to mate with the display because it fits into the shroud that surrounds the 2x8 post strip on the display. The extra pins on each side prevent you from mis-aligning the connectors.

The rest of the parts are optional and add to the minimum build. You can add what you need for your project. I like to buy forty pin snap-apart post strips in black, red and yellow. I then break them apart into the sizes that I need. Of course you can use all black, but I find it very convenient to use black for ground, red for power and yellow or some other color for the signal.

Reference   - Description
J1, J2, J3  - four pin post strips         - I2C headers
J4          - three pin post strip         - Console or Serial port header
J5,         - nine pin post strip, yellow  - Unused GPIO header
J6          - nine pin post strip, black   - GPIO Ground header
J7          - nine pin post strip, red     - GPIO Power (3.3V) header
VR1         - AS1117-3.3                   - 3.3V, 1A regulator
C1, C2      - 10uF tantalum capacitors     - Used to stabilize the AS1117-3.3 regulator

Optionally, you can use three row, right angle post strips for the I2C and GPIO headers. The advantage of using the right angle headers is that they will not interfere with the USB adapter and WiFi dongle if you are using a Raspberry Pi Zero. The right angle headers can be mounted on what ever side of the board is convenient for you.

Tools Needed:

  • Hardware tools
    • Screwdrivers, Philips and flat blade
    • Wire cutters
    • Wire strippers
    • Soldering Iron & solder, preferably with 'No Clean' flux
    • HDMI monitor
    • mini HDMI adapter
    • keyboard
    • micro USB adapter
    • 5V power supply
    • Internet connection for downloading files

The SD card formatter is used to erase & format an SD card to give you a 'clean slate' to work with. The SD card imager is used to put a bootable image of the operating system (a .img file) onto your newly formatted SD card. Putty allows you to use SSH to talk to your Raspberry Pi through its WiFi or Ethernet connection. With Putty and SSH you can operate and monitor your Raspberry Pi from a window on your PC. WinSCP allows you to copy files from your PC to your Raspberry Pi. WinSCP provides a drag and drop GUI for you to transfer files and view the directory structure of your Raspberry Pi and your PC.

Setup the Raspberry Pi

HDMI adapters.jpg
USB adapters.JPG
RPi0 - cables.JPG
bad fit - before.JPG
bad fit - after.JPG
good fit.JPG

The good folks over at www.raspberrypi.org have spent a lot of time and effort making simple to understand, detailed instructions on how to setup your Raspberry Pi and what you will need to do it. They have done a much better job of this then I can. Use the following links to setup your Raspberry Pi;

Here is where we run into a little trouble. The guide on connecting your Raspberry Pi to a monitor, keyboard and mouse assumes that you have a full sized Raspberry Pi 2 or Raspberry Pi 3. The Raspberry Pi Zero and Raspberry Pi Zero W have only one USB port and it has a micro USB connector. The HDMI connector is a mini HDMI and not a full sized HDMI connector. So there are some differences in what is needed and how things are attached. In addition to what was listed on the Raspberry Pi web site, you will also need the following;

  • A full sized female HDMI to male mini HDMI adapter
  • A full sized female USB to male micro USB adapter
  • As we will be running headless, a mouse is not required
  • If you are using a Raspberry Pi Zero, a USB WiFi dongle will be required
  • To power your Raspberry Pi you will need either;
    • To take power from your computer; a USB cable with a micro USB plug at one end
    • To power from a wall socket; a 5V power pack with a micro USB on the end of the cable or an old 5V phone charger with a USB cable with a micro USB plug at one end.

The first picture above is of two styles of mini HDMI adapter. One is a simple plug and the other is a short cable. The second picture is of two styles of micro USB adapter. The third photo is a picture of a Raspberry Pi Zero. I have drawn red circles around where to plug in your power, keyboard, monitor and micro SD card. The micro USB plug adapter in the photo above works quite well, but is a little too big to plug in a micro USB cable into the adjacent micro USB power jack (see fourth photo above). As a result, I filed down the side of the adapter until everything fit nicely (see fifth photo above). The cable style micro USB adapter does not have this problem.

Configure the Raspberry Pi

Once you have your Raspberry Pi up and running the Raspbian Stretch Lite operating system it is time to configure your system. You need to enable the I2C interface, SSH, select your language and keyboard layout, select your timezone and configure WiFi to access your home network and set the WiFi for your country. Most of this is done using raspi-config. Setting up to work with your home network involves editing of a configuration file.

The easiest way to run raspi-config on your Raspberry Pi zero or Raspberry Pi Zero W is to use a keyboard and monitor. If you have a full sized Raspberry Pi you can put the SD card into that Raspberry Pi and then use a keyboard and monitor or plug in an Ethernet cable and SSH into the Raspberry Pi using Putty or connect a USB-to-Serial dongle to the console RX & TX pins and use a terminal program on your computer to run raspi-config.

Use this link for how to use raspi-config

Tip: You can use a full sized Raspberry Pi to configure an SD card to be used in a Raspberry Pi Zero or W. Once the configuration is complete, power down the Raspberry Pi , remove the SD card and plug it into the Raspberry Pi of your choice.

Tip: When using raspi-config, Internationalization Options to change your Locale you must first deselect the default locale (en_GB.UTF-8 UTF-8) before you change to your locale. The selected locale is identified by an asterisk between square brackets ([*]). You deselect the locale by using the arrow keys to move the cursor to the currently selected locale and then press the space bar. The asterisk should disappear. You select a locale by using the arrow keys to move the cursor to your selection and then press the space bar. The asterisk should appear. You can select multiple locales. However, if you do then when you exit, you will find that the default locale is still selected. Until you deselect the default locale your selection of another locale will not 'stick'. If you live in the USA then select en_US.UTF-8 UTF-8.

Configure WiFi for Your Home Network

To do this step you will need to know the SSID (name of your home network) of your home WiFi network and the WiFi passkey. If your WiFi network is not using some form of encryption (a very bad idea) you will not need a WiFi passkey. The WiFi passkey is not the same as your WiFi router's password. One allows you to use your WiFi network and the other allows access to your router to configure it.

To enable WiFi on a Raspberry Pi you have to edit the file /etc/wpa_supplicant/wpa_supplicant.conf and add some lines at the bottom of the file.

At the prompt, type; sudo nano /etc/wpa_supplicant/wpa_supplicant.conf

Use the Arrow keys to go to the bottom of the file.

Add the text below, replacing "yourssid" with the SSID of your home WiFi network and replacing "yourpasskey" with the WiFi passkey for your home network

network={
	ssid=”yourssid”
	psk =”yourpasskey”
}

Press Ctrl-O, Enter, to save the file, Ctrl-X to exit.

If you are using a full sized Raspberry Pi or a Raspberry Pi Zero to configure the SD card then type; sudo poweroff

Wait for the Raspberry Pi to finish powering off, then plug in the USB WiFi dongle and power your Raspberry Pi back up.

If you are using a Raspberry Pi Zero W then the WiFi is built-in, type; sudo reboot instead.

Once the Raspberry Pi has finished booting, type; ifconfig

You should see something like the following;

<p>pi@StretchLite:~ @ ifconfig<br>io: flags=73 mtu 65536
        inet 127,0,0,1  netmask 256.0.0.0
        inet6 ::1  prefixlen 128  scopeid 0x10
        loop  txqueuelen 1  (Local Loopback)
        Rx packets 0  bytes 0 (0.0 B)
        RX errors 0  dropped 0  overruns 0 frame 0
        TX packets 0  bytes 0 (0.0 B)
        TX errors 0  dropped 0 overrun 0  carrier 0  collisions 0
        
wlan0: flags=4163 mtu 1500
        inet 192.168.0.157  netmask 256.255.255.0  broadcast 192.168.0.255
        inet6 fe80::5c97:56f0:9dac:e5ac  prefixlen 64  scopeid 0x20
        ether 74:da:38:62:93:66 txqueuelen 1000 (Ethernet)
        Rx packets 127 bytes 28722 (28.0 KiB)
        RX errors 0  dropped 19  overruns 0 frame 0
        TX packets 90  bytes 16874 (16.4 KiB)
        TX errors 0  dropped 0 overrun 0  carrier 0  collisions 0</p><p>pi@StretchLite:~ @ ifconfig</p>

wlan0: is the Linux name of your WiFi dongle.

inet 192.168.0.157 is the IP address of your WiFi dongle (Raspberry Pi).

ether 74:da:38:62:93:66 is the MAC address of your WiFi dongle.

These values for IP and MAC address are for my WiFi dongle on my network. Yours will be similar, but different. If you do not have a wlan0: or no IP address then something is wrong. Make sure that your WiFi dongle is plugged in to the correct micro USB connector. Check the file /etc/wpa_supplicant/wpa_supplicant.conf and make sure that you entered your WiFi network SSID and passkey properly. If everything looks correct, but still does not work, try a different WiFi dongle. The one you have may not be compatible with the Raspberry Pi.

If all is good then your Raspberry Pi configuration is complete. What I like to do at this point is to put the SD card back into the reader and make a backup image of the configured system. Then the next time a need a fresh SD card I can just use the backup image and the system will be all configured once the SD card is written. I name the image files with the capacity of the SD card, the version of Raspbian, the country and WiFi if added. For example an image on an 8GB SD card would be named; Stretch lite WiFi USA 8GB.img. Of course you are free to use any naming convention you desire.

How to Get an OpenWeatherMap Key

owm-Subscribe_LI.jpg

You will need an API key to access the OpenWeatherMap.org website to obtain current weather information. The next few steps detail how to signup with OpenWeatherMap.org and get an API key.

Follow this link to OpenWeatherMap.org/api.

On the left side, under Current weather data, click the Subscribe button.

How to Get an OpenWeatherMap Key, Get API Key

owm-get api key_LI.jpg

Click on Get API key and Start in the Free column.

How to Get an OpenWeatherMap Key, Signup

owm-signup_LI.jpg

Click on the Signup button under How to get API key (APPID).

How to Get an OpenWeatherMap Key, Create Account

own-new account_LI.jpg

Fill in all the fields. When finished, check the I agree to the Terms of Service and Privacy Policy checkbox. Then click on the Create Account button.

Check your email for a message from OpenWeatherMap.org. The email will have your API key. You will need to copy the API key into the options.ini file in order to obtain the current weather. The OpenWeatherMap.org free service has some limitations. Foremost is that you cannot access it more often than once every ten minutes. This should not be a problem because the weather does not change that rapidly. The other limitations have to do with what information is available. Any of the paid subscriptions will provide more detailed weather information.

Copy the Project Files to Your Raspberry Pi

First you need to be able to talk to your Raspberry Pi. You can do that in one of two ways;

  1. Connect the Raspberry Pi to an HDMI monitor and USB keyboard using the appropriate cables and adapters.
  2. Connect to the Raspberry Pi over Ethernet or WiFi using SSH from a computer running Putty or an equivalent program. To use Putty you must have configured your Pi to enable SSH and you must know the IP address of your Pi.

You need to create a directory on your Raspberry Pi for all of this project's files. You can name the directory whatever you want and put it wherever you want. I recommend that you put the directory in /home/pi. The name I choose for the directory is; rgb-32x64. Be aware that when using the Linux command line, capital letters are not the same as lower case letters. So /home/pi is not the same as /Home/Pi.

  • To create a directory for this project type; mkdir /home/pi/rgb-32x64

All of the project files are available on GitHub. Click here to download the zip archive or clone the directory. If you have Git installed on your Raspberry Pi, you can clone the project files directory or download the zip archive directly to your Raspberry Pi.

Do the same for the Henner Zeller RPI RGB Matrix driver library. Click here to get the Henner Zeller RGB Matrix Driver Library from GitHub.

If you downloaded or cloned to your PC then use WinSCP or a similar program to copy the project files and RGB matrix driver directory to the directory you just created on your Raspberry Pi. You can unzip the archive on your PC prior to transferring the files or unzip the archive on your Raspberry Pi.

To unzip the archives on your Raspberry Pi

  • To unzip the project files archive, type: unzip

    RPi-RGB-Matrix-Scrolling-Sign

    .zip /home/pi/rgb-32x64
  • To unzip the Henner Zeller RGB Matrix library, type: unzip rpi-rgb-led-matrix-master.zip /home/pi/rgb-32x64

The folder on your Raspberry Pi should now contain all of the following;

  • RGB-32x64.py - Python script that runs the RGB LED matrix
  • options.ini - configuration file for enabling/disabling features of the Python script
  • birthdays.xml - XML file for birthday greetings
  • holidays.xml - XML file for holiday greetings
  • fonts - directory containing all of the fonts used by the RGB matrix display, part of the Henner Zeller RGB LED matrix driver package
  • samplebase.py - part of the Henner Zeller RGB LED matrix driver package
  • rpi-rgb-led-matrix-master - Henner Zeller RGB LED matrix driver directory

The zip archive/clone downloaded from GitHub contains some files that are not needed to run the project on your Raspberry Pi. There is a zip archive within the zip archive/clone that contains all of the eagle files need to have my PC board manufactured and a PDF for the schematic of my board. There are also some files used by GitHub that you can ignore.

Edit Options.ini

The options.ini file is used by the system to enable/disable features and to provide URLs for some features to use. The file is organized as key=value pairs. When the Python script starts up, it reads and parses the contents of options.ini into system variables and lists. The keys are used to determine where/how the values are stored. You need to edit options.ini to add your OpenWeatherMap.org API key and to add your zip code and country. OpenWeatherMap.org is used to obtain current, local weather information. In a previous step you signed up for the free weather service from OpenWeatherMap.org.

If you wish to not have a URL be used, but want to keep it in the file then just alter the key by adding a letter or symbol to the key. For example, if you are not a fan of Blonde jokes then just add a pound symbol ('#') before jokesurl in the line; jokesurl=http://www.randomjoke.com/topic/blonde.php. The result should look like this; #jokesurl=http://www.randomjoke.com/topic/blonde.php. Or you could just delete the line.

Here is the default version of options.ini. Do not change any of the keys. Change only the values to the right of the equals sign ('='). For example; military=f can be changed to military=t to have the time displayed in 24 hour format (military time). To keep the time displayed in 12 hour format, leave the value as f.

military=f
temperature=t
humidity=t
pressure=t
weather=t
weatherkey=
weatherzip=
quote=t
quoteurl=https://www.brainyquote.com/link/quotebr.js
jokes=t
jokesurl=http://www.randomjoke.com/topic/oneliners.php
jokesurl=http://www.randomjoke.com/topic/riddles.php
jokesurl=http://www.randomjoke.com/topic/signs.php
jokesurl=http://www.randomjoke.com/topic/blonde.php
jokesurl=http://www.randomjoke.com/topic/doit.php
jokesurl=http://www.randomjoke.com/topic/professional.php
jokedelay=300
news=t
newsurl=http://hosted2.ap.org/atom/APDEFAULT/3d281c11a76b4ad082fe88aa0db04909
newsurl=http://news.google.com/?output=rss
newsurl=http://news.yahoo.com/rss/</p>

The following expains what each key is used for and what values can be used.

  • military
    • t -> 24 hour (military time) format is enabled
    • f -> 12 hour format is enabled
  • temperature
    • t -> temperature read from the optional BME280 is displayed, BME280 must be present
    • f -> temperature read from the optional BME280 is not displayed or the BME280 is not present
  • humidity
    • t -> humidity read from the optional BME280 is displayed, BME280 must be present
    • f -> humidity read from the optional BME280 is not displayed or the BME280 is not present
  • pressure
    • t -> barometric pressure read from the optional BME280 is displayed, BME280 must be present
    • f -> barometric pressure read from the optional BME280 is not displayed or the BME280 is not present
  • weather
    • t -> weather data from OpenWeatherMap.org is collected and displayed
    • f -> weather data is not displayed
  • weatherkey
    • the API key obtained from OpenWeatherMap.org is copied here. The key is used when the site is accessed. Enter the text of the key without any quotes around it
  • weatherzip
    • this is the postal zip code of the city that you want to obtain weather data for. The entry here should be your zip code followed by a comma and then your country. Example; weatherzip=14502,us
  • quote
    • t -> enable the quote of the day to be displayed
    • f -> quote of the day is not displayed
  • quoteurl=https://www.brainyquote.com/link/quotebr.js
    • do not change this line. quoteurl= specifies the URL used to obtain the quote of the day. The Python script knows how to parse quotes from this web site. If you change the URL then the quote may not be parsed properly
  • jokes
    • t -> enable jokes to be displayed
    • f -> no jokes are displayed
  • jokesurl
    • Each URL is read into a list. When it is time to get a new joke the next URL in the list is used to obtain a joke. The Python script knows how to parse jokes from www.randomjoke.com, so always use that URL. Randomjoke.com has several topics or types of jokes to choose from. Some are not suitable for all people. It is up to you to determine which topics you wish to use. I recommend that you use your browser to visit the site and edit the list of URLs to suit your tastes in jokes. Only one URL per line and you can have as many lines as you like.
  • jokedelay
    • This is the number of seconds before a new joke is obtained. If the value is too small then some jokes may never get a chance to be displayed. You should increase this value if there are a lot of headlines to display. A sufficiently large enough delay will ensure that a joke is displayed more than once before a new joke is obtained.
  • news
    • t -> news headlines are displayed
    • f -> no news headlines are displayed
  • newsurl
    • This works like jokes, one line for each URL where news headlines are obtained. Do not change these URLs. The Python script knows how to parse headlines from these sites. If you add more sites they may or may not be parsed properly. The URLs are read into a list. All of the headlines from one URL are parsed and added to the list of messages to display. When the list is rebuilt the next URL is used. If you want fewer headlines then remove one or more URLs.

Edit Birthdays.xml

The file birthdays.xml is read every time the date changes. The file is formatted using XML. The file is used to show a message whenever the current date (month and day number) matches the values stored in the file. Upon a match the message associated with the date is added to the list of messages to be displayed. If you have multiple entries with the same date then multiple messages will be displayed. Add or edit the entries in this file for any occasion that you want to have a message displayed for. Birthdays, anniversaries, memorable dates it is up to you. The only stipulation is that it must be a fixed date, like July 4th. It must fall on the same date every year. If you add an entry for February 29th it will only match once every four years. To add a new entry, copy and paste everything from <item> to </item> inclusive and then change the month value, day value and text values.

One entry looks like this;

<item>
  <month>11</month>
  <day>29</day>
  <flags>Birthday</flags>
  <line>2</line>
  <backgnd>0000</backgnd>
  <foregnd>FFFF<foregnd>
  <text>Happy Birthday to all</text>
</item>

The fields are;

  • item
    • indicates the start of a new entry
  • month
    • a number between 1 and 12 inclusive. Where 1 represents January. If you enter an number greater than 12 then the entry will never match a date.
  • day
    • a number between 1 and 31 inclusive. Where 1 is the first day of the month. If you enter an invalid date, like February 30th, then the date will never match. If you would like the associated text to be displayed every day of a particular month the entern 0 or 00 for the day.
  • flags
    • not used for birthdays. Can be set to any value, however, it must be present.
  • line
    • should always be 2. This value determines which line on the display the text is displayed on. There are two lines on the display line 1 and line 2.
  • backgnd
    • this field is not used. However, it must be present. The value is the background color to use when the associated text is displayed. The color is specified in 5-6-5 format, 5 bits for red intensity, 6 bits for green intensity and 5 bits for blue intensity. The value is a 16 bit number expressed in hexadecimal. The field is here for future use.
  • foregnd
    • this field is not used. However, it must be present. The value is the foreground color to use when the associated text is displayed. The color is specified using the same hexadecimal 5-6-5 format as backgnd. The field is here for future use.
  • text
    • this is the message to be displayed when the date matches.

Edit Holidays.xml

The file holidays.xml works in a similar fashion to birthdays.xml. The difference is that the entries in holidays.xml use the day and flags fields to target dates that occur on specific days of the week. For example, Thanksgiving is always on the fourth Thursday in November.

The entry for Thanksgiving looks like this;

<item>
  <month>11</month>
  <day>Fourth</day>
  <flags>Thursday</flags>
  <line>2</line>
  <backgnd>0000</backgnd>
  <foregnd>FFFF</foregnd>
  <text>Happy Thanksgiving</text>
</item>

Holidays that fall on the same date every year, like Christmas, December 25th, are entered just like an entry in the birthdays.xml file. The day field has the day of the month and the flags field has Holiday instead of Birthday.

For holidays that do not fall on a set date, the day field gets one of the following values; First, Second, Third, Fourth, PalmSunday, GoodFriday or Easter. Use the value exactly as shown, capital letters are important. The values indicate which week of the month the holiday falls on or that it is a special case. The flags field gets one of the following values; Monday, Tuesday, Wednesday, Thursday, Friday, Saturday or Sunday to indicate the day of the week to match against. Use the value exactly as show, capital letters are important. The holidays.xml file contains most of the holidays observed in the USA. Unfortunately the system used is not perfect. Some holidays, like Hanukkah, can not be determined by the code as it is. Feel free to take a stab at adding Hanukkah. The issue with Hanukkah is that the date is determined by a calendar that does not coincide with the Gregorian calendar. I never figured out how to reconcile the different calendars.

Install the Henner Zeller RGB LED Matrix Library

The Python script for this project was adapted from one of the example programs that are included with the Henner Zeller RGB LED matrix library. You can download the library here; Henner Zeller RGB Matrix Library. If you are interested, the README.md file details how the library works. The library also includes schematics and board files for making Hub75 interface boards. There are board packages for driving one, two or three matrices with one Raspberry Pi. One caveat is that the snd_bcm2835 driver that comes with the Raspbian operating system can cause interference with the matrix driver. Instructions are included on how to disable the snd_bcm2835 driver.

Once you have downloaded the matrix library, unzipped it and copy it to your project directory on your Raspberry Pi then follow these steps to compile and install the Henner Zeller RGB LED Matrix library.

  • type; cd rpi-rgb-led-matrix-master/bindings/python
  • type; sudo apt-get update && sudo apt-get install python2.7-dev python-pillow -y
  • type; sudo make build-python
  • type; sudo make install-python
  • type; sudo python setup.py install
  • type; cd ..
  • type; cd ..
  • type; cd ..
  • or type; cd /home/pi/rgb-32x64

You should now be back to your project directory.

How to Disable the Sound Driver

Follow these steps to prevent the snd_bcm2835 driver from being loaded

The Linux prompt should be similar to this; pi@StretchLite:~ $

  • type; cat <

The prompt changes to >

  • type; blacklist snd_bcm2835
  • type; EOF

The prompt changes back to; pi@StretchLite:~ $

  • type; sudo update-initramfs -u

Reboot your Pi

  • type; sudo reboot

After the reboot, you will have to re-login to your Raspberry Pi. If you are using Putty then you will need to close the session and start a new one.

  • type; lsmod

Look for snd_bcm2835. if it is present then try again. You should not see snd_bcm2835 when you type lsmod

How to Make a Python Script Run When the Raspberry Pi Boots Up

To run any Python script, program or shell script on power up, you need to edit /etc/rc.local. Before you can edit

/etc/rc.local you have to change its permissions to allow you to save it after you make changes.

Type; chmod 777 /etc/rc.local

To make it executable, type; /etc/rc.local enabled

Now you are ready to edit it. Open it in your editor of choice. Add the following two lines just above the exit 0 line;

cd /home/pi/rgb-32x64
sudo python RGB-32x64.py

Save your changes and exit the editor.

The first line; cd /home/pi/rgb-32x64 changes the current working directory to where the Python script for this project was copied to. The second line; sudo python RGB-32x64.py invokes supervisor privileges (sudo) to run the Python interpreter (python) and tell it to load and run the Python script (RGB-32x64.py) for this project.

If you want to run a different script on start up then change the path in the first line to where your script is located. Then change the second line to have the name of your script. The sudo command is only required by the RGB-32x64.py script because the Henner Zeller RGB Matrix library requires supervisory privileges to run. You may not need it to run a different script.

Assemble the Hub75 Interface Board, Minimum Build

min-top.jpg
min-bottom.jpg
Top Full marked up.jpg
bottom full.jpg

If you bought the Adafruit Hub75 HAT or plan on hand wiring your own board then you can skip this step. The pictures above show the top and bottom sides of a minimum build board and a fully built board. The minimum build board has only the bare minimum parts needed to connect your Raspberry Pi to a Hub75 RGB LED matrix display. The fully built board has the optional 3.3V regulator circuit and the optional I2C, Console and GPIO headers. You can build the minimum board, the full build or something in between. It is up to you. The top of the board has the 3.3V regulator pads and the pads for IC2. The bottom of the board has the pads for IC1. Before you start, you should decide what optional parts you want to add and have all the parts on hand. I find that it is easiest to assemble a board from the lowest height components to the tallest components. Therefore, I always start with the surface mount parts. Resistors, capacitors and integrated circuits are first. Top or bottom first does not matter. Be sure that the little dimple that marks pin one of the 74HC245 ic is oriented as shown in the pictures.

If you add the AS1117-3.3 regulator then you must also add the two 10uF capacitors. Make sure that the black line on the capacitors is oriented as shown. The black line is the positive side of the capacitor. One of the + signs for the capacitors was obliterated by a feed through next to the capacitor and the other is hard to see due to it ending up on top of some other text. The negative sides of the capacitors share a common trace on the top side of the board. If you mount the capacitors backwards then you will hear a load pop and see smoke when power is turned on.

If you are not adding the voltage regulator circuit then you will need to add a wire to short the two holes of J10 together (first picture above, red circle on the left). This allows the 3.3V from the Raspberry Pi to power any added peripherals.

J11 is used to select a 32 row or a 16 row display. You can either solder a wire that shorts the center hole to the appropriate side for your display (first picture above, red circle near the middle) or add a three pin male header and use a shorting jumper to make your selection (third picture above, red circle near middle). Do not leave this open, a 32 row display will not function properly without the 32 row jumper in place.

The 2x10 socket goes on the bottom side of the board. Optionally, you could use a 2x8 male header mounted on the bottom side of the board and connected to the RGB matrix using the gray cable that came with it. If you are using a full sized Raspberry Pi you should do this. the 2x8 header should be centered in the 2x10 hole pattern such that there are two unused holes on each side of the header.

The two 20 pin socket strips mount on the top side of the board. They are where you plug in your Raspberry Pi. If you bought the Adafruit 2x20 GPIO female header then solder it to the top of the board.

Tip: I find it helpful to plug in a couple of spare male header strips into the socket strips at right angles to them. This helps to stabilize the socket strips, keeps them vertical and keeps the proper spacing. I use extra socket strips to do the same when adding male headers. I always solder one pin and then check to make sure that the header is aligned and vertical before soldering the remaining pins. It is far easier to heat one pin and adjust the header than it is to try and re-align a header that has all of the pins soldered.

The two pin terminal block can mount on the top or the bottom side of the board. If you are using a full sized Raspberry Pi then it must go on the bottom side. I found that on the display that I am using, one of the small screws that hold the display together rubbed against the terminal block when it was installed on the bottom side. You can either ignore it or clip off the screw or mount the terminal block on the top side. Optionally, you can eliminate the terminal block and just solder wires from the holes to the power plug on the display.

Assemble the Hub75 Interface Board, Options

Top Full marked up.jpg
bottom full.jpg
min-top-rt-angle.JPG
min-bottom-rt-angle.JPG

The first two pictures above depict a fully assembled Hub75 Interface Board with all options added.

Because the voltage regulator circuit has been added, J10 is left open (red circles on left side).

A three pin male header has been soldered into J11 (red circle in middle) and a shorting jumper has been set to select a 32 row display.

Three rows of nine pin male headers have been added for the unused GPIO pins. I like to use black for the ground row, red for the 3.3V row and yellow for the GPIO signals. You can use any colors you like.

Three rows of four pin male headers have been added for the I2C breakout. The red headers are 3.3V.

A three pin male header was added for the Console (Serial) port.

This board was assembled with the two pin terminal block on the bottom side.

The last two pictures are of a minimum build board with triple row right angle headers in place on the top and/or the bottom side.

If you are not using a Raspberry Pi Zero W then you might want to consider triple row, right angle post strips for the unused GPIO and/or the I2C breakouts. If you are using a Raspberry Pi Zero, these can be mounted on the top or bottom of the board. Using the right angle headers for the GPIO breakout will prevent any interference with the WiFi dongle and USB adapter. The I2C headers do not interfere with a Raspberry Pi Zero, so you can use vertical headers mounted on the top of the board. If you are using a full sized Raspberry Pi, you should use right angle headers mounted to the bottom of the board. This will allow access to the headers when the Raspberry Pi is attached. You could substitute a 2x8 post strip header for the 2x10 socket and connect to the RGB LED display using the gray flat cable that came with the display. Just make sure that you connect pin one to pin one. Solder the 2x8 header centered in the 2x10 layout. Their should be two unused holes on each side of the 2x8 header.

The two pin terminal block can mount on the top or bottom of the board. If you use a full sized Raspberry Pi then it must go on the bottom.

FYI: The top side of the board is the side that has the pads for the AS1117-3.3 regulator, C1, C2 and IC2.

Prepare the Power Harness

Harness.JPG
Cut off hsrness.JPG
Power harness with power jack.JPG
Soldered Power cable.JPG
Soldered Power cable closeup.JPG
power harness and bd.JPG
Power harness to bd close up.JPG

The first picture above is a picture of the power harness that came with my RGB LED Matrix display. There are two, four wire power plugs, each with two red and two black wires. All four red wires are twisted together and soldered to a single red wire that has a spade connector on the other end. The same was done with the black wires. I am not cascading two displays, so I only need one, four wire power plug. Therefore, I decided to cut the red and black wires of one four wire power plug from where there are soldered together. The result is shown in the second picture. The third picture shows the power harness and a red/black pair wired into a power jack. The fourth and fifth pictures show an alternate method to get power for the Hub75 interface board. Instead of adding two wires to the power jack, a red and a green wire are soldered to the RGB LED Matrix's power header. These wires would then be attached to the terminal block on the Hub75 interface board, with the red wire going to +5V and the green wire to GND.

The sixth photo shows the power harness with the power plug and the extra red/black pair attached to the Hub75 interface board, with the red wire going to +5V and the black wire to GND.

The last photo is a closeup of the terminal block. showing the red and black wires wired to +5V and GND.

The important points here are to use all four of the wires of the power harness to carry power to the display. This will limit the voltage drop in the cable when the display is drawing maximum current. The other point is to provide a source of +5V and Ground to the Hub75 interface board. The Raspberry Pi will get its power from the Hub75 interface board when it is plugged in. The wires to power the Hub75 interface board do not need to be as heavy as the wires to the display because the Hub75 interface board and Raspberry Pi together only require a few hundred milliamps, assuming you are using a Pi Zero or W.

Putting It All Together

wired no pi.JPG
wired no pi closeup.JPG
all bds in place.JPG
DSCN1934.JPG

Now you have all of the pieces, let's put it all together.

  1. Plug the Hub75 interface board with the power cables connected into the input connector on the RGB LED Matrix display. The Raspberry Pi connector should be towards the edge of the display as shown in all of the pictures.
  2. If you are adding the optional BME280 environmental sensor array then this would be a good time to attach it to the Hub75 interface board. The first three pictures above show the BME280 attached using four female to female jumper cables. The BME280 has an I2C interface so it is wired to one of the I2C breakouts, Gnd to Gnd, 3.3V to 3.3V, SDA to SDA and SCL to SCL. Note that this is not a one-to-one cable, the SDA and SCL positions are not the same on the Hub75 interface board as they are on the BME280.
  3. The third photo shows a Raspberry Pi W plugged into the Hub75 interface board. The fourth photo shows a Raspberry Pi Zero with WiFi dongle and USB adapter plugged into the Hub75 interface board. Note that a minimum build was used with the I2C header pins added.
  4. Plug in your power supply and plug the power supply into a wall socket (mains power).
  5. In about 30 seconds your sign should light up and start scrolling messages.

Note: The unused GPIO pins, I2C and Console pins all use 3.3V levels. Connecting 5V signals to these pins will damage your Raspberry Pi. Use only 3.3V peripherals or provide external level shifters.

Where to From Here

You have just finished making a fairly complex project. Congratulations, you are now the proud owner of a Raspberry Pi based 32x64 RGB LED display. You can sit back and enjoy the fruits of your labor...or dive right in and give your scrolling sign more things to do. Maybe you want to add some Python code to follow someone on Twitter and display their tweets. You could experiment with using it as a graphics display to play Pong or Tic-Tac-Toe or Breakout or Othello. How about running a game of life simulation or just a mess of pretty blinking lights. Let your imagination run free. Have fun and enjoy.

If for some reason your display did not light up then go back and check your wiring. If you hand built a Hub75 interface board then make sure that you wired it correctly and/or that there are no solder shorts on your board. Make sure that everything is plugged in correctly. You can also try to manually start the python script by using Putty to SSH into your Raspberry Pi and typing;

cd /home/pi/rgb32x64

followed by; sudo python RGB-32x64.py

If this gets your sign running then something is wrong with the auto startup. Go back to step 17 and double check your work.