Raspberry Pi – LCD Display ansteuern

In meinem Hardware-Fundus hatte ich noch ein 16×2 Zeichen LCD Display wiederentdeckt, das wollte ich schon länger mal am Raspberry Pi testen und in Betrieb nehmen. Was liegt da näher, um für einen Funktionstest, die aktuelle Uhrzeit und die IP-Adresse meines Mini-Rechners auf dem Display auszugeben. In diesem kleinen Raspberry Pi Projekt zeige ich euch wie ihr ein 16×2 Zeichen LCD an den RasPi anschließt und via Python Script ansteuert.

Material

Folgendes Material habe ich verwendet

  • QC1602a 16×2 Zeichen LCD Display
  • Drehpotentiometer 50k Ohm
  • Breadboard
  • Steckbrettkabel Male-Male
  • GPIO Breakout

Falls ihr noch kein Breadboard und Kabel besitzt, das Ganze gibt es auch als Set inkl LCD und Poti.

Verkabelung des LCD Display

Die Verkabelung des Display scheint auf den ersten Blick recht komplex, habt ihr allerdings die die Funktion einmal verstanden ist das Setup recht einfach.

LCD-Display

Das LCD-Display hat 16 Pins. In der unten stehenden Tabelle habe ich die Verkabelung des Display dargestellt. Da ich, wie ihr auf den Bild erkennen könnt, ein GPIO Breakout verwende habe ich in der letzten Spalte die Verkabelung mit meinem Breakout dokumentiert.

Falls ihr das Display über ein anderes Breakout oder direkt am RasPi bzw. via Breadboard verkabeln wollt habe ich die RasPi GPIO Pins aufgeführt, wie immer ist es die Nummer des Pins auf der Leiste P1. Falls ihr euch unsicher bei der Zuordnung der Pins seit könnt ihr einen Blick auf mein GPIO Pin Worksheet werfen dort die Verbindungen eintragen.

LCD Pin LCD Funktion RasPi Funktion RasPi GPIO-Pin Mein Breakout (T-Cobbler)

01 GND GND GPIO Pin 6 GND

02 +5V +5V GPIO Pin 2 5V0

03 Contrast GND GPIO Pin 6 Potentiometer (mittlerer Pin)

04 RS GPIO7 GPIO Pin 26 CE1

05 RW GND GPIO Pin 6 GND

06 E GPIO8 GPIO Pin 24 CE0

07 Data 0    

08 Data 1    

09 Data 2    

10 Data 3    

11 Data 4 GPIO25 GPIO Pin 22 GPIO6

12 Data 5 GPIO24 GPIO Pin 18 GPIO5

13 Data 6 GPIO23 GPIO Pin 16 GPIO4

14 Data 7 GPIO18 GPIO Pin 12 GPIO1

15 +5V   GPIO Pin 2 5V0

16 GND   GPIO Pin 6 GND

Alternativ gibt es auf der Adafruit Seite ein passendes Verkabelungsdiagramm, allerdings verwenden die wieder eine anderes Breakout.

LCD Display am Raspberry Pi einrichten

Wir steuern das LCD Display via Python an, daher installieren wir als erstes die notwendigen Python Programme und Abhängigkeiten nachdem wir unser System aktualisiert via apt aktualisiert haben.

sudo apt-get -y update & sudo apt-get -y upgrade
sudo apt-get install -y python-dev python-setuptools python-pip git
sudo easy_install -U distribute 
sudo pip install rpi.gpio

Dann können wir direkt loslegen, das Python Script, welches ich vorbereitet haben laden wir uns via wget ins Home und machen es via chmod ausführbar.

cd ~
wget -O raspberry.tips.lcd.py http://cdn.raspberry.tips/2014/12/raspberry.tips_.lcd_.py_.txt
chmod +x raspberry.tips.lcd.py

Zum Testen eures LCD-Display können wir das Script nun direkt ausführen und uns die Ausgabe auf dem Display ansehen.

sudo python raspberry.tips.lcd.py

Eventuell müsst ihr noch über den Drehpoti den Kontrast eures LCDs einstellen, erhaltet ihr keine oder eine falsche Ausgabe liegt dies vermutlich an der falschen Verkabelung. Falls die angezeigte Uhrzeit nicht stimmt müsst ihr eure Zeitzone via Raspi-config auf die Deutsche (GMT +1) umstellen.

Wer möchte kann mit den unten aufgeführten Script die Ausgabe nach jedem Neustart des RasPi aktivieren. Hierzu müsst ihr den Code in die Datei /etc/init.d/lcd kopieren und dann folgende Befehle ausführen um /etc/init.d/lcd zum automatischen Start hinzuzufügen.

sudo chmod +x /etc/init.d/lcd
sudo update-rcd lcd defaults

 LCD Python Code

#!/usr/bin/python
# based on code from lrvick, LiquidCrystal and Adafruit


from time import sleep


