2

Ive connected the lcd to the pi, setup raspbian, and powered the device (3B+) on. The display displays 4 lines, line 1 and 3 are sort of darked out, what seems to be indicating working hardware. I wrote java-code, hoping for it to be easy, but Im stuck. I cant get the screen to clear or show anything at all. My code:

GpioController gpio = GpioFactory.getInstance();
GpioLcdDisplay lcd = new GpioLcdDisplay(4, 20, 
        RaspiPin.GPIO_11, // LCD RS pin
        RaspiPin.GPIO_10, // LCD strobe pin / enable
        RaspiPin.GPIO_00, // LCD data bit 1
        RaspiPin.GPIO_01, // LCD data bit 2
        RaspiPin.GPIO_02, // LCD data bit 3
        RaspiPin.GPIO_03); // LCD data bit 4;
lcd.clear();
Thread.sleep(1000);
lcd.write(1, "hej hej");
Thread.sleep(2000);
lcd.clear();
gpio.shutdown();

and the data-sheet is here: https://produktinfo.conrad.com/datenblaetter/1300000-1399999/001380371-an-01-en-20X04_LC_DISPLAY_MONOCHROM.pdf

I would just want it to display anything, like hello world. Grateful for any help.

I even tried the example program that is linked to in the papers, a python program - also, it does nothing to the display. Isnt that weird? But the screen displays 2 darkened lines, so it seems to be working.. Anyone?

What I might seem to be stuck on are the used gpio pins, I have no idea which of them I should use, the above java-code is just trial and error. I hope I havent broken it. Thoughts?

Mathias
  • 21
  • 3
  • What do you mean by the "used GPIO pins"? I thought you were using a Rpi hat and there is no chance of wrongly aligning the pins, LCD_RS = 7 #GPIO7 = Pi pin 26 LCD_E = 8 #GPIO8 = Pi pin 24 LCD_D4 = 17 #GPIO17 = Pi pin 11 LCD_D5 = 18 #GPIO18 = Pi pin 12 LCD_D6 = 27 #GPIO21 = Pi pin 13 LCD_D7 = 22 #GPIO22 = Pi pin 15 – tlfong01 May 15 '19 at 12:55
  • I have included the LCD 4bit init sequence flow chart in appendix C of my answer. It is very useful to understand the vendor's demo program (no need to read the very tedious and boring datasheet!). The only critical thing is the wait millisecond timing. There are only a couple of python statements. So I guess it not that tedious to translate them to pi4j. – tlfong01 May 16 '19 at 04:44
  • By 'used GPIO pins', I mean what seems to be initialized in the code. And no, it doesnt seem possible to misplace the hat, it has 40 input pins like the header. – Mathias May 16 '19 at 06:58

1 Answers1

1

Question

Device = 20 x 4 LCD Java-code can't get the screen to clear or show anything at all

Answer

Well, I see that your program are using lcd.clear(), and lcd.write(). But I don't see any lcd.init().

You might like to show the full listing, then I might point if your lcd.init() and lcd.clear(), and lcd.write() are OK.

I skimmed through Joy-IT's python demo program and find it very structured and of course should be fully debugged.

To make debugging simple, I suggest you to remove the button functions (button input and LCD output are independent no side effect functions. So removing button functions make debugging easy to locate errors.)

