LCD scherm 20×4 met behulp van I2C aansturen

In dit stappenplan gaan we een generiek LCD scherm (4 regels van 20 karakters) dat is voorzien van een I2C backpack aansluiten op een Raspberry Pi. Het scherm is in verschillende kleuren beschikbaar en kan worden aangesloten zowel 5V als 3.3V.

Het LCD backpack aansturen met behulp van een speciaal Python script waarmee we systeeminformatie op het scherm laten verschijnen. Maar natuurlijk kan je ook zelf informatie op het scherm laten verschijnen.

Gebruikte componenten

20×4 Character LCD met IIC/I2C Backpack Module
Logic Level Shifter Bi-directioneel
10x Dupont verbindingskabel (female/female)

Kosten componenten: 4,50€

Raspberry Pi Zero, Raspberry Pi 2, Raspberry Pi 3
Raspbian Jessie (2016-05-27 kernel 4.4.13)

Aansluitschema 3.3V

Je kunt het I2C backpack direct aansluiten op de Raspberry Pi zonder gebruik te maken van een level shifter. Je maakt dan gebruik van de 3.3V pin, het enige nadeel hiervan is dat de helderheid van de backlight iets minder is dan wanneer je 5V gebruikt. Het voordeel: met vier kabeltjes is het LCD scherm aangesloten!

