Guten morgen zusammen, Ich habe ein Problem mit einem LCD. Und zwar habe ich in uregelmässigen Abständen (1 Monate bis 11 Monate) das Problem das das LCD plötzlich nur noch Hyroglyphen anzeiget. Der uC selbst läuft aber ohne probleme in seiner Software weiter das erkenne ich an LEDs und ich kann noch "Blind" durch das Menu steuern welches eigentlich auf dem LCD angezeigt werden sollte. Ich weiss nicht woher das kommt und es Tritt sooo selten auf das ich es nicht nachvollziehen kann Wie schon geschrieben Zeitspanne ist so zwischen 1 bis 11 Monate. Meine Idee war jetzt das LCD Regelmässig neu zu initialisieren und den Inhalt der drauf stand wieder aufs LCD zu schreiben. Um festzustellen was mal auf dem Display stand würde ich gerne Jegliche Ausgabe die ich auf das LCD schreibe in meinen Speicher des uC speichern Das wäre bei meinem 4x20 Zeichen Display 80 Bytes. und dann hätte ich ein komplettes abbild des LCDs in meinem Speicher drin. Ich habe schon etwas dazu geschrieben aber das ist noch sehr unausgereift. und ich wollte erstmal eure Meinung anhören was ihr so dazu denkt. Schöne Grüße
statische ladungen ? die typischen LCDs sind da recht empfindlich ... ich beschreibe dazu gerne eine ungenutzte RAMzelle und lese diese zyklisch aus. stimmt der wert == ist es egal ist der wert != dann folgt ein LCD reset witzigerweise ist selbst das manchen LCDs egal .. dann hilft nur LCD über einen PIN aus/einschalten
Das Display wird wohl kurzzeitig gestoert werden, bspw. durch Spannungsschwankungen. Wie sieht deine Beschaltung aus? Kondensatoren ausreichend vorhanden, gut gewaehlt und gut platziert? Was passiert sonst noch auf deiner Schaltung? Schaltest du irgendwas groesseres ein/aus. Wo ist deine Schaltung platziert, ist in der nahen Umgebung etwas besonderes? Warum musst du das Display so umstaendlich neu laden? Weisst du nicht was drauf ist? Also dein uC schreibt doch auf das Display Werte. Warum das Display nicht resetten und die Werte eben einfach neu drauf schreiben? Ansonsten kannst eben so einen Pseudo-Double-Buffer implementieren, als ein 80 Byte Array. Wenn du Display-Interne Funktionen verwendest bietet es sich vielleicht an das Array immer nach einer dieser Funktionen durch Auslesen des Display-RAM vom Display direkt zu laden. Zur Sicherheit kannst du ueberpruefen ob der Inhalt Hyroglyphen enthaelt.
@Sebastian (Gast) >Abständen (1 Monate bis 11 Monate) das Problem das das LCD plötzlich nur >noch Hyroglyphen anzeiget. LCD Controller abgestürzt. >Ich weiss nicht woher das kommt und es Tritt sooo selten auf das ich es >nicht nachvollziehen kann Wie schon geschrieben Zeitspanne ist so >zwischen 1 bis 11 Monate. Sehr lange. >Meine Idee war jetzt das LCD Regelmässig neu zu initialisieren und den >Inhalt der drauf stand wieder aufs LCD zu schreiben. Jo. Hab ich auch schon gemacht. >Um festzustellen was mal auf dem Display stand würde ich gerne Jegliche >Ausgabe die ich auf das LCD schreibe in meinen Speicher des uC speichern Kann man machen, ist aber nur eine von vielen Möglichkeiten. >Das wäre bei meinem 4x20 Zeichen Display 80 Bytes. und dann hätte ich >ein komplettes abbild des LCDs in meinem Speicher drin. Jo. >Ich habe schon etwas dazu geschrieben aber das ist noch sehr >unausgereift. und ich wollte erstmal eure Meinung anhören was ihr so >dazu denkt. Je nach Programm hat man so oder so eine Funktion, welche einen vollständigen Update des LCDs macht. Die kann man dafür nutzen, dann braucht man nicht die 80 Byte zusätzlichen Speicher. Wenn man 1x pro Tag das LCD neu initialisiert und dann einen kompletten Update macht, passt das schon. Wenn man es richtig macht, kriegt das auch keiner mit. Bei der Variante mit den 80 Byte Extra Puffer im uC hat man ach das Problem, das man alle LCD-Zufriffe auf diesen Puffer ändern muss. Allerdings sind die dann deutlich schneller, was in eingen Fällen vorteilhaft sein kann. Bei meiner schaltung habe ich einmal pro Sekunde das LCD neu initialisiert ;-), weil ich das EMV-Problem nicht beheben konnte. Aber auch dort sieht man das im Normalbetrieb nicht, nur wenn der Absturz eingetreten ist.
Die herkömmlichen HD44780-Displays sind meist empfindlich gegen Störeinstrahlungen. Wie empfindlich, hängt oft vom Layout des Displays ab, ich habe schon miterlebt, daß eine spätere Revision eines Herstellers schlechter war als eine frühere. Zum Ausfall (vergessen der Initialisierung, softwaremäßig zurückzusetzen) können leitungsgebundene Störungen führen (Relaisspulen u.ä.), aber auch elektrostatische Entladungen in Displaynähe, oder ausreichend starke HF-Einstrahlung. Neben zyklischer Re-initialisierung kann auch eine letifähig beschichtete Schutzscheibe vor dem Display helfen.
Jo nur habe ich ein Problem: Für die erklärung reduzieren ich es mal auf eine Zeile: gehen wir von folgendem fiktiven szenario aus. Ich gebe auf meinem Display folgendes aus:
1 | char out[21]; |
2 | sprintf(out, "Menu1: TEST"); |
3 | set_cursor(0,1); |
4 | lcd_string( out ); |
5 | |
6 | char bufferuC[21]; |
7 | strcpy( &bufferuC[0], out); |
dadurch steht in meinem bufferuC das was im string out steht und das steht nun auch auf dem LCD Es kommt in der Software vor das ich dann meinen Cursor auf set_cursor(5,1); stelle und nun das "Menu1" auf "Menu2" als Faktisch ändere ich nur die 1 auf 2 Wie sage ich das meinem Buffer das sich nun an der stelle 5 etwas gehändert hat ? Wie füge ich die Beiden Strings so ein einander das sich nur das eine byte in dem String ändert ? Schöne Grüße
Sebastian schrieb: > Wie sage ich das meinem Buffer das sich nun an der stelle 5 etwas > gehändert hat ? Ich denke da liegt ein Missverständnis vor. Du hast in deinem Programm ein char LCDBuffer[4][20]; und dieses Char-Array IST ab sofort dein LCD! Alle Ausgaben landen ausnahmslos in diesem Buffer, egal wie sie zu STande kommen. Und ein anderer Mechanismus sorgt dann dafür, dass dieser Buffer regelmässig an das LCD upgedatet wird. Aber für dein Programm ist dieses char-Array die Ausgabefläche. D.h. du musst dein Programm derart umbauen, dass erst mal * es einen Mechanismus gibt, der laufend das LCD von diesem Buffer aus nachzieht. Zb mit einem Timer-Interrupt, in dem laufend 1, 2 Zeichen aus dem Buffer ans LCD übertragen werden, bis alles draussen ist und dann läuft alles wieder von vorne * alle Ausgaben deines Programmes ausnahmslos in diesem Buffer landen. Ja das bedeutet auch, dass du dir Ersatz für Funktionen wie lcd_clear oder set_cursor oder lcd_string machst, die diese Operation dann eben in diesem Buffer abbilden. Du programmierst dir Funktionen, so dass der Inhalt des Buffers für dein Programm sich wie ein LCD verhält. > > Wie füge ich die Beiden Strings so ein einander das sich nur das eine > byte in dem String ändert ? Gar nicht. Warum sollte man das machen wollen? Wenn du am LCD sen String "Menü 1" stehen haben willst, dann gibst du den Text "Menü 1" aus. Soll dort "Menü 2" stehen, dann wird eben der Text "Menü 2" ausgegeben. Soll dort "Schnurdibur" stehen, dann wird eben der Text "Schnurdibur" ausgegeben.
Ich habe auch einen Buffer, der automatisch ans LCD ruebergeschrieben wird. Und zwar im Timer Tick. Jede 10ms wird ein Zeichen aus dem Buffer in das Display geschrieben. Und meine Software Funktionalitaet muss daher nur den Buffer beschreiben. Falls man nun auch den Fall abdecken will, in dem der LCD Controller aussteigt, muss man nur alle Minuten oder so die komplette Initialisierungs Sequenz ans LCD wiederholen.
Achso Karl Heinz, Das hört sich sehr gut an. Nur muss ich dann das gesammte programm ja umschreiben. Da fehlt mir gerade ein wenig der Denkansatz zu der umwandlung von Setcurser auf das Array denn ich Rufe ja immer Set_curser auf und bestimme die Position des Cursers auf dem LCD. Diese information ist natürlich auch enorm Wichtig den Buffer. Denn der Text String der dann an die Position des Cursors auf dem LCD geschrieben werden soll. Soll dann natürlich in den Buffer geschrieben werden. Bei dieser Umwandlung hängts gerade gedanklich bei mir. ah. könntest du deinen Qullcode fuer die Umwandlung mal posten ?
Sebastian schrieb: > Das hört sich sehr gut an. Nur muss ich dann das gesammte programm ja > umschreiben. Tja. > Da fehlt mir gerade ein wenig der Denkansatz zu der umwandlung von > Setcurser auf das Array > denn ich Rufe ja immer Set_curser auf und bestimme die Position des > Cursers auf dem LCD. Na komm so schwer ist das nicht
1 | char LCDBuffer[4][20]; |
2 | uint8_t actLine; |
3 | uint8_t actColumn; |
4 | |
5 | |
6 | void set_cursor( uint8_t line, uint8_t column ) |
7 | {
|
8 | actLine = line; |
9 | actColumn = column; |
10 | }
|
11 | |
12 | void lcd_data( char c ) |
13 | {
|
14 | LCDBuffer[actLine][actColumn] = c; |
15 | actColumn++; |
16 | }
|
17 | |
18 | void lcd_string( const char* str ) |
19 | {
|
20 | while( *str ) |
21 | lcd_data( *str++ ); |
22 | }
|
23 | |
24 | void lcd_home() |
25 | {
|
26 | actLine = 0; |
27 | actColumn = 0; |
28 | }
|
29 | |
30 | void lcd_clrs() |
31 | {
|
32 | uint8_t i, j; |
33 | |
34 | for( i = 0; i < 4; i++ ) |
35 | {
|
36 | for( j = 0; j < 20; j++ ) |
37 | LCDBuffer[i][j] = ' '; |
38 | }
|
39 | |
40 | lcd_home(); |
41 | }
|
42 | |
43 | ....
|
Sicherheitshalber sollte noch ein wenig Absicherung da rein, so dass man nicht out of bounds ans Array zugreift. Hab ich mir jetzt mal gespart. EDit: Und ob das so schlau ist, die Funktionen 1:1 gleich zu nennen, wie die originalen LCD Funktionen ... nach ein wenig Sinnieren finde ich das keine so gute Idee mehr.
Man muss sich den fuer den Benutzer stehenden Cursor merken.
Oh mann stehe ich auf dem Schlauch. Ja natürlich Vielen Dank. Ich glaube ich sollte erstmal was die sonne geniessen ich habe ja eine ganze holz huette vorm kopp xD Vielen Vielen Dank
Nein ich habe an alle funktionen ein _buffer drangehangen also so siehts aus:
1 | void set_cursor_buffer( uint8_t line, uint8_t column ) |
2 | {
|
3 | actLine = line; |
4 | actColumn = column; |
5 | }
|
6 | |
7 | void lcd_data_buffer( char c ) |
8 | {
|
9 | LCDBuffer[actLine][actColumn] = c; |
10 | actColumn++; |
11 | }
|
12 | |
13 | void lcd_string_buffer( const char* str ) |
14 | {
|
15 | while( *str ) |
16 | lcd_data_buffer( *str++ ); |
17 | }
|
18 | |
19 | void lcd_home_buffer() |
20 | {
|
21 | actLine = 0; |
22 | actColumn = 0; |
23 | }
|
und halt die ganzen anderen Funktionen, die du sonst noch so vom LCD benutzt. Wenn du benutzerdefinierte Zeichen benutzt, dann musst du die zwischenspeichern, wenn du Display-Shift benutzt, dann musst du dir das merken, etc. etc. Eben: Du schreibst einen Ersatz für ein LCD, der sich aus Sicht deines Programms wie ein LCD verhält und sich alles merkt, damit er a) das LCD in genau diesen Zustand bringen kann b) und das zu jeder Zeit c) im laufenden Betrieb, denn schliesslich will der Benutzer ja auch was sehen :-) wobei c) durchaus auch 'in Raten passieren kann'. Wie weiter oben schon mal wer geschrieben hat, updatet er das LCD alle 1ms mit jeweils dem nächsten Zeichen aus dem Buffer. 1ms, das sind 1000 Update pro Sekunde, du hast 80 Zeichen, schaffst also in 1 Sekunde mehr als 10 komplette Refreshes des LCD. Das reicht dicke, weil sowieso kein Mensch schneller lesen kann.
@ Karl Heinz Buchegger (kbuchegg) (Moderator) >mal wer geschrieben hat, updatet er das LCD alle 1ms mit jeweils dem >nächsten Zeichen aus dem Buffer. 1ms, das sind 1000 Update pro Sekunde, 1000 Zeichen / s >du hast 80 Zeichen, schaffst also in 1 Sekunde mehr als 10 komplette >Refreshes des LCD. 12,5 ;-) > Das reicht dicke, weil sowieso kein Mensch schneller > lesen kann. Schon gar nicht auf einem einfachen LCD, welches selber recht träge ist.
jo genau daran begebe ich mich jetzt es funktioniert jetzt so das ich meinen LCDBuffer fülle. Nun kommt es gleich dazu das der Inhalt vom LCDBuffer an das LCD gesendet wird. Dafür müsste ich doch erstmal den inhalt von sagen wir mal Zeile 1 im Buffer zu einem String formatieren den ich dann mit lcd_string senden kann oder?
Hi >Dafür müsste ich doch erstmal den inhalt von sagen wir mal Zeile 1 im >Buffer zu einem String formatieren den ich dann mit lcd_string senden >kann oder? Wozu? Der String wird auch nur zeichenweise an das LCD gesendet. Also kannst du auch gleich die Zeichen einzeln aus dem Puffer senden. MfG Spess
Sebastian schrieb: > Dafür müsste ich doch erstmal den inhalt von sagen wir mal Zeile 1 im > Buffer zu einem String formatieren den ich dann mit lcd_string senden > kann oder? machs nicht so kompliziert
1 | uint8_t refreshLine; |
2 | uint8_t refreshColumn; |
3 | |
4 | ISR( ..... ) |
5 | {
|
6 | lcd_data( LCDBuffer[refreshLine][refreshColumn] ); |
7 | |
8 | refreshColumn++; |
9 | if( refreshColumn == 20 ) |
10 | {
|
11 | refreshColumn = 0; |
12 | refreshLine++; |
13 | if (refreshLine == 4 ) |
14 | refreshLine = 0; |
15 | |
16 | set_cursor( refreshLine, refreshColumn ); |
17 | }
|
18 | }
|
(hier sind natürlich die originalen LCD ROutinen gemeint. Denn hier muss ja wirklich ans LCD übertragen werden. Einzig bei den Wartezeiten nach einer LCD-Übertragung muss man ein wenig aufpassen. zb wird man nach lcd_data im Normalfall (wenn kein set_cursor hinten nach kommt), keine Wartezeit mehr benötigen, weil ja ohnehin sicher gestellt ist, dass das nächste Zeichen erst mit dem nächsten Interrupt (zb 1 ms später) kommt.
Ich bin der Meinung du brauchst keinen echten Zwischen-Buffer. Schließlich hast du ja kein Grafikdisplay, das flackert wenn du zu langsam das Display updatest. Und immer das ganze Display neu aus dem Buffer zu beschreiben finde ich persönlich für unnötig. Ebenso das ständige Updaten mittels eines Interrupts ist recht sinnfrei. Du hast deine Displayroutinen mit SetCursor, lcd_Data, ... Was spricht dagegen, in diese Routinen zusätzlich zur Ausgabe auf das Display das Zeichen in einen Buffer zu schreiben? (Diese Funktionen hast du ja hier schon bekommen). Also in der Art zwei Displays, eines ist das reale, das andere der Buffer, in beide wird gleichzeitig geschrieben. Falls das Display sich verabschiedet hat, dann kannst du es resetten und mit dem Buffer abgleichen.
Frank M. schrieb: > Ebenso das ständige Updaten mittels eines Interrupts ist recht sinnfrei. Das entkoppelt die ganze Geschichte. Wenn man in Hintergrund einen Puffer hat der immer wieder an das Display geschickt wird, dann können alle Funktionen ohne jede Verzögerung arbeiten. Verschiedene Programmteile können unabhängig voneinander ohne ausgebremst zu werden dröfmal+x pro Sekunde den Puffer beschreiben, die Änderungen kommen dann irgendwann mal auf dem Display an. So Funktionen mit Namen wie lcd_write_string() die direkt ins Display schreiben müssen nach jedem Zeichen ein delay() einwerfen oder in einer Schleife nachfragen ob das Display schon fertig ist. Wenn der Anwender in dieser Zeit z.B. einen Taster betätigt kann der Controller auf sowas garnicht reagieren.
Gibt es schon Rückmeldung zum Thema Hardware? Einen Kondensator hinzuzufügen kann einfacher sein, als das Programm umzuschreiben und zu testen.
Man sollte auch SW-Fehler nicht außer acht lassen (Race-Conditions). Z.B. Zugriffe auf andere Pins der LCD-Ports. Oder LCD-Ausgaben im Interrupt und Main.
>Falls das Display sich verabschiedet hat, dann kannst du es resetten und
mit dem Buffer abgleichen.
Und wie stellt man fest, ob sich das Display verabschiedet hat ? Das
Ready auswerten ? Vielleicht. Ich verwende das Ready allerding nie.
>Wenn der Anwender in dieser Zeit z.B. einen Taster betätigt kann der
Controller auf sowas garnicht reagieren.
Eine Taste ist nie so schnell wie das display. Zudem sollte man eine
Taste eh entprellen.
Frank M. schrieb: > Ich bin der Meinung du brauchst keinen echten Zwischen-Buffer. > Schließlich hast du ja kein Grafikdisplay, das flackert wenn du zu > langsam das Display updatest. Und immer das ganze Display neu aus dem > Buffer zu beschreiben finde ich persönlich für unnötig. Im Prinzip auch meine Meinung - man sollte IMHO immer nur machen, was auch nötig ist. Es gibt aber durchaus noch Möglichkeiten: 1. man führt eine Statusvariable, die Veränderungen des Buffers trackt. So lange der Buffer nicht verändert wird, braucht man das LCD auch nicht zu aktualisieren. 2. Wie 1. aber mit feinerer Granularität, bspw. für einzelne Zeilen eines Textdisplays. Ebenso würde ich den Refresh des Displays eher am Stück machen als in einem (langsamen) Timerinterrupt. Ein Schreiber erwähnte mal 10ms. Ein 4x20 Display braucht dann schon satte 800ms für den Refresh. Das sieht man, gerade wenn große Änderungen dabei sind. Ideal wäre ein Interrupt vom Display, wenn es das letzte Zeichen "gefressen" hat. Andererseits braucht ein HD44780 gerade mal ~40µs für einen Schreibzugriff auf das Display-RAM. XL
Axel Schwenke schrieb: > Ebenso würde ich den Refresh des Displays eher am Stück machen als in > einem (langsamen) Timerinterrupt. Nö. Der Trick an der Timerlösung ist ja gerade, daß alles Warten wegfällt. Der Timerinterupt schreibt nur ein Byte und kümmert sich garnicht um das Busy. Und das Main schreibt alle Ausgaben sauschnell in das SRAM. Die CPU hat also viel mehr Zeit für andere Tasks übrig.
Eine Hardware Lösung wärenatürlich Optimal. Aber Die üblichen Puffer Elkos sowie Kondensatoren befinden sich direkt an der Verbindung zum LCD so wie am Eingang der Versorgungspannung vom uC. Die Software ist jetzt übernacht auch soweit angepasst worden das jede funktion die Früher das LCD angesprochen hat nun meinen Buffer anspricht jetzt gucken ich nur noch nach einer angenehmen zeit in der das Display kontinuirlich beschrieben werden soll
Hallo zusammen, was meiner Meinung nach in der gesamten Diskussion nicht genügend beachtet wurde, ist die Frage wie stelle ich fest das sich das Display verabschiedet hat und neu initialsiert werden muss. Gruss Roman
Da habe ich leider Keine möglichkeit zu ich werde es in regelmässigen abständen "einfach" neu initialisieren. Muss mal schauen wie ich das am geschicktesten anstelle
Hallo zusammen, ich habe mich da noch mal schlau gemacht. Mit der Kombination aus RS und RW Pin kann, laut AVR LCD Tutorial , der Inhalt des LCD's gelesen werden und theoretisch mit dem Inhalt des Buffers verglichen werden. Nur so als Idee, eine Umsetzung ist sicherlich ein Herausforderung für unsere Profis. Gruss Roman
wenn der LCD µC komplett weg ist hilft auch eine neu-init manchmal nicht ... dann kann dein buffer noch so tolle zeichen enthalten da hilft dann nur ein HW reset Aus genau diesem grund hatte ich das wie oben geschrieben gemacht das LCD war extrem empfindlich und bei berühren war das LCD leer
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
Mit Google-Account einloggen
Noch kein Account? Hier anmelden.