This is the first post in a series looking at how to use a SSD1306 128×64 Pixel OLED Display Module as a passenger information display on a model railway. The screens on these modules are 22mm by 11mm. This makes them a scale size of 1.6m wide by 0.8m high at OO scale. So they are a suitable size.
We will begin by looking at the code required to make a static departures screen. Other articles in the series will cover displaying a clock, dynamic departures and arrivals and using multiple screens to create the kind of information display you see on a mid-sized station concourse.
Whatever the style of display, there are two things that the sketch has to do; it needs to hold the data about the trains, and display that data on the screen. You could merge this together, but that would make changing or updating the display very difficult. We will keep these separate to give us flexibility.
We will start with the data. We are going to display train departure information, including destination, departure time and platform number. If we only ever want to display information for one train we use a variable of suitable type for each piece of data. But our aim is to be able to display several different trains on our screen. We can make things easier by structuring our data, grouping together the information about each train in one place. To do this we will use a struct data type.
Within this struct we will place the variables required to hold the information about each train.
This coma separated list places the data into the variables in the order we specified them in the TrainDeparture struct. The information to be displayed on our screen is in the sketch. We will now work through getting that information on the screen.
Working out which of our screen’s 8,192 individual pixels need to be switched on and off is rather complex, as is communicating that information to the display module. However, we can ignore all that complexity by using the Hobby Components Library, which will deal with all the complex stuff for us. This needs to be installed in the Arduino IDE and can be download from the support page on the forum here.
This library, along with SPI (which enables the development board to communicate with the screen) needs to be included in our sketch.
Three pins also need to be defined. These connect to the RST (reset), DC (data/command) and CS (chip select) pins on the display.
#define CS_DI 10
#define DC_DI 9
#define RST_DI 8
Between the display module and the development board there also needs to be a GND to GND wire, VCC to 5V (or 3.3V) D0 to pin 13 and D1 to pin 11. Pins 11 and 13 are mandatory for the SPI connection. This also ties up pin 12, so do not try and use 12 for another purpose (I learnt this the hard way when a thing that “should” have worked didn’t).
We need to create an instance of the display:
HCuOLED HCuOLED(SH1106, CS_DI, DC_DI, RST_DI);
The library is designed to work with several Hobby Components display modules. This specifies which module we are using and the pins it is connected to.
To get our train information on to the display we need to follow a process. To print text on the screen we first need to specify which of the available fonts to use. Because we are working at a scale of 1/76th and we have lots of information to cram on the screen we need a tiny font. For this project I created two fonts, the first 6 pixels high and the second a mere 5 pixels high. They are included in the library with 3 other larger fonts. To set the font we use the following line:
Once set, we can continue to use this font until we specify a different one.
Next we need to specify where we want our text to appear on the display. Our display is 64 pixels high and 128 pixels wide. Starting at (0, 0) and finishing at (63, 127) we use the Cursor() function to set where we want the top left corner of the text to appear. We’ll start with it at the very top left of the screen.
We can then place the text we want on the screen using the Print command.
This will place hours value of departure on the display.
We can then continue to specify the location and the information we want on the screen. First a colon to separate the Hours and Minutes, and then the minutes.
Notice that the first value of the cursor is increasing. This is moving the cursor across the screen so the text is “printed” to the right of, rather than on top of, the previous text. We will now add the Destination and Platform Number.
To complete the line we will add in one more piece of information for our passengers.
Our trains are never late!! So we don’t need to use a variable for this text!
We need to do this for all of our departures, displaying them below, row by row. So we will place this code in a function to allow us to use it repeatedly. The zeros for our departures and our row position are replaced with variables “train” and “row” so they can be incremented for each departure.
This can then be called from the loop() by displayDeparture() but we will get back to that. We have to consider setup first.
If the display has already been used there will be information held in its display buffer. When we power it up we want to clear that information from the screen. To do this we issue a reset in setup.
/* Reset the display */
With the display reset we are ready to head into the loop and build up all the rows on our screen. We need to use a for loop to call the displayDeparture() function for each of the trains. This builds up all of our text in a screen buffer. This is one of the complex bits that the Hobby Components library does for us so we don’t have to worry about it. Once the screen buffer is completed we can send it to the display using the Refresh function.
for (int i = 0; i < NUMBER_OF_DEPARTURES; i++)
We now have all the code required to create a model railway departure board. Our sketch can be uploaded to a deelopment board. If you haven’t followed along writing the code, you can download the sketch from Github here.