Connection issues with Sparkfun 20x4 LCD and Raspberry Pi 3B+ via serial

Hi there,

I am having issues connecting my Raspberry Pi 3B+ to a Sparkfun LCD screen 20x4 via serial connection. (SparkFun 20x4 SerLCD - RGB Backlight (Qwiic) - LCD-16398 - SparkFun Electronics).

I am trying to connect using python code. (GitHub - fourstix/Sparkfun_CircuitPython_SerLCD: CircuitPython driver for the Sparkfun SerLCD displays)

I find this strange because I was able to get it working with my Raspberry Pi Zero W. All I did was move the SD card from the Raspberry Pi Zero to the Raspberry Pi 3B+. I thought it would be the same settings, as per the documentation (Raspberry Pi Documentation - Configuration). However, I have changed the serial settings within to see if I can get it working.
(UPDATE: Ever since changing to a Raspberry Pi 3B+, the LCD is not working anymore on the Raspberry Pi Zero)

My physical connections to the LCD are as follows:
Raspberry Pi Pin17 (3.3V) - LCD RAW power input
Raspberry Pi Pin30 (GND) - LCD Ground connection
Raspberry Pi GPIO14 or Pin8 (Tx) - LCD Rx connection

Other setup information:

  • DS3231 RTC module is installed on pins 1,3,5,7,9 on raspberry pi
  • several other GPIO pins are being used, but are most likely irrelevant to the LCD issue.

I am currently trying to talk to the serial port using the miniUART (GPIO pins 14 only), and I have also tried using the PL011 UART hardware too. Both show the following on the screen using a baud rate of 9600.

If I change the baud rate to 115200 (on both PL011 and MiniUART), I get the following on the LCD screen.

To verify that my baud rate settings were default:

stty < /dev/ttyAMA0
speed 9600 baud; line = 0;
min = 0; time = 0;
-brkint -icrnl -imaxbel
-opost -onlcr
-isig -icanon -iexten -echo -echoe -echok -echoctl -echoke

stty < /dev/ttyS0
speed 9600 baud; line = 0;
min = 0; time = 0;
-brkint -icrnl -imaxbel
-opost -onlcr
-isig -icanon -iexten -echo -echoe -echok -echoctl -echoke

=============
I have disabled both consoles for /dev/ttyS0 (MiniUART) and /dev/ttyAMA0 (PL011):

sudo systemctl disable serial-getty@ttyS0.service 
sudo systemctl disable serial-getty@ttyAMA0.service

=============
MiniUART SETUP on raspberry pi 3B+ is as follows:

  • /boot/config.txt file has the following relevant settings for the MiniUART:
[all]
enable_uart=1
#dtoverlay=uart1,txd1_pin=8,rxd1_pin=10  # Setting MiniUART to Pin 8 and Pin 10
  • I removed the appropriate console from my /boot/cmdline.txt for the MiniUART:
    console=tty1 root=PARTUUID=ede117fa-02 rootfstype=ext4 fsck.repair=yes rootwait

=============
PL011 SETUP
When trying to use the PL011 UART, I disabled Bluetooth to make the PL011 the primary UART.

  • the /boot/config.txt file has the following settings for the PL011:
[all]
enable_uart=1 
dtoverlay=disable-bt
#dtoverlay=uart0,txd1_pin=8,rxd1_pin=10  # Setting MiniUART to Pin 8 and Pin 10
  • I had to disable the Bluetooth modem:
sudo systemctl disable hciuart 
sudo systemctl stop hciuart 
  • /boot/cmdline.txt for the PL011 is the same as MiniUART. The file is as follows:
    console=tty1 root=PARTUUID=ede117fa-02 rootfstype=ext4 fsck.repair=yes rootwait

=============
My CODE:


#!/bin/env python3

import time
from sparkfun_serlcd import Sparkfun_SerLCD_UART
from serial import Serial, PARITY_NONE, STOPBITS_ONE, EIGHTBITS

raspiUART = Serial(
        #port='/dev/serial0',
        #port='/dev/serial1',
        #port='/dev/ttyAMA0',
        port='/dev/ttyS0',
                                                                                         
        baudrate = 9600,
        parity=PARITY_NONE,
        stopbits=STOPBITS_ONE,
        bytesize=EIGHTBITS,
        timeout=1)

serlcd = Sparkfun_SerLCD_UART(raspiUART)

serlcd.set_cursor(0,0)
serlcd.write("Is the LCD working??")
serlcd.set_cursor(0,1) 
serlcd.write("Monkeys luv bananas.") 
serlcd.set_cursor(0,2) 
serlcd.write("Yum, bananas. Purple") 
serlcd.set_cursor(0,3)
serlcd.write("Monkey Dishwasher!!!")