The demo program contains a couple of functions and the pulse function is a bit time critical. Setting up GPIO pins for output is of course easy, but writing functions according the HD44780 datasheet, is very tedious (It took me more than 20 long hours to thoroughly understand the easy 8 bit but three times harder 4 bit operations.

The important thing is do not modify those LCD pule/write/init functions. Just run the program to init the LCD. You should see the LCD cleared, IF everything goes well. Then you use the ShowMessage(string) to display a character string.

Troubleshooting tips to newbies

If you don't see the characters or blank 5x7 dots character matrices, you need to adjust the pot fully CW and CCW to display them.

I still remember vividly that the first time I spent long hours and much effort and did everything correct, but -

THE CHARACTERS DID NOT SHOW UP, UNTIL I ADJUST THE BACKGROUND BRIGHTNESS!

References

Hitachi HD44780U Dot Matrix LCD Controller Rev. 0.0

Pi4J Project Version: 1.2 - pi4j 2019-03-05

Java Pi4j Interface with 16*2 LCD Problem

Appendix A - A Minimal Simple Test Program

Errata - This program is buggy, do not use it - use the corrected version in Appendix D

Now I have removed the button functions and only test the LCD output. You might like to just run it and let me know any bugs or results.

Joy-IT Demo Program modified by tlfong01 2019may15hkt2144

LCD Display 20x4 with Buttons - Ausgabe Joy-IT 10.11.2017

import time
import RPi.GPIO as GPIO

# PIN-Configuration

LCD_RS =  7 #GPIO7  = Pi pin 26
LCD_E  =  8 #GPIO8  = Pi pin 24
LCD_D4 = 17 #GPIO17 = Pi pin 11
LCD_D5 = 18 #GPIO18 = Pi pin 12
LCD_D6 = 27 #GPIO21 = Pi pin 13
LCD_D7 = 22 #GPIO22 = Pi pin 15

OUTPUTS = [LCD_RS, LCD_E, LCD_D4, LCD_D5, LCD_D6, LCD_D7]

# HD44780 Controller Commands

CLEARDISPLAY = 0x01
SETCURSOR    = 0x80

# Line Addresses

LINE = [0x00,0x40,0x14,0x54] 

# LCD Functions 

def InitIO():
  GPIO.setmode(GPIO.BCM)
  GPIO.setwarnings(False)
  for lcdLine in OUTPUTS:
    GPIO.setup(lcdLine, GPIO.OUT)
  return

def PulseEnableLine():
  mSec = 0.0005 # use half-millisecond delay
  time.sleep(mSec) #give time for inputs to settle
  GPIO.output(LCD_E, GPIO.HIGH) #pulse E high
  time.sleep(mSec)
  GPIO.output(LCD_E, GPIO.LOW) #return E low
  time.sleep(mSec) #wait before doing anything else
  return

def SendNibble(data):
  GPIO.output(LCD_D4, bool(data & 0x10))
  GPIO.output(LCD_D5, bool(data & 0x20))
  GPIO.output(LCD_D6, bool(data & 0x40))
  GPIO.output(LCD_D7, bool(data & 0x80))
  return

def SendByte(data,charMode=False):
  GPIO.output(LCD_RS,charMode) #set mode: command vs. char
  SendNibble(data) #send upper bits first
  PulseEnableLine() #pulse the enable line
  data = (data & 0x0F)<< 4 #shift 4 bits to left
  SendNibble(data) #send lower bits now
  PulseEnableLine() #pulse the enable line
  return

def InitLCD():
  SendByte(0x33) #initialize
  SendByte(0x32) #set to 4-bit mode
  SendByte(0x28) #2 line, 5x7 matrix
  SendByte(0x0C) #turn cursor off (0x0E to enable)
  SendByte(0x06) #shift cursor right
  SendByte(CLEARDISPLAY) #remove any stray characters on display
  return

def SendChar(ch):
  SendByte(ord(ch),True)
  return

def ShowMessage(string):
  for character in string:
    SendChar(character)
  return

# *** main ***

InitLCD()
ShowMessage("This is a test string")

# *** End of program ***

Appendix B - Original Joy-IT Full List Demo Program

Errata - This program is buggy, do not use it - use the corrected version in Appendix D

LCD Display 20x4 with Buttons - Ausgabe Joy-IT 10.11.2017
https://produktinfo.conrad.com/datenblaetter/1300000-1399999/001380371-an-01-en-20X04_LC_DISPLAY_MONOCHROM.pdf

import tim
import RPi.GPIO as GPIO

# PIN-Configuration

LCD_RS = 7 #GPIO7 = Pi pin 26
LCD_E  = 8 #GPIO8 = Pi pin 24
LCD_D4 = 17 #GPIO17 = Pi pin 11
LCD_D5 = 18 #GPIO18 = Pi pin 12
LCD_D6 = 27 #GPIO21 = Pi pin 13
LCD_D7 = 22 #GPIO22 = Pi pin 15

OUTPUTS = [LCD_RS,LCD_E,LCD_D4,LCD_D5,LCD_D6,LCD_D7]

# Button-PINs

SW1 = 4  #GPIO4  = Pi pin 7
SW2 = 23 #GPIO16 = Pi pin 16
SW3 = 10 #GPIO10 = Pi pin 19
SW4 = 9  #GPIO9  = Pi pin 21

INPUTS = [SW1,SW2,SW3,SW4]

# HD44780 Controller Commands

CLEARDISPLAY = 0x01
SETCURSOR = 0x80

# Line Addresses. (Pick one. Comment out whichever doesn't apply)

LINE = [0x00,0x40,0x14,0x54] #for 20x4 display
#LINE = [0x00,0x40] #for 16x2 display

########################################################################

def InitIO():
#Sets GPIO pins to input & output, as required by LCD board

GPIO.setmode(GPIO.BCM)
GPIO.setwarnings(False)

for lcdLine in OUTPUTS:
  GPIO.setup(lcdLine, GPIO.OUT)

for switch in INPUTS:
  GPIO.setup(switch, GPIO.IN, pull_up_down=GPIO.PUD_UP)

def CheckSwitches():

# Check status of all four switches on the LCD board

val1 = not GPIO.input(SW1)
val2 = not GPIO.input(SW2)
val3 = not GPIO.input(SW3)
val4 = not GPIO.input(SW4)
return (val4,val1,val2,val3)

def PulseEnableLine():
# Pulse the LCD Enable line; used for clocking in data
mSec = 0.0005 # use half-millisecond delay
time.sleep(mSec) #give time for inputs to settle
GPIO.output(LCD_E, GPIO.HIGH) #pulse E high
time.sleep(mSec)
GPIO.output(LCD_E, GPIO.LOW) #return E low
time.sleep(mSec) #wait before doing anything else
def SendNibble(data):

# sends upper 4 bits of data byte to LCD data pins D4-D7
GPIO.output(LCD_D4, bool(data & 0x10))
GPIO.output(LCD_D5, bool(data & 0x20))
GPIO.output(LCD_D6, bool(data & 0x40))
GPIO.output(LCD_D7, bool(data & 0x80))

def SendByte(data,charMode=False):
# send one byte to LCD controller
GPIO.output(LCD_RS,charMode) #set mode: command vs. char
SendNibble(data) #send upper bits first
PulseEnableLine() #pulse the enable line
data = (data & 0x0F)<< 4 #shift 4 bits to left
SendNibble(data) #send lower bits now
PulseEnableLine() #pulse the enable line

def InitLCD():

#initialize the LCD controller & clear display
SendByte(0x33) #initialize
SendByte(0x32) #set to 4-bit mode
SendByte(0x28) #2 line, 5x7 matrix
SendByte(0x0C) #turn cursor off (0x0E to enable)
SendByte(0x06) #shift cursor right
SendByte(CLEARDISPLAY) #remove any stray characters on display

########################################################################

def SendChar(ch):
SendByte(ord(ch),True)
def ShowMessage(string):

# Send string of characters to display at current cursor position
for character in string:
SendChar(character)

Appendix C - LCD Init 4 bit sequence

lcd init sequence

Appendix D - LCD 20 x 4 Schematic

lcd20x4 wiring

Rpi GPIO BCM GPIO pin numbering vs 40 pin connector board physical position numbering

rpi gpio pin numbering

Appendix D - Correct Version joy-IT Demo Program

Note - I have made a mistake in copying the demo code from the user guide. In other words, the programs in Appendix A and B is buggy. Do not use them!

import time
import RPi.GPIO as GPIO

# PIN-Configuration
LCD_RS = 7 #GPIO7 = Pi pin 26
LCD_E = 8 #GPIO8 = Pi pin 24
LCD_D4 = 17 #GPIO17 = Pi pin 11
LCD_D5 = 18 #GPIO18 = Pi pin 12
LCD_D6 = 27 #GPIO21 = Pi pin 13
LCD_D7 = 22 #GPIO22 = Pi pin 15
OUTPUTS = [LCD_RS,LCD_E,LCD_D4,LCD_D5,LCD_D6,LCD_D7]

#Button-PINs
SW1 = 4 #GPIO4 = Pi pin 7
SW2 = 23 #GPIO16 = Pi pin 16
SW3 = 10 #GPIO10 = Pi pin 19
SW4 = 9 #GPIO9 = Pi pin 21
INPUTS = [SW1,SW2,SW3,SW4]
#HD44780 Controller Commands
CLEARDISPLAY = 0x01
SETCURSOR = 0x80

#Line Addresses. (Pick one. Comment out whichever doesn't apply)
LINE = [0x00,0x40,0x14,0x54] #for 20x4 display
#LINE = [0x00,0x40] #for 16x2 display
########################################################################

def InitIO():
 #Sets GPIO pins to input & output, as required by LCD board
 GPIO.setmode(GPIO.BCM)
 GPIO.setwarnings(False)
 for lcdLine in OUTPUTS:
     GPIO.setup(lcdLine, GPIO.OUT)
 for switch in INPUTS:
     GPIO.setup(switch, GPIO.IN, pull_up_down=GPIO.PUD_UP)

def CheckSwitches():
 #Check status of all four switches on the LCD board
 val1 = not GPIO.input(SW1)
 val2 = not GPIO.input(SW2)
 val3 = not GPIO.input(SW3)
 val4 = not GPIO.input(SW4)
 return (val4,val1,val2,val3)

def PulseEnableLine():
 #Pulse the LCD Enable line; used for clocking in data
 mSec = 0.0005 #use half-millisecond delay
 time.sleep(mSec) #give time for inputs to settle
 GPIO.output(LCD_E, GPIO.HIGH) #pulse E high
 time.sleep(mSec)
 GPIO.output(LCD_E, GPIO.LOW) #return E low
 time.sleep(mSec) #wait before doing anything else

def SendNibble(data):
 #sends upper 4 bits of data byte to LCD data pins D4-D7
 GPIO.output(LCD_D4, bool(data & 0x10))
 GPIO.output(LCD_D5, bool(data & 0x20))
 GPIO.output(LCD_D6, bool(data & 0x40))
 GPIO.output(LCD_D7, bool(data & 0x80))

def SendByte(data,charMode=False):
 #send one byte to LCD controller
 GPIO.output(LCD_RS,charMode) #set mode: command vs. char
 SendNibble(data) #send upper bits first
 PulseEnableLine() #pulse the enable line
 data = (data & 0x0F)<< 4 #shift 4 bits to left
 SendNibble(data) #send lower bits now
 PulseEnableLine() #pulse the enable line

def InitLCD():
 #initialize the LCD controller & clear display
 SendByte(0x33) #initialize
 SendByte(0x32) #set to 4-bit mode
 SendByte(0x28) #2 line, 5x7 matrix
 SendByte(0x0C) #turn cursor off (0x0E to enable)
 SendByte(0x06) #shift cursor right
 SendByte(CLEARDISPLAY) #remove any stray characters on display
########################################################################

def SendChar(ch):
 SendByte(ord(ch),True)

def ShowMessage(string):
 #Send string of characters to display at current cursor position
 for character in string:
     SendChar(character)

def GotoLine(row):
 #Moves cursor to the given row
 #Expects row values 0-1 for 16x2 display; 0-3 for 20x4 display
 addr = LINE[row]
 SendByte(SETCURSOR+addr)

########################################################################
# Main Program
print "LCD program starting. Press CTRL+C to stop."
InitIO()
InitLCD()
ShowMessage('Press a button!')
while (True):
 GotoLine(1)
 switchValues = CheckSwitches()
 decimalResult = " %d %d %d %d" % switchValues
 ShowMessage(decimalResult)
# time.sleep(0.2)

Appendix E - LCD2004 Module for testing

lcd2004 module

Appendix F - LCD2004 Rpi3B+ Wiring

LCD2004 wiring

Appendix G - LCD2004 Wiring 2

LCD2004 wiring 2

tlfong01
  • 4,665
  • 3
  • 10
  • 24
  • I tried running the program, and it exited with an error: Traceback (most recent call last): File "lcd20x4-2.py", line 78, in InitLCD() File "lcd20x4-2.py", line 59, in InitLCD SendByte(0x33) #initialize File "lcd20x4-2.py", line 50, in SendByte GPIO.output(LCD_RS,charMode) #set mode: command vs. char RuntimeError: Please set pin numbering mode using GPIO.setmode(GPIO.BOARD) or GPIO.setmode(GPIO.BCM) – Mathias May 16 '19 at 06:53
  • Also, you dont see an lcd.init(), thats because such a function does not exist in the java library, at least not what I can tell. – Mathias May 16 '19 at 06:58
  • Ah Error message says we forget to set numbering mode. You can try the following: – tlfong01 May 16 '19 at 07:01
  • Also, regaring adjusting the brightness; As it is now, I clearly see the four lines, or rather the two of the four that are darkened out, containing 20 black blocks instead of real characters. So my guess was that the background-color indeed is relevant as is. At least I think so? – Mathias May 16 '19 at 07:02
  • Quick reply - yes, adjusting background lighting is important. You see only two of four line, perhaps because by default is 16 x 2, so if properly initialized, should hopefully see 4 lines. (2) To remove the pin numbering error, try place the line GPIO.setmode(GPIO.BCM) or GPIO.setmode(GPIO.BOARD) after the # pin config comment, and try run the program again. I don't find the schematic. Perhaps I draw one and make an educated guess. Good luck. – tlfong01 May 16 '19 at 07:08
  • Just now I added the wiring diagram I am guessing at the end of my answer. It might be useful if we need to debug later. – tlfong01 May 16 '19 at 07:14
  • The Rpi BCM GPIO vs Board pin number is always confusing. So I added a picture as an appendix at the end of my answer to hopefully clarify a bit. – tlfong01 May 16 '19 at 07:20
  • I quickly checked again. Your module should be using the BCM GPIO numbering. So if you insert the statement "GPIO.setmode(GPIO.BCM)" the pin numbering error should disappear. – tlfong01 May 16 '19 at 07:25
  • About the lcd.init() function. If you use it and do not get any error message, then it should be somewhere. Do you have a link to the specific pi4j lcd library you are using? – tlfong01 May 16 '19 at 07:31
  • Just now I googled again and read a forum discussion that the pi4j program they are talking about uses another numbering method called "wiring pi" pin numbering, and they said it was the cause of the errors. BTW, I am going to gym and then supper. So see you tomorrow. Good luck. – tlfong01 May 16 '19 at 07:39
  • I set GPIO.setmode(GPIO.BOARD) after the line '# PIN-Configuration'. Now I get the following error message: Traceback (most recent call last): File "lcd20x4-2.py", line 79, in InitLCD() File "lcd20x4-2.py", line 60, in InitLCD SendByte(0x33) #initialize File "lcd20x4-2.py", line 51, in SendByte GPIO.output(LCD_RS,charMode) #set mode: command vs. char RuntimeError: The GPIO channel has not been set up as an OUTPUT – Mathias May 16 '19 at 11:22
  • Ah, I guess I have not written in enough detail. I mean you can try .Board first. If still error, then try .BCM. Later I found out that .BCM should work. So I then said you should try .BCM. Anyway, if you have not tried GPIO.setmode(GPIO.BCM), then try it now. Good luck!. – tlfong01 May 16 '19 at 11:52
  • My bad, I actually tried .bcm before .board, and it also did not work. Also, I tried changing the background-color, but it was good as I already suspected. I really appreciate your help =) – Mathias May 16 '19 at 13:29
  • Let me see. If error message suggests you to use GPIO.setmode, usually it means that the system cannot find the GPIO pin to assign it to output mode etc. Perhaps there is some bug in the program. I would suggest you to take a break now, and let me think again perhaps let you know tomorrow, or day after tomorrow. – tlfong01 May 16 '19 at 13:44
  • @Mathias I checked the programs I uploaded and found I made a careless mistake in copying the code from the user guide. My apologies. Now I have uploaded the corrected version in Appendix D, at the very end of my answer. Please try it again. and let me know the error message or results. – tlfong01 May 16 '19 at 14:43
  • I tried running the program, and no error-messages are displayed. However, it fails to change the display, I see the same result of blackened lines. Any ideas? – Mathias May 20 '19 at 06:15
  • Thank you for your feedback. I checked the program again and guess that there are other incompatible things beside BCM/board/wiringPi pin numbering. I also suspect other possible errors. Now I am thinking of using my own 2004 LCD module and use the same GPIO pins as your board to test out the Joy-IT program. I need to search my junk box to find my LCD module. It might take some time. So you might like to wait for my test results. – tlfong01 May 20 '19 at 06:23
  • I would appreciate it though :) – Mathias May 20 '19 at 06:29