wie vor ein paar Tagen schon angekündigt habe ich versucht, ein alphanumerisches Display am Raspberry Pi einzurichten. Jetzt habe ich die Implementierung halbwegs fertig und wollte mal fragen, ob ihr da eventuell etwas rübergucken könntet? Es sind noch einige kleinere Fehler drin, aber im Großen und Ganzen klappt das mit dem Display.
Benutzung:
Code: Alles auswählen
databus = [1, 2, 3, 4, 5, 6, 7, 8] (da müssen die Ausgänge vom GPIO eingetragen werden)
lcd_e = 9
lcd_rs = 10
lcd_control = LcdControl(data_bus, lcd_e, lcd_rs, 16, 2)
lcd_control.write("Hallo")
Code: Alles auswählen
class LcdControl(object):
def __init__(self, data_bus, lcd_e, lcd_rs, columns, rows):
self.data_bus = data_bus
self.lcd_enable = lcd_e
self.lcd_rs = lcd_rs
self.columns = columns
self.rows = rows
if len(data_bus) == 4:
self.four_bit = True
else:
self.four_bit = False
#Konstanten
self.PULSE = 0.00002
self.PAUSE = 0.0001
self.LCD_CLEAR_DISPLAY = 0x01 #0b00000001
self.LCD_CURSOR_HOME = 0x02 #0b00000010
self.LCD_SOFT_RESET = 0x30 #0b00110000
#Set Function: 0b001xxxxx
#Die Werte werden mit bitweisem ODER (|) aufaddiert.
#Die Optionen werden dann als Maske zusätzlich gesetzt.
self.LCD_SET_FUNCTION = 0x20 #0b00100000
self.LCD_FUNCTION_4BIT = 0x00 #0b00000000
self.LCD_FUNCTION_8BIT = 0x10 #0b00010000
self.LCD_FUNCTION_1LINE = 0x00 #0b00000000
self.LCD_FUNCTION_2LINE = 0x08 #0b00001000
self.LCD_FUNCTION_5X7 = 0x00 #0b00000000
self.LCD_FUNCTION_5X10 = 0x04 #0b00000100
#Set Display: 0b00001xxx
self.LCD_SET_DISPLAY = 0x08 #0b00001000
self.LCD_DISPLAY_OFF = 0x00 #0b00000000
self.LCD_DISPLAY_ON = 0x04 #0b00000100
self.LCD_CURSOR_OFF = 0x00 #0b00000000
self.LCD_CURSOR_ON = 0x02 #0b00000010
self.LCD_BLINKING_OFF = 0x00 #0b00000000
self.LCD_BLINKING_ON = 0x01 #0b00000001
#Set Entry Mode: 0b000001xx
self.LCD_SET_ENTRY = 0x04 #0b00000100
self.LCD_ENTRY_DECREASE = 0x00 #0b00000000
self.LCD_ENTRY_INCREASE = 0x02 #0b00000010
self.LCD_ENTRY_NOSHIFT = 0x00 #0b00000000
self.LCD_ENTRY_SHIFT = 0x01 #0b00000001
#Set DD RAM Address: 0b1xxxxxxx
#Zweite Zeile startet mit 40
self.LCD_DDADR = 0x80 #0b10000000
self.LCD_DD_ROWS = [0x00, 0x40]
self.LCD_CGADR = 0x40 #0b01000000
self._initialize_lcd()
def _initialize_lcd(self):
self._set_data_bus_low()
for i in range(3):
self.write_command(self.LCD_SOFT_RESET)
time.sleep(self.PAUSE)
self.write_command(self.LCD_SET_FUNCTION |
self.LCD_FUNCTION_8BIT |
self.LCD_FUNCTION_2LINE |
self.LCD_FUNCTION_5X7)
self.write_command(self.LCD_SET_DISPLAY |
self.LCD_DISPLAY_ON |
self.LCD_CURSOR_OFF |
self.LCD_BLINKING_OFF)
self.write_command(self.LCD_SET_ENTRY |
self.LCD_ENTRY_INCREASE |
self.LCD_ENTRY_NOSHIFT)
self.write_command(self.LCD_CLEAR_DISPLAY)
def _send_command(self, value, command):
"""Schickt einen Befehl an das LCD, wartet eine kleine Weile und setzt
alles wieder auf Low.
Bitte nicht direkt aufrufen, sondern write_command() bzw.
write_character().
value muss ein Integer zwischen 0-255 sein.
command = True: Kommando, lcd_rs ist LOW.
command = False: Text, lcd_rs ist HIGH,
"""
if command:
self._send_byte(value, True)
else:
self._send_byte(value, False)
time.sleep(self.PULSE)
self._set_data_bus_low()
time.sleep(self.PULSE)
def _send_enable_pulse(self):
"""Schaltet das Enable-Signal HIGH und nach einer Pause wieder LOW"""
GPIO.output(self.lcd_enable, GPIO.HIGH)
time.sleep(self.PULSE)
GPIO.output(self.lcd_enable, GPIO.LOW)
def _send_byte(self, value, command):
"""Low-Level-Implementierung um ein Byte zu senden.
command=True: Ist ein Kommando und RS ist LOW.
command=False: Ist kein Kommando (=Text) und RS ist HIGH.
"""
#Wenn es ein Kommando ist, wird RS auf LOW gesetzt. Bei Text auf HIGH.
if command:
GPIO.output(self.lcd_rs, GPIO.LOW)
else:
GPIO.output(self.lcd_rs, GPIO.HIGH)
#Logik:
#Die Schleife zählt die Einträge im Datenbus der Reihe nach hoch.
#Dabei wird mittels Bitverschiebung (<<) immer ein höherer Bit gezählt,
#also 0001, 0010, 0100, 1000 usw.
#Mittels bitweisem UND (&) wird geprüft, ob im zu sendenden Wert (value)
#genau dieses Bit vorkommt. Wenn das Wahr ist, wird der Ausgang auf HIGH
#geschaltet.
for i, pin_number in enumerate(self.data_bus):
if value & (1 << i):
GPIO.output(pin_number, GPIO.HIGH)
#Wenn die Ausgänge fertig geschaltet sind muss man einmal kurz einen
#Enable-Puls senden, damit der Controller die Daten übernimmt.
self._send_enable_pulse()
def _set_data_bus_low(self):
"""Setzt alle Datenkanäle auf Low."""
for channel in self.data_bus:
GPIO.output(channel, GPIO.LOW)
GPIO.output(self.lcd_rs, GPIO.LOW)
GPIO.output(self.lcd_enable, GPIO.LOW)
def clear_lcd(self):
self.write_command(self.LCD_CLEAR_DISPLAY)
def generate_char(self, position, character_glyph):
self._send_command(self.LCD_CGADR | position)
for character_line in character_glyph:
self.write_character(character_line)
def return_home(self):
self.write_command(self.LCD_CURSOR_HOME)
def set_cursor(self, row, column):
self.write_command(self.LCD_DDADR | self.LCD_DD_ROWS[row] | column)
def write_command(self, value):
"""Schreibt ein Kommando ans LCD"""
self._send_command(value, True)
def write_character(self, value):
"""Schreibt genau einen Buchstaben ans LCD"""
self._send_command(value, False)
def write(self, text):
"""Schreibt einen String ans LCD"""
self.clear_lcd()
self.return_home()
for i, character in enumerate(text.encode("ascii")):
self.write_character(character)
if i == self.columns - 1:
self.set_cursor(1, 0)
Danke