4

I use a 16*2 screen (refe: EA W162-X3LW) for a project. I manage to display some text and scrolling text on it as I wanted but when I kill the code with the Keyboard, my GPIOs are not cleared as they should be. If I run the code a first time after booting the RPi the screen display the text properly. If I kill it then I get some Warnings telling me my channels are already in used and the screen display weird characters... I have to shutdown the RPi to clear the screen and clean my GPIOs. Does anybody knows what I making wrong ?

Here is the code :

# The wiring for the LCD is as follows:
# 1 : GND
# 2 : 5V
# 3 : Contrast (0-5V)*
# 4 : RS (Register Select)
# 5 : R/W (Read Write)       - GROUND THIS PIN
# 6 : Enable or Strobe
# 7 : Data Bit 0             - NOT USED - CAN BE USED FOR 8 BITS
# 8 : Data Bit 1             - NOT USED - CAN BE USED FOR 8 BITS
# 9 : Data Bit 2             - NOT USED - CAN BE USED FOR 8 BITS
# 10: Data Bit 3             - NOT USED - CAN BE USED FOR 8 BITS
# 11: Data Bit 4
# 12: Data Bit 5
# 13: Data Bit 6
# 14: Data Bit 7
# 15: LCD Backlight +5V**
# 16: LCD Backlight GND

#import
import RPi.GPIO as GPIO
import time

# Define GPIO to LCD mapping
LCD_RS = 23  # Blue cable 
LCD_E  = 18  # Green cable
LCD_D4 = 12  # Yellow cable
LCD_D5 = 16  # Yellow cable
LCD_D6 = 20  # Yellow cable
LCD_D7 = 21  # Yellow cable

# Define some device constants
LCD_WIDTH = 16    # Maximum characters per line
LCD_CHR = True
LCD_CMD = False

LCD_LINE_1 = 0x80 # LCD RAM address for the 1st line
LCD_LINE_2 = 0xC0 # LCD RAM address for the 2nd line

# Timing constants
E_PULSE = 0.00005
E_DELAY = 0.00005

def main():
  # Main program block
  GPIO.setmode(GPIO.BCM)       # Use BCM GPIO numbers
  GPIO.setup(LCD_E, GPIO.OUT)  # E
  GPIO.setup(LCD_RS, GPIO.OUT) # RS
  GPIO.setup(LCD_D4, GPIO.OUT) # DB4
  GPIO.setup(LCD_D5, GPIO.OUT) # DB5
  GPIO.setup(LCD_D6, GPIO.OUT) # DB6
  GPIO.setup(LCD_D7, GPIO.OUT) # DB7

  # Initialise display
  lcd_init()

  while True:
    str_pad = " " * 16

    # HELLO
    lcd_stringfix("HELLO",LCD_LINE_1)
    time.sleep(2)
    lcd_stringfix("ALL RIGHT",LCD_LINE_1)

    my_long_string = "P1 : " "P2 : " "P3 : "
    my_long_string = str_pad + my_long_string
    for i in range (0, len(my_long_string)):
     lcd_byte(LCD_LINE_2, LCD_CMD)
     lcd_text = my_long_string[i:(i+15)]
     lcd_stringscroll(lcd_text,1)
     time.sleep(0.4)
    lcd_byte(LCD_LINE_2, LCD_CMD)
    lcd_stringscroll(str_pad,1)

    time.sleep(3) # 3 second delay

def lcd_init():
  # Initialise display
  lcd_byte(0x33,LCD_CMD)
  lcd_byte(0x32,LCD_CMD)
  lcd_byte(0x28,LCD_CMD)
  lcd_byte(0x0C,LCD_CMD)
  lcd_byte(0x06,LCD_CMD)
  lcd_byte(0x01,LCD_CMD)
  time.sleep(E_DELAY)

def lcd_stringfix(message,line):
  # Send string to display

  message = message.ljust(LCD_WIDTH," ")

  lcd_byte(line, LCD_CMD)

  for i in range(LCD_WIDTH):
    lcd_byte(ord(message[i]),LCD_CHR)

def lcd_stringscroll(message,style):
  # Send string to display
  # style=1 Left justified
  # style=2 Centred
  # style=3 Right justified

  if style==1:
    message = message.ljust(LCD_WIDTH," ")
  elif style==2:
    message = message.center(LCD_WIDTH," ")
  elif style==3:
    message = message.rjust(LCD_WIDTH," ")

  for i in range(LCD_WIDTH):
    lcd_byte(ord(message[i]),LCD_CHR)

