blog.dbrgn.ch

Scrolling Text with RPLCD

written on Sunday, April 20, 2014 by

The RPLCD Library

Last year when I started playing around with HD44780 based character LCDs on the Raspberry Pi, I did not find any software library for it that I liked. There were some C++ libraries around and also some Python scripts, but they were a bit messy and not as clean and consistent as I'm used to from the Python community. So I wrote my own library: RPLCD.

In contrast to other libraries, RPLCD tries to be "Pythonic", which means that I don't want to simply copy the C implementations, but use Python features where appropriate. The result of this is that I'm using a clean modular approach and make use of language features like properties and context managers. Here's a small example on how to write a text to a 20x4 LCD:

>>> from RPLCD import CharLCD
>>> lcd = CharLCD()
>>> lcd.write_string(u'Raspberry Pi HD44780')
>>> lcd.cursor_pos = (2, 0)
>>> lcd.write_string(u'http://github.com/\n\rdbrgn/RPLCD')

The result:

A photo of the HD44780 LCD module displaying some text.

If you want to know more, please refer to the README file.

Scrolling Text

Writing a string to the display with RPLCD is easy. But what about more dynamic things, like scrolling text? That's not hard to implement by using a "frame buffer" data structure.

The idea is that you create a data structure which contains all the characters that should be written to the display later on. This data structure can then be manipulated with standard Python tools. A good choice here would be a 2-dimensional list, representing rows and columns. In the case of a 2x16 LCD:

>>> framebuffer = [
...     'Hello!',
...     '',
... ]

Then we need a function to actually write the framebuffer to the device. It should properly truncate the strings to the max column length.

>>> def write_to_lcd(lcd, framebuffer, num_cols):
...     """Write the framebuffer out to the specified LCD."""
...     lcd.home()
...     for row in framebuffer:
...         lcd.write_string(row.ljust(num_cols)[:num_cols])
...         lcd.write_string('\r\n')

Write the framebuffer to the LCD:

>>> from RPLCD import CharLCD
>>> lcd = CharLCD()
>>> write_to_lcd(lcd, framebuffer, 16)

Now we have a framebuffer that simply writes "Hello!" to the first row of the LCD. But we want a scrolling text across the second row... To achieve this, we need to manipulate the framebuffer, write it to the display, sleep for a short while and repeat. A simple version might look like this:

>>> import time
>>> long_string = 'This string is too long to fit'
>>> for i in range(len(long_string) - 16 + 1):
...     framebuffer[1] = long_string[i:i+16]
...     write_to_lcd(lcd, framebuffer, 16)
...     time.sleep(0.2)

This simply scrolls the text into the visible area and stops. To get infinite scrolling, simply add 16 blank characters at the beginning and end of the string and repeat. Here's the extended version of the above code, wrapped in a function:

>>> def loop_string(string, lcd, framebuffer, row, num_cols, delay=0.2):
...     padding = ' ' * num_cols
...     s = padding + string + padding
...     for i in range(len(s) - num_cols + 1):
...         framebuffer[row] = s[i:i+num_cols]
...         write_to_lcd(lcd, framebuffer, num_cols)
...         time.sleep(delay)
...
>>> while True:
...     loop_string(long_string, lcd, framebuffer, 1, 16)

Now you got infinite scrolling text on the second row, while the first row stays static.

This entry was tagged algorithms, hardware and raspberry_pi