In this little project I use a serial LCD connected to the Rasp Pi serial output to print the current time and IP address for the Pi. It’s a fun little project as it puts together a few pieces; using the Adafruit T-Cobbler Plus, making an inverter circuit and controlling the serial LCD.
There are already some good tutorials online on how to use a standard (non-serial) LCD with the Pi. For example, Adafruit has a great tutorial on driving an LCD using the Pi. However I had a BPI-216N serial LCD from Scott Edwards Electronics which uses a simple single-line serial link running at 2400 or 9600 baud to send data from the Pi to the display. Amazingly I bought this unit in 1998 and have had it sitting in a drawer ever since – and it still works perfectly!
Using the serial port on the Rasp Pi
The first thing you need to do is disable the serial port console on the Rasp Pi. Why? By default the Pi boots up and creates a serial console on the Rx and Tx lines running at 115200 baud. This is great if you need to log into a Pi that has no screen attached, but we want to use this serial port to send data to the LCD.
The serial console is configured in /boot/cmdline.txt and you simply need to remove the text that says
console=ttyAMA0,115200 and save the cmdline.txt file.
The second step is to display the init process in Linux from attempting to connect a tty to the serial console. In older releases of Raspbian the procedure is to edit /etc/inittab, but in the later releases Raspbian has moved to a new way of starting boot services. The command to remove the serial console tty starting is:
sudo systemctl stop serial-betty@ttyAMA0.service
Reboot your Pi and then the serial console is disabled.
Inverting the signal to the LCD
The interesting (or challenging) part about the serial LCD is that it expects inverted TTL as it expects to be connected to an RS232 port, which inverts the polarity of the signal by default. What does this mean? Well if you want to send the letter ‘a’ (decimal character code 97, binary 0110 0001) then you need to flip each bit and send the value 1001 1110 or 158. This is painful to do in software, so the simple solution is to put an inverter between the TxD pin on the GPIO header and the serial input on the LCD.
I did a quick search online and found this schematic for a single-transistor simple inverter made using one transistor and two resistors. I used 1K resistors and a 2N2222 transistor, mainly because I had them sitting on my desk! Note that this circuit does not do level shifting! The Pi GPIO pins operate at 3.3V but most serial devices use 5V. This isn’t a problem for this project as we’re sending data to the LCD so a level shift isn’t needed.
Wiring it all together looks as follows (yes my breadboard work won’t win any prizes!)
Python Code to print to the LCD
Finally we get to the code itself. It’s actually pretty simple as the serial port does the bulk of the work and the transistor inverter takes care of the logic signals. I set my LCD to work at 9600 baud. I cheated a little to get the IP address by running the hostname command and parsing the output; not pretty but it works.
To learn more about the commands accepted by the LCD read the programmers guide.
# Show the current IP address and date and time # on the serial LCD attached to the serial port # # Mark Crosbie firstname.lastname@example.org 12/3/16 # http://thinkbricks.net
import serial from time import sleep, strftime from datetime import datetime import commands
ser = serial.Serial(port='/dev/ttyAMA0', baudrate=9600) cls = bytearray([254, 1]) ip_addr = commands.getoutput("hostname -I").split(" ")
def clearscreen(): ser.write(cls) # clear and reset screen sleep(0.01)
def moveTo(line, col): pos = line*192 + col b = bytearray([254, pos]) ser.write(b) sleep(0.01)
if ser.isOpen(): while 1: clearscreen() ser.write(ip_addr) moveTo(1,0) ser.write(datetime.now().strftime('%d %b %H:%M:%S')) sleep(1.0)