def lcd_byte(bits, mode):
  # Send byte to data pins
  # bits = data
  # mode = True  for character
  #        False for command

  GPIO.output(LCD_RS, mode) # RS

  # High bits
  GPIO.output(LCD_D4, False)
  GPIO.output(LCD_D5, False)
  GPIO.output(LCD_D6, False)
  GPIO.output(LCD_D7, False)
  if bits&0x10==0x10:
    GPIO.output(LCD_D4, True)
  if bits&0x20==0x20:
    GPIO.output(LCD_D5, True)
  if bits&0x40==0x40:
    GPIO.output(LCD_D6, True)
  if bits&0x80==0x80:
    GPIO.output(LCD_D7, True)

  # Toggle 'Enable' pin
  lcd_toggle_enable()

  # Low bits
  GPIO.output(LCD_D4, False)
  GPIO.output(LCD_D5, False)
  GPIO.output(LCD_D6, False)
  GPIO.output(LCD_D7, False)
  if bits&0x01==0x01:
    GPIO.output(LCD_D4, True)
  if bits&0x02==0x02:
    GPIO.output(LCD_D5, True)
  if bits&0x04==0x04:
    GPIO.output(LCD_D6, True)
  if bits&0x08==0x08:
    GPIO.output(LCD_D7, True)

  # Toggle 'Enable' pin
  lcd_toggle_enable()

def lcd_toggle_enable():
  # Toggle enable
  time.sleep(E_DELAY)
  GPIO.output(LCD_E, True)
  time.sleep(E_PULSE)
  GPIO.output(LCD_E, False)
  time.sleep(E_DELAY)

if __name__ == '__main__':
  main()

  try:
    GPIO.setwarnings(False)
    main()
  except KeyboardInterrupt:
    pass
  finally:
    lcd_byte(0x01, LCD_CMD)
    lcd_string("Goodbye!",LCD_LINE_1)
    print "Interrupt"
    time.sleep(1)
    GPIO.cleanup()
1

I am going to assume the error is the superfluous early call to main() as you gave no explanation for why it was there.

if __name__ == '__main__':
  main()

  try:
    GPIO.setwarnings(False)
    main()
  except KeyboardInterrupt:
    pass
  finally:
    lcd_byte(0x01, LCD_CMD)
    lcd_string("Goodbye!",LCD_LINE_1)
    print "Interrupt"
    time.sleep(1)
    GPIO.cleanup()

Perhaps you should have

if __name__ == '__main__':
  try:
    GPIO.setwarnings(False)
    main()
  except KeyboardInterrupt:
    pass
  finally:
    lcd_byte(0x01, LCD_CMD)
    lcd_string("Goodbye!",LCD_LINE_1)
    print "Interrupt"
    time.sleep(1)
    GPIO.cleanup()
  • 1
    Thanks joan. You are right this was a mistake. Also lcd_string to be changed in lcd_stringfix. However when I run the code the weird characters are still displayed on my screen... The screen is not cleared. – Rixpuk Dec 22 '15 at 11:16
  • Did the code ever work? Have you ruled out a wiring problem? – joan Dec 22 '15 at 11:31
  • The GPIO.cleanup() has never work properly. I always have the warnings. I didn't experience any wiring issue... The only way that works to clear the screen is to unplug the Raspi, even reboot doesn't work. When I try to display an empty character, weird character are displayed instead. – Rixpuk Dec 22 '15 at 11:44
  • Does writing text work? Is it only commands, like clear screen, which are failing? – joan Dec 22 '15 at 13:03
  • Yes writing text work. Scrolling text also. Just GPIO.cleanup() does not do anything apparently. – Rixpuk Dec 22 '15 at 13:20
1

I have an I2C backpack equipped 16x02 LCD and I see strong similarities with the above code in what I had with mine. I too got odd termination effects so I changed the finally: block to be:

  finally:
    lcd_string("    Goodbye!    ",LCD_LINE_1)
    lcd_string("                ",LCD_LINE_2)
    time.sleep(E_DELAY)
    lcd_byte(0x01, LCD_CMD)
    time.sleep(E_DELAY)
    lcd_byte(0x01, LCD_CMD)
    time.sleep(E_DELAY)

Now I do not use the GPIO pins in quite the same way so I did not have a GPIO.cleanup() call - you will probably want to put it in. I do write to both lines on the display and I send the command to clear the display lcd_byte(0x01, LCD_CMD) AFTER that and a delay - I see you clear the display and then write a "Goodbye" message. If you refer to the Wikipedia article on this type of display you will note that there is a significantly longer delay for the clear display (and the cursor home) commands compared to all the others to execute. I actually do it twice but in hindsight that may be overkill - however I do another delay after the second one before the program ends.

I would suggest that you include a delay after the GPIO.cleanup() too.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.