class Adafruit_CharLCD(object):

    # commands
    LCD_CLEARDISPLAY        = 0x01
    LCD_RETURNHOME          = 0x02
    LCD_ENTRYMODESET        = 0x04
    LCD_DISPLAYCONTROL      = 0x08
    LCD_CURSORSHIFT         = 0x10
    LCD_FUNCTIONSET         = 0x20
    LCD_SETCGRAMADDR        = 0x40
    LCD_SETDDRAMADDR        = 0x80

    # flags for display entry mode
    LCD_ENTRYRIGHT          = 0x00
    LCD_ENTRYLEFT           = 0x02
    LCD_ENTRYSHIFTINCREMENT = 0x01
    LCD_ENTRYSHIFTDECREMENT = 0x00

    # flags for display on/off control
    LCD_DISPLAYON           = 0x04
    LCD_DISPLAYOFF          = 0x00
    LCD_CURSORON            = 0x02
    LCD_CURSOROFF           = 0x00
    LCD_BLINKON             = 0x01
    LCD_BLINKOFF            = 0x00

    # flags for display/cursor shift
    LCD_DISPLAYMOVE         = 0x08
    LCD_CURSORMOVE          = 0x00

    # flags for display/cursor shift
    LCD_DISPLAYMOVE         = 0x08
    LCD_CURSORMOVE          = 0x00
    LCD_MOVERIGHT           = 0x04
    LCD_MOVELEFT            = 0x00

    # flags for function set
    LCD_8BITMODE            = 0x10
    LCD_4BITMODE            = 0x00
    LCD_2LINE               = 0x08
    LCD_1LINE               = 0x00
    LCD_5x10DOTS            = 0x04
    LCD_5x8DOTS             = 0x00

    def __init__(self, pin_rs=7, pin_e=8, pins_db=[25, 24, 23, 18], GPIO=None):
        # Emulate the old behavior of using RPi.GPIO if we haven't been given
        # an explicit GPIO interface to use
        if not GPIO:
            import RPi.GPIO as GPIO
            GPIO.setwarnings(False)
        self.GPIO = GPIO
        self.pin_rs = pin_rs
        self.pin_e = pin_e
        self.pins_db = pins_db

        self.GPIO.setmode(GPIO.BCM)
        self.GPIO.setup(self.pin_e, GPIO.OUT)
        self.GPIO.setup(self.pin_rs, GPIO.OUT)

        for pin in self.pins_db:
            self.GPIO.setup(pin, GPIO.OUT)

        self.write4bits(0x33)  # initialization
        self.write4bits(0x32)  # initialization
        self.write4bits(0x28)  # 2 line 5x7 matrix
        self.write4bits(0x0C)  # turn cursor off 0x0E to enable cursor
        self.write4bits(0x06)  # shift cursor right

        self.displaycontrol = self.LCD_DISPLAYON | self.LCD_CURSOROFF | self.LCD_BLINKOFF

        self.displayfunction = self.LCD_4BITMODE | self.LCD_1LINE | self.LCD_5x8DOTS
        self.displayfunction |= self.LCD_2LINE

        # Initialize to default text direction (for romance languages)
        self.displaymode = self.LCD_ENTRYLEFT | self.LCD_ENTRYSHIFTDECREMENT
        self.write4bits(self.LCD_ENTRYMODESET | self.displaymode)  # set the entry mode

        self.clear()

    def begin(self, cols, lines):
        if (lines > 1):
            self.numlines = lines
            self.displayfunction |= self.LCD_2LINE

    def home(self):
        self.write4bits(self.LCD_RETURNHOME)  # set cursor position to zero
        self.delayMicroseconds(3000)  # this command takes a long time!

    def clear(self):
        self.write4bits(self.LCD_CLEARDISPLAY)  # command to clear display
        self.delayMicroseconds(3000)  # 3000 microsecond sleep, clearing the display takes a long time

    def setCursor(self, col, row):
        self.row_offsets = [0x00, 0x40, 0x14, 0x54]
        if row > self.numlines:
            row = self.numlines - 1  # we count rows starting w/0
        self.write4bits(self.LCD_SETDDRAMADDR | (col + self.row_offsets[row]))

    def noDisplay(self):
        """ Turn the display off (quickly) """
        self.displaycontrol &= ~self.LCD_DISPLAYON
        self.write4bits(self.LCD_DISPLAYCONTROL | self.displaycontrol)

    def display(self):
        """ Turn the display on (quickly) """
        self.displaycontrol |= self.LCD_DISPLAYON
        self.write4bits(self.LCD_DISPLAYCONTROL | self.displaycontrol)

    def noCursor(self):
        """ Turns the underline cursor off """
        self.displaycontrol &= ~self.LCD_CURSORON
        self.write4bits(self.LCD_DISPLAYCONTROL | self.displaycontrol)

    def cursor(self):
        """ Turns the underline cursor on """
        self.displaycontrol |= self.LCD_CURSORON
        self.write4bits(self.LCD_DISPLAYCONTROL | self.displaycontrol)

    def noBlink(self):
        """ Turn the blinking cursor off """
        self.displaycontrol &= ~self.LCD_BLINKON
        self.write4bits(self.LCD_DISPLAYCONTROL | self.displaycontrol)

    def blink(self):
        """ Turn the blinking cursor on """
        self.displaycontrol |= self.LCD_BLINKON
        self.write4bits(self.LCD_DISPLAYCONTROL | self.displaycontrol)

    def DisplayLeft(self):
        """ These commands scroll the display without changing the RAM """
        self.write4bits(self.LCD_CURSORSHIFT | self.LCD_DISPLAYMOVE | self.LCD_MOVELEFT)

    def scrollDisplayRight(self):
        """ These commands scroll the display without changing the RAM """
        self.write4bits(self.LCD_CURSORSHIFT | self.LCD_DISPLAYMOVE | self.LCD_MOVERIGHT)

    def leftToRight(self):
        """ This is for text that flows Left to Right """
        self.displaymode |= self.LCD_ENTRYLEFT
        self.write4bits(self.LCD_ENTRYMODESET | self.displaymode)

    def rightToLeft(self):
        """ This is for text that flows Right to Left """
        self.displaymode &= ~self.LCD_ENTRYLEFT
        self.write4bits(self.LCD_ENTRYMODESET | self.displaymode)

    def autoscroll(self):
        """ This will 'right justify' text from the cursor """
        self.displaymode |= self.LCD_ENTRYSHIFTINCREMENT
        self.write4bits(self.LCD_ENTRYMODESET | self.displaymode)

    def noAutoscroll(self):
        """ This will 'left justify' text from the cursor """
        self.displaymode &= ~self.LCD_ENTRYSHIFTINCREMENT
        self.write4bits(self.LCD_ENTRYMODESET | self.displaymode)

    def write4bits(self, bits, char_mode=False):
        """ Send command to LCD """
        self.delayMicroseconds(1000)  # 1000 microsecond sleep
        bits = bin(bits)[2:].zfill(8)
        self.GPIO.output(self.pin_rs, char_mode)
        for pin in self.pins_db:
            self.GPIO.output(pin, False)
        for i in range(4):
            if bits[i] == "1":
                self.GPIO.output(self.pins_db[::-1][i], True)
        self.pulseEnable()
        for pin in self.pins_db:
            self.GPIO.output(pin, False)
        for i in range(4, 8):
            if bits[i] == "1":
                self.GPIO.output(self.pins_db[::-1][i-4], True)
        self.pulseEnable()

    def delayMicroseconds(self, microseconds):
        seconds = microseconds / float(1000000)  # divide microseconds by 1 million for seconds
        sleep(seconds)

    def pulseEnable(self):
        self.GPIO.output(self.pin_e, False)
        self.delayMicroseconds(1)       # 1 microsecond pause - enable pulse must be > 450ns
        self.GPIO.output(self.pin_e, True)
        self.delayMicroseconds(1)       # 1 microsecond pause - enable pulse must be > 450ns
        self.GPIO.output(self.pin_e, False)
        self.delayMicroseconds(1)       # commands need > 37us to settle

    def message(self, text):
        """ Send string to LCD. Newline wraps to second line"""
        for char in text:
            if char == '\n':
                self.write4bits(0xC0)  # next line
            else:
                self.write4bits(ord(char), True)