Raspberry Pi I2C backpack
3.3V (PIN #1) VCC
SDA (PIN #3) SDA
SCL (PIN #5) SCL
GND (PIN #6) GND

i2c backpack raspberry pi

Aansluitschema 5V

De I2C module kan gevoed worden met 5V of 3.3V maar geeft de beste helderheid als je gebruik maakt van 5V. De GPIO pins van de Raspberry Pi zijn echter niet 5V ’tolerant’ vandaar dat we een I2C level shifter gebruiken. Op de level shifter wordt zowel 3.3V als 5V als referentie aangesloten.

Raspberry Pi Level Shifter I2C backpack
3.3V (PIN #1) LV
SDA (PIN #3) LV1
SCL (PIN #5) LV2
GND (PIN #6) GND
5V (PIN #2) HV
5V (PIN #3) VCC
HV1 SDA
HV2 SCL
GND GND

I2C Activeren

Om tekst op het LCD scherm te krijgen gebruiken we een speciaal Python script dat de I2C interface aanstuurt. Om toegang te krijgen tot de interface dient deze in de Raspberry Pi geactiveerd te zijn. Je kunt deze activeren met behulp van raspi-config.

sudo raspi-config

Selecteer de optie ‘Advanced Options’ ▸ ‘I2C’ en kies ‘YES’ om de I2C interface te activeren.

Controleren werking I2C

Nadat de module is aangesloten op de I2C bus kun je controleren of deze ook daadwerkelijk wordt gedetecteerd. Dit kun je doen met de I2C tools, heb je deze niet geïnstalleerd dan kun je dit doen met behulp van:

sudo apt-get install i2c-tools

Controleer hierna of de module zichtbaar is:

sudo i2cdetect -y 1

i2cdetect

De LCD backpack module heeft als ID #03F. Mocht de module niet zichtbaar zijn controleer dan of de kabels goed zijn aangesloten.

Wordt er een andere waarde dan #03F weergeven, wijzig dan in het script de parameter I2C_ADDR in de waarde die verschijnt in de i2cdetect tool.

lcd scherm 20x4 raspberry pi i2c

LCD scherm Python script

Een demo script om de werking van het LCD display te testen:

#!/usr/bin/python
# https://raspberrytips.nl/lcd-scherm-20x4-i2c-raspberry-pi/
import sys
import smbus
import time
import datetime
import subprocess
I2C_ADDR = 0x3F # I2C device address
LCD_WIDTH = 20 # Maximum characters per line
# Define some device constants
LCD_CHR = 1 # Mode - Sending data
LCD_CMD = 0 # Mode - Sending command
LCD_LINE_1 = 0x80 # LCD RAM address for the 1st line
LCD_LINE_2 = 0xC0 # LCD RAM address for the 2nd line
LCD_LINE_3 = 0x94 # LCD RAM address for the 3rd line
LCD_LINE_4 = 0xD4 # LCD RAM address for the 4th line
LCD_BACKLIGHT = 0x08 # On 0X08 / Off 0x00
ENABLE = 0b00000100 # Enable bit
E_PULSE = 0.0005
E_DELAY = 0.0005
bus = smbus.SMBus(1) # Rev 2 Pi uses 1
def run_cmd(cmd):
return subprocess.check_output(cmd, shell=True).decode('utf-8')
def get_my_ipwlan():
val = run_cmd("/sbin/ifconfig wlan0 | grep 'inet addr:' | cut -d: -f2 | awk '{ print $1}'")[:-1]
if val == "":
val = "No connection!"
return val
def get_my_ipeth():
val = run_cmd("/sbin/ifconfig eth0 | grep 'inet addr:' | cut -d: -f2 | awk '{ print $1}'")[:-1]
if val == "":
val = "No connection"
return val
def lcd_init():
lcd_byte(0x33,LCD_CMD) # 110011 Initialise
lcd_byte(0x32,LCD_CMD) # 110010 Initialise
lcd_byte(0x06,LCD_CMD) # 000110 Cursor move direction
lcd_byte(0x0C,LCD_CMD) # 001100 Display On,Cursor Off, Blink Off
lcd_byte(0x28,LCD_CMD) # 101000 Data length, number of lines, font size
lcd_byte(0x01,LCD_CMD) # 000001 Clear display
time.sleep(E_DELAY)
def lcd_byte(bits, mode):
bits_high = mode | (bits & 0xF0) | LCD_BACKLIGHT
bits_low = mode | ((bits<<4) & 0xF0) | LCD_BACKLIGHT
bus.write_byte(I2C_ADDR, bits_high)
lcd_toggle_enable(bits_high)
bus.write_byte(I2C_ADDR, bits_low)
lcd_toggle_enable(bits_low)
def lcd_toggle_enable(bits):
time.sleep(E_DELAY)
bus.write_byte(I2C_ADDR, (bits | ENABLE))
time.sleep(E_PULSE)
bus.write_byte(I2C_ADDR,(bits & ~ENABLE))
time.sleep(E_DELAY)
def lcd_string(message,line):
message = message.ljust(LCD_WIDTH," ")
lcd_byte(line, LCD_CMD)
for i in range(LCD_WIDTH):
lcd_byte(ord(message[i]),LCD_CHR)
def main():
lcd_init()
while True:
now = datetime.datetime.now()
lcd_string("RASPBERRYTIPS.NL",LCD_LINE_1)
lcd_string( str(now.day)+'/'+str(now.month)+'/'+str(now.year)+' '+str(now.hour)+':'+str(now.minute),LCD_LINE_2)
lcd_string("W:{}".format(get_my_ipwlan()),LCD_LINE_3)
lcd_string("E:{}".format(get_my_ipeth()),LCD_LINE_4)
time.sleep(60)
if __name__ == '__main__':
try:
main()
except KeyboardInterrupt:
pass
finally:
lcd_byte(0x01, LCD_CMD)
view raw lcd20x4.py hosted with ❤ by GitHub

Kopieer of download het Python script:

wget https://raspberrytips.nl/lcd20x4.py

Activeer het script:

sudo python lcd20x4.py

Op het scherm verschijnt nu de url van deze website en op de tweede regel de actuele datum en tijd. Op de derde en vierde regel respectievelijk het WIFI en WLAN IP adres. Je kunt natuurlijk ook zelf informatie weergeven zoals bijvoorbeeld waardes van sensoren.

I2C Script parameters

lcd_init()
Reset en activeer het LCD scherm.

lcd_string("tekst",LCD_LINE_1)
Plaats ’tekst’ maximaal 20 characters op de eerste regel LCD_LINE_1, het getal op het einde geeft de de regel aan waarop de tekst moet worden geplaatst.

6 gedachten over “LCD scherm 20×4 met behulp van I2C aansturen”

  1. Hallo Richard,

    De module is zichtbaar (3F) maar ik krijg geen tekst te zien op het display. Aangezien ik 2 ic2 en 2 displays heb en deze in alle combinaties heb geprobeerd is het hoogstwaarschijnlijk geen hardware probleem. Ik heb een Raspberry Pi 3B met Jessie. Enig idee waar dit aan kan liggen?

    *Mijn eerste reactie werd trouwens niet geplaats

    Beantwoorden
  2. Er zit een foutje in de pin-tabel bij “Aansluitschema 5V”.
    “5V (PIN #3)” moet denk ik “5V (PIN #4)” zijn, want een paar regels er boven staat al “SDA (PIN #3)” en pin 3 is niet voor de algemene 5V stroom.

    Beantwoorden
  3. Het script werket niet op mijn nieuwe RPi met Buster omdat ifconfig ietwat andere output geeft. Het deel addr: is weg, vandaar dat je een stukje code moet aanpassen.

    def get_my_ipwlan():
    val = run_cmd(“/sbin/ifconfig wlan0 | grep ‘inet ‘ | cut -d: -f2 | awk ‘{ print $2}'”)[:-1]
    if val == “”:
    val = “No connection!”
    return val

    def get_my_ipeth():
    val = run_cmd(“/sbin/ifconfig eth0 | grep ‘inet ‘ | cut -d: -f2 | awk ‘{ print $2}'”)[:-1]
    if val == “”:
    val = “No connection”
    return val

    Beantwoorden
  4. Ik heb de code nog wat aangepast voor de laatste versie van Buster (05082021)

    #!/usr/bin/python
    # https://raspberrytips.nl/lcd-scherm-20×4-i2c-raspberry-pi/

    import sys
    import smbus
    import time
    import datetime
    import subprocess

    #I2C_ADDR = 0x3F # I2C device address
    I2C_ADDR = 0x27 # I2C device address
    LCD_WIDTH = 20 # Maximum characters per line

    # Define some device constants
    LCD_CHR = 1 # Mode – Sending data
    LCD_CMD = 0 # Mode – Sending command

    LCD_LINE_1 = 0x80 # LCD RAM address for the 1st line
    LCD_LINE_2 = 0xC0 # LCD RAM address for the 2nd line
    LCD_LINE_3 = 0x94 # LCD RAM address for the 3rd line
    LCD_LINE_4 = 0xD4 # LCD RAM address for the 4th line

    LCD_BACKLIGHT = 0x08 # On 0X08 / Off 0x00

    ENABLE = 0b00000100 # Enable bit

    E_PULSE = 0.0005
    E_DELAY = 0.0005

    bus = smbus.SMBus(1) # Rev 2 Pi uses 1

    def run_cmd(cmd):
    return subprocess.check_output(cmd, shell=True).decode(‘utf-8’)

    def get_my_ipwlan():
    val = run_cmd(“/sbin/ifconfig wlan0 | grep -w ‘inet’ |cut -c 14-28 | awk ‘{ print $1}'”)[:-1]
    if val == “”:
    val = “No connection!”
    return val

    def get_my_ipeth():
    val = run_cmd(“/sbin/ifconfig enxb827eb62bee2 | /sbin/ifconfig enxb827eb62bee2 | grep -w ‘inet’ |cut -c 14-28 | awk ‘{ print $1}'”)[:-1]
    if val == “”:
    val = “No connection”
    return val

    def lcd_init():
    lcd_byte(0x33,LCD_CMD) # 110011 Initialise
    lcd_byte(0x32,LCD_CMD) # 110010 Initialise
    lcd_byte(0x06,LCD_CMD) # 000110 Cursor move direction
    lcd_byte(0x0C,LCD_CMD) # 001100 Display On,Cursor Off, Blink Off
    lcd_byte(0x28,LCD_CMD) # 101000 Data length, number of lines, font size
    lcd_byte(0x01,LCD_CMD) # 000001 Clear display
    time.sleep(E_DELAY)

    def lcd_byte(bits, mode):

    bits_high = mode | (bits & 0xF0) | LCD_BACKLIGHT
    bits_low = mode | ((bits<<4) & 0xF0) | LCD_BACKLIGHT

    bus.write_byte(I2C_ADDR, bits_high)
    lcd_toggle_enable(bits_high)

    bus.write_byte(I2C_ADDR, bits_low)
    lcd_toggle_enable(bits_low)

    def lcd_toggle_enable(bits):
    time.sleep(E_DELAY)
    bus.write_byte(I2C_ADDR, (bits | ENABLE))
    time.sleep(E_PULSE)
    bus.write_byte(I2C_ADDR,(bits & ~ENABLE))
    time.sleep(E_DELAY)

    def lcd_string(message,line):

    message = message.ljust(LCD_WIDTH," ")

    lcd_byte(line, LCD_CMD)

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

    def main():

    lcd_init()

    while True:

    now = datetime.datetime.now()

    lcd_string("PA0ESH-10 iGate APRX",LCD_LINE_1)
    lcd_string( str(now.day)+'/'+str(now.month)+'/'+str(now.year)+' '+str(now.hour)+':'+str(now.minute),LCD_LINE_2)
    lcd_string("W:{}".format(get_my_ipwlan()),LCD_LINE_3)
    lcd_string("E:{}".format(get_my_ipeth()),LCD_LINE_4)
    time.sleep(60)

    if __name__ == '__main__':

    try:
    main()
    except KeyboardInterrupt:
    pass
    finally:
    lcd_byte(0x01, LCD_CMD)
    root@hampi:/home/pi# ^C
    root@hampi:/home/pi# nano lcd20x4.py

    GNU nano 3.2 lcd20x4.py

    lcd_init()

    while True:

    now = datetime.datetime.now()

    lcd_string("MY OWN STRING",LCD_LINE_1)
    lcd_string( str(now.day)+'/'+str(now.month)+'/'+str(now.year)+' '+str(now.hour)+':'+str(now.minute),LCD_LINE_2)
    lcd_string("W:{}".format(get_my_ipwlan()),LCD_LINE_3)
    lcd_string("E:{}".format(get_my_ipeth()),LCD_LINE_4)
    time.sleep(60)

    if __name__ == '__main__':

    try:
    main()
    except KeyboardInterrupt:
    pass
    finally:
    lcd_byte(0x01, LCD_CMD)

    Beantwoorden

Plaats een reactie