Forum: Mikrocontroller und Digitale Elektronik HD47780-Displayproblem an Raspi


von Displayproblem (Gast)


Angehängte Dateien:

Lesenswert?

Grüß Gott an alle,

ich habe hier aus einem Tutorial einen Python-Schnipsel für meine Zwecke 
angepasst, der ein hd47780 (oder kompatibles) Display an einem Raspberry 
ansteuert  (nicht i2c, sondern der "normale" 4-Bit-Modus).
Der Code macht auch genau das, was er soll - zumindest mit einem 2x8, 
einem 2x16 und einem 4x20-Zeichen-Display.
Jetzt habe ich hier ein Display mit 2x40 Zeichen. Und hier habe ich das 
Problem, daß bei der ersten Zeile der Inhalt um eins nach links 
verschoben erscheint - der erste Buchstabe fehlt, der letzte wird mit 
"leer" aufgefüllt (siehe Bild).
Was ich schon versucht habe: Die Werte von LCD_LINE_1 und -2 zu ändern. 
Bei dem Wert für die zweite Zeile funktioniert das auch, ich kann damit 
den Text zeichenweise nach links oder rechts schieben. Nur die erste 
Zeile bleibt unverändert.
Ich habe auch schon versucht, alle 80 Zeichen in nur einer Zeile 
anzugeben. Auch das funktioniert und auch hier ist die erste Zeile um 
ein Zeichen versetzt.
Die Frage ist - wie bekomme ich das hin, daß die erste Zeile auch 
korrekt angezeigt wird? Ein " " vor den String zu setzen geht zwar, aber 
dann passen nur 39 Zeichen in die erste Zeile, und da geht's um das 
Prinzip. :)

Hier der auf das 2x40-Zeichen-Display angepasste Code aus dem erwähnten 
Tutorial:
1
!/usr/bin/python
2
3
import RPi.GPIO as GPIO
4
import time, sys
5
6
# Define GPIO to LCD mapping
7
LCD_RS = 7
8
LCD_E  = 8
9
LCD_D4 = 25
10
LCD_D5 = 24
11
LCD_D6 = 23
12
LCD_D7 = 18
13
LED_ON = 15
14
15
# Define some device constants
16
LCD_WIDTH = 40    # Maximum characters per line
17
LCD_CHR = True
18
LCD_CMD = False
19
20
#Diesen Wert ändern hat keinerlei Auswirkungen:
21
LCD_LINE_1 = 0x80 # LCD RAM address for the 1st line
22
23
# Über diesen Wert kann ich zeichenweise den Text der zweiten Zeile 
24
# verschieben, bei xa2 startet der Text genau in der ersten Zelle der 
25
# zweiten Zeile.
26
LCD_LINE_2 = 0xa2 # LCD RAM address for the 2nd line 
27
28
# Timing constants
29
E_PULSE = 0.00005
30
E_DELAY = 0.00005
31
32
def main():
33
  GPIO.setmode(GPIO.BCM)       # Use BCM GPIO numbers
34
  GPIO.setup(LCD_E, GPIO.OUT)  # E
35
  GPIO.setup(LCD_RS, GPIO.OUT) # RS
36
  GPIO.setup(LCD_D4, GPIO.OUT) # DB4
37
  GPIO.setup(LCD_D5, GPIO.OUT) # DB5
38
  GPIO.setup(LCD_D6, GPIO.OUT) # DB6
39
  GPIO.setup(LCD_D7, GPIO.OUT) # DB7
40
#  GPIO.setup(LED_ON, GPIO.OUT) # Backlight enable
41
42
  # Initialise display
43
  lcd_init()
44
45
  # Toggle backlight on-off-on
46
 # GPIO.output(LED_ON, False)
47
  zeile1=sys.argv[1]
48
  zeile2=sys.argv[2]
49
50
 # Send some centred test
51
  lcd_byte(LCD_LINE_1, LCD_CMD)
52
  lcd_string(zeile1,1)
53
  lcd_byte(LCD_LINE_2, LCD_CMD)
54
  lcd_string(zeile2,1)
55
56
  time.sleep(0.5) # delay
57
58
def lcd_init():
59
  # Initialise display
60
  lcd_byte(0x33,LCD_CMD)
61
  lcd_byte(0x32,LCD_CMD)
62
  lcd_byte(0x28,LCD_CMD)
63
  lcd_byte(0x0C,LCD_CMD)
64
  lcd_byte(0x06,LCD_CMD)
65
  lcd_byte(0x01,LCD_CMD)
66
67
def lcd_string(message,style):
68
  # Send string to display
69
  # style=1 Left justified
70
  # style=2 Centred
71
  # style=3 Right justified
72
if style==1:
73
    message = message.ljust(LCD_WIDTH," ")
74
  elif style==2:
75
    message = message.center(LCD_WIDTH," ")
76
  elif style==3:
77
    message = message.rjust(LCD_WIDTH," ")
78
79
  for i in range(LCD_WIDTH):
80
    lcd_byte(ord(message[i]),LCD_CHR)
81
82
83
def lcd_byte(bits, mode):
84
  # Send byte to data pins
85
  # bits = data
86
  # mode = True  for character
87
  #        False for command
88
89
  GPIO.output(LCD_RS, mode) # RS