if __name__ == '__main__':
    lcd = Adafruit_CharLCD()	
	cmd = "ip addr show eth0 | grep inet | awk '{print $2}' | cut -d/ -f1"

	lcd.begin(16, 1)


	def run_cmd(cmd):
		p = Popen(cmd, shell=True, stdout=PIPE)
		output = p.communicate()[0]
		return output

	while 1:
		lcd.clear()
		ipaddr = run_cmd(cmd)
		lcd.message(datetime.now().strftime('%b %d  %H:%M:%S\n'))
		lcd.message('IP %s' % (ipaddr))
		sleep(2)

Autostart Script

### BEGIN INIT INFO
# Provides: LCD - date / time / ip address
# Required-Start: $remote_fs $syslog
# Required-Stop: $remote_fs $syslog
# Default-Start: 2 3 4 5
# Default-Stop: 0 1 6
# Short-Description: Liquid Crystal Display
# Description: date / time / ip address
### END INIT INFO

#! /bin/sh
# /etc/init.d/lcd

export HOME
case "$1" in
    start)
        echo "Starting LCD"
        /home/pi/raspberry.tips.lcd.py 2>&1 &
    ;;
    stop)
        echo "Stopping LCD"
	LCD_PID=`ps auxwww | grep raspberry.tips.lcd.py | head -1 | awk '{print $2}'`
	kill -9 $LCD_PID
    ;;
    *)
        echo "Usage: /etc/init.d/lcd {start|stop}"
        exit 1
    ;;
esac
exit 0

 


wallpaper-1019588
Winter Tollwood 2024
wallpaper-1019588
TOKYOPOP: Das sind die Boys Love- und Girls-Love-Lizenzen
wallpaper-1019588
Clevatess: Neuigkeiten zum Anime + Visual
wallpaper-1019588
The Dark History of the Reincarnated Villainess: Neuigkeiten zum Anime bekannt gegeben