print("Check the LCD screen.\nSomething legible should be seen.\n\nSleeping for 2 seconds...") 
print("One banana ...") 
time.sleep(1) 
print("Two banana ...") 
time.sleep(1)

serlcd.reset() 

=============

As a last resort, I attempted an Emergency Reset using this guide (AVR-Based Serial Enabled LCDs Hookup Guide - SparkFun Learn), but was unable to get a “System Reset” message on the screen.

I have been working on this for over a week now and still no success with communicating with the Raspberry Pi 3B+. Any help would be appreciated.

Hi Simon,

Welcome to the forum :slight_smile:

Thanks for your detailed troubleshooting steps. I’ve had a read through what you’ve done and checked the wiring in your photos as best I can and I can’t see any obvious mixups that would explain why your LCD isn’t working.

Serial interfaces in general can be pretty difficult to troubleshoot since everything has to be just so before you get an outcome and know if the device is working. Are you able to run a loop-back test by connecting the Pis TX and RX together so that you know it is sending and receiving test messages ok?

At the risk of muddying the waters I noticed your display does have a Qwiic connector, so you could try using a different interface altogether and just cut serial uart out of the process. By connecting via the I2C interface using a cable like this. Then there is an alternative Python library using the I2C/qwiic interface that should get that display running. GitHub - sparkfun/Qwiic_SerLCD_Py: Python module for I2C control of the SparkFun Qwiic Serial LCDs

Thanks for the reply Trent.

I have given up on the serial connection and moved onto using i2c for LCD communication. But I am still having connection issues.

I am using GPIO0 (ID_SD) and GPIO1 (ID_SC) for the i2c connections instead of the defaults, because I have a RTC clock on the default I2C pins. I believe this means that I am using Bus 0, and not the default Bus 1.

Here is the address for the LCD on Bus 0

i2cdetect -y 0 
     0  1  2  3  4  5  6  7  8  9  a  b  c  d  e  f 
00:                         -- -- -- -- -- -- -- --
10: -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- 
20: -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- 
30: -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- 
40: -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- 
50: -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- 
60: -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- 
70: -- -- 72 -- -- -- -- --  

The code was pretty much copied and pasted from qwiic’s repo into a file with the address manually entered:

from __future__ import print_function
import qwiic_serlcd
import time
import sys

my_address = 0x72

mylcd = qwiic_serlcd.QwiicSerlcd(address=my_address)
#mylcd = qwiic_serlcd.QwiicSerlcd()

mylcd.setAddress(my_address)
print(mylcd.connected)

def runExample():	
	print("\nSparkFun Qwiic SerLCD   Example 1\n")
        myLCD = qwiic_serlcd.QwiicSerlcd() 

        if myLCD.connected == False:
                print("The Qwiic SerLCD device isn't connected to the system. Please check your connection", \ 
                        file=sys.stderr) 
                return

        myLCD.setBacklight(255, 255, 255) # Set backlight to bright white 
        myLCD.setContrast(5) # set contrast. Lower to 0 for higher contrast. 
        myLCD.clearScreen() # clear the screen - this moves the cursor to the home position as well 
 
        time.sleep(1) # give a sec for system messages to complete

        myLCD.print("Hello World!")
        counter = 0
        while True:
                print("counter: %d" % counter)
                myLCD.setCursor(0,1)
                myLCD.print(str(counter))
                counter = counter + 1 
                time.sleep(1) 

if __name__ == '__main__': 
        try: 
                runExample() 
        except (KeyboardInterrupt, SystemExit) as exErr: 
                print("\nEnding Example 1")
                sys.exit(0)     

When I run the code, it gives me the following error:

OSError: [Errno 121] Remote I/O error

If I do not assign the address (line 8 and/or 11), it seems to detect the address correctly, but still gives an I/O error:

Error connecting to Device: 72, [Errno 121] Remote I/O error

Again, I find this strange because the LCD works fine when I use the smbus2 library directly, using this code:

import smbus2

device_bus = 0
address = 0x72

bus = smbus2.SMBus(device_bus)
#bus.write_byte_data(address, 0xA5, 0x5A) # Reset the LCD 

text = "This is a string that will show up on the LCD using the smbus2 python library." 

for char in text: 
        bus.write_byte(address, ord(char))

However, when using the smbus2 library, I am unable to control the cursor (not yet anyway), but using the qwiic library, controlling the cursor seems to be relatively straight forward.

When using the Qwiic library, does it have to use the default Bus 1, or can this be changed to Bus 0?

Hi Simon,

You can have both devices connected to I2C bus 1 if you wanted to, provided they have different I2C addresses. I suspect the Qwiic library may be defaulting to I2C bus 1 if it isn’t explicitly commanded to initialise using bus 0.