90
# High bits
91
  GPIO.output(LCD_D4, False)
92
  GPIO.output(LCD_D5, False)
93
  GPIO.output(LCD_D6, False)
94
  GPIO.output(LCD_D7, False)
95
  if bits&0x10==0x10:
96
    GPIO.output(LCD_D4, True)
97
  if bits&0x20==0x20:
98
    GPIO.output(LCD_D5, True)
99
  if bits&0x40==0x40:
100
    GPIO.output(LCD_D6, True)
101
  if bits&0x80==0x80:
102
    GPIO.output(LCD_D7, True)
103
104
  # Toggle 'Enable' pin
105
  time.sleep(E_DELAY)
106
  GPIO.output(LCD_E, True)
107
  time.sleep(E_PULSE)
108
  GPIO.output(LCD_E, False)
109
  time.sleep(E_DELAY)
110
  # Low bits
111
  GPIO.output(LCD_D4, False)
112
  GPIO.output(LCD_D5, False)
113
  GPIO.output(LCD_D6, False)
114
  GPIO.output(LCD_D7, False)
115
  if bits&0x01==0x01:
116
    GPIO.output(LCD_D4, True)
117
  if bits&0x02==0x02:
118
    GPIO.output(LCD_D5, True)
119
  if bits&0x04==0x04:
120
    GPIO.output(LCD_D6, True)
121
  if bits&0x08==0x08:
122
    GPIO.output(LCD_D7, True)
123
124
  # Toggle 'Enable' pin
125
  time.sleep(E_DELAY)
126
  GPIO.output(LCD_E, True)
127
  time.sleep(E_PULSE)
128
  GPIO.output(LCD_E, False)
129
  time.sleep(E_DELAY)
130
131
if __name__ == '__main__':
132
  main()

von Stefan F. (Gast)


Lesenswert?

Ich glaube, du musst nach dem Initialisieren des Displays ein bisschen 
warten. Ich warte nach jedem Daten-Byte (das wäre bei Dir das Ende von 
lcd_byte) 60µs und nach dem Kommando RETURN_HOME sogar 1600µs.

Das Kommando RETURN_HOME (0x02) vermisse ich in deiner Initialisierung 
ganz. Vielleicht ist es notwendig.


Was du mal probieren kannst:
Gebe mal zuerst etwas in Zeile 2 aus, danach in Zeile 1. Wenn sich der 
Fehler dann auf Zeile 2 verschiebt, hatte ich mit dem Timing ziemlich 
sicher Recht.

von Peter D. (peda)


Lesenswert?

Displayproblem schrieb:
> Die Frage ist - wie bekomme ich das hin, daß die erste Zeile auch
> korrekt angezeigt wird?

Im Datenblatt des LCD sind, besonders beim Init, Zeiten zwischen den 
Bytes angegeben, die man nicht unterschreiten sollte.
Man kann auch die Zeiten aus dem HD44780-Datenblatt nehmen, die meisten 
Text-LCD sind dazu kompatibel.

von Karl B. (gustav)


Lesenswert?

Hi,
die Initialisierungssequenz sieht bei mir so aus (2x16):
Vermisse die 3x 0x30


Jedesmal Pausen dazwischen senden.


0x30   Init
0x30   Init
0x30   Init
0x20   Vierbit
0x28   Vierbit, z w e i zeilig; kann angepasst werden(!)
ab hier Befehle im Vierbitmodus senden (zweimal Enable!)
0x08   Cursor aus, Blinken aus
0x01   Anzeigepuffer loeschen
0x06   Cursor nach rechts
0x10   Cursor nach rechts, kein Schieben
0x0C   Cursor aus, Blinken aus
0x01   Anzeigepuffer loeschen

Mal den Test machen mit den Positionierungsbefehl:

locate1:    ;Anfang Zeile 1
push  temp
ldi  temp, 0x80
rcall  comd2lcd
pop  temp
ret

Ist zwar ASM, aber gemeint ist, einen Befehl mit dem "Wert" 0x80 an das 
Display zu senden im Kommandomodus, nicht Textmodus. Wie das in der 
Syntax aussieht, weiß ich nicht, jedenfalls müssen die 0x80 rein für 
Anfang Zeile 1 plus Befehl zum Wechseln in den Befehlsmodus.
Wenn das dann nach der Initialisierung klappt, ist die Initsequenz 
irgendwo nicht ganz korrekt, oder, wie oben schon gesagt, die Pausen zu 
kurz.

Peter D. schrieb:
> Im Datenblatt des LCD sind, besonders beim Init, Zeiten zwischen den
> Bytes angegeben, die man nicht unterschreiten sollte.


ciao
gustav

: Bearbeitet durch User
von Displayproblem (Gast)


Lesenswert?

> Jedesmal Pausen dazwischen senden.

Das war der entscheidende Hinweis.
ein "time.sleep(0.1)" in der Initialisierung hat das Problem behoben. 
Danke an alle.

Bitte melde dich an um einen Beitrag zu schreiben. Anmeldung ist kostenlos und dauert nur eine Minute.
Bestehender Account
Schon ein Account bei Google/GoogleMail? Keine Anmeldung erforderlich!
Mit Google-Account einloggen
Noch kein Account? Hier anmelden.