Forum: Mikrocontroller und Digitale Elektronik LCD 4x20 hängt sich nach der Zeit auf!


von Koksi (Gast)


Angehängte Dateien:

Lesenswert?

Hallo!

Ich verwende  ein 4x20 Zeichen LCD mit HD44780-Controllerchip und 
4Bit-Datenübertragung. Angesteuert wird es über einen ATMega8. 
Prinzipiell funktioniert die komplette Schaltung und die Ansteuerung des 
Displays auch einwandfrei, alles wird zu Beginn richtig angezeigt (Text, 
Variablen, usw.).

Nach einiger Zeit werden aber am Display immer wieder mal komische 
Zeichen anstatt dem richtigen Text angezeigt und manchmal "stürzt" es 
dann auch ab (Es werden nur mehr volle Kästchen in der 1. und 3. Zeile 
angezeigt, wie wenn es noch nicht initialisiert ist).

Das Datenkabel zwischen ATMega8 und LCD ist ein normales Flachbandkabel. 
Ist es vielleicht hier auch empfehlenswert ein geschirmtes Rundkabel zu 
verwenden oder ist das mehr vernachlässigbar?

Im Anhang habe ich die essentiellen Programmteile der Ansteuerung des 
Displays hinzugefügt, oben die Include-Datei für das LCD und danach die 
einzelnen Unterprogramme in der main.c.

Ich hoffe Ihr könnt mir dabei helfen, was der Grund dafür sein kann.

Mfg Koksi

von Karl H. (kbuchegg)


Lesenswert?

Koksi schrieb:

> Das Datenkabel zwischen ATMega8 und LCD ist ein normales Flachbandkabel.

Wie lang?

> Ist es vielleicht hier auch empfehlenswert ein geschirmtes Rundkabel zu
> verwenden oder ist das mehr vernachlässigbar?

Meine Kabel sind so um die 20cm lang. Das von dir geschilderte Verhalten 
hab ich noch nie gesehen.

von Koksi (Gast)


Lesenswert?

Die Kabel sind so um die 30cm lang.

von Wolfgang K. (koksi)


Lesenswert?

Nur zur Info damit keine Verwirrung entsteht, ich hab mich jetzt im 
Mikrocontroller-Forum angemeldet ;-)

Interessant wäre für mich, ob die Ansteuerung des LCD's prinzipiell in 
Ordnung ist, oder ob irgendwo so etwas wie zeitliche Flaschenhälse 
entstehen können, die dann die Kommunikation mit dem LCD 
beeinträchtigen?

von Knut (Gast)


Lesenswert?

das hier scheint mit etwas seltsam:
1
PORT = 0b00000010;      // Interface auf 4-Bit setzen
2
PORT = 0b00000010;      // Interface auf 4-Bit setzen
3
PORT = 0b00000010;      // Interface auf 4-Bit setzen

so ausm Bauch raus würde ich sagen man muss dazwischen den anable 
toggeln oder?

30cm Kabellänge sollten noch ok sein.

Stürzt nur das LCD ab, oder auch der µC?

Ich hatte mal versehendlich den ADC-Prescaler auf 1 bei 3,6864MHz und 
der µC ist sporadisch nach n paar Stunden betrieb eingefrohren.



Gruß Knut

von Wolfgang K. (koksi)


Lesenswert?

Hab die Initialisierungsroutine von einem Beispielprogramm übernommen 
und wenn ich das richtig verstanden habe, geht es bei den 3 Befehlen 
hintereinander einfach nur darum, eine Art Verzögerung für das Display 
einzubauen, da es bei der 4Bit-Initialisierung länger braucht um die 
Befehle abzuarbeiten (wenn man das Busy-Flag nicht abfragt).

Es stürzt nur das LCD ab, der µC läuft weiter und hat nichts.
Das LCD verhält sich einmal früher, einmal wieder später, wie wenn es 
irgendwie resettet wird oder Ähnliches, da es danach am Display genauso 
aussieht, wie beim Einschalten der Spannung...

mfg Koksi

von Karl H. (kbuchegg)


Lesenswert?

Zeig doch mal den Rest des Programms.
Vielleicht ist es gar nicht das LCD, sondern du hast einen 
Programmfehler und in Wirklichkeit resettet der AVR.

Das könntest du testen, wenn du noch irgendwo eine LED anschliessen 
kannst.

Die LED schaltest du gleich am Anfang in main() ein und nach der 
kompletten Initialisierung vor dem sei wieder aus.
Und dann beobachtest du, ob die LED während des Programmlaufs kommt.

Edit: Ne, Quatsch. Du hast ja die Intialisierungsbalken am LCD. Das LCD 
wird definitiv resettet. Nur: Softwaremässig schaffst du das so nicht. 
Irgendwas in der Versorgungsspannung? Eventuell mal am LCD einen 10µF 
Elko an die Versorungsspannung hängen?
Wackelkontakt irgendwo?
Schlechte Lötstelle?

von Phil J. (sunflower_seed)


Lesenswert?

Wenn die Hardware stimmt und das Display erst nach einiger Zeit falsche 
Zeichen ausgibt, würde ich mal davon ausgehen, das du es irgendwo 
geschafft hast ne "Variable" überlaufen zu lassen.
Oder du eine Schleife nicht richtig beendest und oder dabei eine 
Variable nicht richtig zurückgesetzt wird.

Letztendlich sind das natürlich keine Variablen sondern irgendwelche 
Register-Overflows, wo dann müll bei raus kommt.

von Wolfgang K. (koksi)


Angehängte Dateien:

Lesenswert?

Hab mal jetzt das gesamte Programm angehängt. Die Programmlogik mit Ein- 
und Ausgängen funktioniert und ich steuer da ja auch was an, also der µC 
kanns vom Aufhängen oder Resetten schon mal nicht sein, weil sonst würde 
der Sollwert auch resettet werden, was es aber nicht tut.

Wackelkontakt und schlechte Lötstelle hab ich schon alles kontrolliert, 
das passt alles. Es passiert auch, wenn die ganze Schaltung im 
Versuchsaufbau ruhig am Tisch liegt.

Einen Kondi in der Nähe des LCD's hab ich zur Zeit nicht, die Nächsten 
liegen bei den Versorgungspins des µC und Ausgangsseitig des 7805 mit 
10uF, 1uF und 100nF parallel.

Kann es sein dass eine nebenbeilaufende Leitung in die Datenleitung so 
derart reinstört, dass sich das LCD verabschiedet? Es ist eine normale 
12V-Leitung, die ein nachgeschaltenes Leistungsrelay mit ein paar 100mA 
schaltet (dass beim Ausschalten die Spannungsspitze Schuld ist???).

von Karl H. (kbuchegg)


Lesenswert?

Wolfgang Kogler schrieb:

> Kann es sein dass eine nebenbeilaufende Leitung in die Datenleitung so
> derart reinstört, dass sich das LCD verabschiedet? Es ist eine normale
> 12V-Leitung, die ein nachgeschaltenes Leistungsrelay mit ein paar 100mA
> schaltet (dass beim Ausschalten die Spannungsspitze Schuld ist???).


Oha.
Relais ist immer ein heißer Kandidat.

von Karl H. (kbuchegg)


Lesenswert?

1
char      Thermopile_Temperatur_Soll_Temp[3], Thermopile_Temperatur_Ist_Temp[3];

3 sind ein wenig knapp.

Hier ist die Stelle an der der String besetzt wird.
1
  Thermopile_Temperatur_Ist = ((ADC1_Wert * 2000) / 1023) / 10;
2
  ltoa (Thermopile_Temperatur_Ist, Thermopile_Temperatur_Ist_Temp, 10);

setz als ADC1_Wert mal 1024 ein. Das ist der maximal mögliche Wert. 
Pjysikalisch wird der zwar nicht vorkommen können, trotzdem sollte man 
damit als Maximalwert rechnen. Bricht dir aus irgendeinem Grund die 
Referenzspannung am ADC ein, dann kommt der Wert nämlich vom ADC.

Tut man das, dann kommt 200 raus. 200 passt nicht mehr in ein char[3]

Du hast SRAM genug. Ob es jetzt brach liegt, oder ob du hier ein bischen 
großzügig bist und auch im Fehlerfall (Wert aus irgendeinem Grund zu 
hoch) die Arrays nicht überläufst, spielt für den µC keine Rolle.


In eigener Sache. Beim nächsten Projekt
Du solltest ein bischen mehr mit else-if arbeiten. Dein Stil ist 
ziemlich schwer zu lesen und auf Korrektheit zu prüfen. Man muss ständig 
komplette Zeilen vergleichen um sich zu überzeugen, dass Abfragen 
wirklich identisch sind.

das hier
1
void Ausgang_setzen (void)
2
{  
3
  if (PD0_PD1_Motor == 1)        PORTD |= (1 << PD0);
4
  if (PD0_PD1_Motor == 1)        PORTD |= (1 << PD1);
5
  if (PD2_PD3_PD4_Lampe == 1)      PORTD |= (1 << PD2);
6
  if (PD2_PD3_PD4_Lampe == 1)      PORTD |= (1 << PD3);
7
  if (PD2_PD3_PD4_Lampe == 1)      PORTD |= (1 << PD4);
8
  if (PD5_Lampe_Temperatur_OK == 1)  PORTD |= (1 << PD5);
9
  
10
  if (PD0_PD1_Motor == 0)        PORTD &= ~(1 << PD0);
11
  if (PD0_PD1_Motor == 0)        PORTD &= ~(1 << PD1);
12
  if (PD2_PD3_PD4_Lampe == 0)      PORTD &= ~(1 << PD2);
13
  if (PD2_PD3_PD4_Lampe == 0)      PORTD &= ~(1 << PD3);
14
  if (PD2_PD3_PD4_Lampe == 0)      PORTD &= ~(1 << PD4);
15
  if (PD5_Lampe_Temperatur_OK == 0)  PORTD &= ~(1 << PD5);
16
}

könnte zb auch so aussehen
1
void Ausgang_setzen (void)
2
{  
3
  if (PD0_PD1_Motor) {
4
    PORTD |= (1 << PD0);
5
    PORTD |= (1 << PD1);
6
  }
7
  else {
8
    PORTD &= ~(1 << PD0);
9
    PORTD &= ~(1 << PD1);
10
  }
11
12
  if (PD2_PD3_PD4_Lampe) {
13
    PORTD |= (1 << PD2);
14
    PORTD |= (1 << PD3);
15
    PORTD |= (1 << PD4);
16
  }
17
  else {
18
    PORTD &= ~(1 << PD2);
19
    PORTD &= ~(1 << PD3);
20
    PORTD &= ~(1 << PD4);
21
  }
22
23
  if (PD5_Lampe_Temperatur_OK == 1)
24
    PORTD |= (1 << PD5);
25
  else
26
    PORTD &= ~(1 << PD5);
27
}

noch ein bischen Makro-Magie drübergestreut und wir sind bei
1
#define MOTOR_PORT     PORTD
2
#define MOTOR_1        PD0
3
#define MOTOR_2        PD1
4
5
#define LAMPEN_PORT    PORTD
6
#define LAMPE_ROT      PD2
7
#define LAMPE_GELB     PD3
8
#define LAMPE_GRUEN    PD4
9
#define LAMPE_TEMP_OK  PD5
10
11
#define TURN_ON(port,bit)   ( (port) |= ( 1 << (bit) ) )
12
#define TURN_OFF(port,bit)  ( (port) &= ~( 1 << (bit) ) )
13
14
15
......
16
17
void Ausgang_setzen (void)
18
{  
19
  if (PD0_PD1_Motor) {
20
    TURN_ON( MOTOR_PORT, MOTOR_1 );
21
    TURN_ON( MOTOR_PORT, MOTOR_2 );
22
  }
23
  else {
24
    TURN_OFF( MOTOR_PORT, MOTOR_1 );
25
    TURN_OFF( MOTOR_PORT, MOTOR_2 );
26
  }
27
28
  if (PD2_PD3_PD4_Lampe) {
29
    TURN_ON( LAMPEN_PORT, LAMPE_ROT );
30
    TURN_ON( LAMPEN_PORT, LAMPE_GELB );
31
    TURN_ON( LAMPEN_PORT, LAMPE_GRUEN );
32
  }
33
  else {
34
    TURN_OFF( LAMPEN_PORT, LAMPE_ROT );
35
    TURN_OFF( LAMPEN_PORT, LAMPE_GELB );
36
    TURN_OFF( LAMPEN_PORT, LAMPE_GRUEN );
37
  }
38
39
  if (PD5_Lampe_Temperatur_OK == 1)
40
    TURN_ON( LAMPEN_PORT, LAMPE_TEMP_OK );
41
  else
42
    TURN_OFF( LAMPEN_PORT, LAMPE_TEMP_OK );
43
}

Das hat dann codemässig schon eine ganz andere Qualität.

    TURN_ON( LAMPEN_PORT, LAMPE_TEMP_OK );

erzählt dir in 2 Monaten beim Lesen des Codes einfach viel mehr als

    PORTD |= (1 << PD5);

denn an dieser Stelle sind PORTD bzw. PD5 im Grunde technisch bedingte 
Nebensächlichkeiten. An dieser Stelle ist die Bedeutung wichtig. Und die 
Bedeutung ist nun mal, dass die Lampe eingeschaltet bzw. ausgeschaltet 
wird, die anzeigt, dass die Temperatur im erlaubten Bereich ist.
    TURN_ON( LAMPEN_PORT, LAMPE_TEMP_OK );
drückt genau das aus. Hier steht mehr oder weniger im Klartext, dass die 
Lampe eingeschaltet wird, obwohl es vom Compiler genau gleich übersetzt 
wird, wie die Variante in der die Ports und Bits direkt dort stehen.

von Wolfgang K. (koksi)


Lesenswert?

@ Karl Heinz: Danke für die programmiertechnischen Hilfestellungen! 
Werde die char in Zukunft größer machen, ist mir dabei nie etwas 
aufgefallen, dürfte im Bezug auf das Glück gehabt haben derweil :)
Über das mit den Ausgängen beschalten hab ich mir nie etwas dabei 
gedacht, da ich das gleich am Anfang immer geschrieben hab und dann im 
Programm mit den einzelnen Variablen nur mehr gearbeitet habe. Kann 
verstehen dass es schwierig zu lesen ist für jemanden, der das Programm 
zum ersten Mal liest ;)

Wenn das Problem das Relay ist, wie kann ich dieses Problem dann 
ausmertzen? Geschirmte Leitung? Oder was anderes? Die Leitung selber ist 
ein paar cm neben der LCD-Datenleitung, ich kann die beiden aber nicht 
mehr umverlegen, da alles in einem geschlossenem Metallgehäuse eingebaut 
ist und der Platz zu klein ist.

Welche Tipps gibt es prinzipiell um die Datenübertragung störungsfreier 
in Zukunft zu gestalten?

mfg Koksi

von Karl H. (kbuchegg)


Lesenswert?

Wolfgang Kogler schrieb:
> @ Karl Heinz: Danke für die programmiertechnischen Hilfestellungen!

Es tut mir leid, dass ich dir beim eigentlichen Problem nicht weiter 
helfen kann. Ich hab keine Idee mehr, was es noch sein könnte. Am 
ehesten tippe ich noch auf Versorgungsspannung, Relais oder irgendsowas 
in die Richtung.

Gibt es einen Zusammenhang, zwischen Abstürzen und dem Schalten des 
Relais?

> mehr umverlegen, da alles in einem geschlossenem Metallgehäuse eingebaut
> ist und der Platz zu klein ist.

Kannst du das Relais probehalber einfach mal komplett abtrennen (Kabel 
ablöten). Wenns dann ein paar Tage störungsfrei funktioniert, ist das 
schon ein Hinweis, dass du auf der richtigen Spur sein könntest.

> Welche Tipps gibt es prinzipiell um die Datenübertragung störungsfreier
> in Zukunft zu gestalten?

Die Störungen an der Quelle unterdrücken. Das ist immer das besser, als 
wie wenn man hinten nach Klimmzüge machen muss.

von Wolfgang K. (koksi)


Lesenswert?

> Gibt es einen Zusammenhang, zwischen Abstürzen und dem Schalten des
> Relais?

Ich sage mal in ca. 50% der Fälle schaltet gerade das Relay, bei den 
anderen schaltet eigentlich gar nichts sonst.


>> mehr umverlegen, da alles in einem geschlossenem Metallgehäuse eingebaut
>> ist und der Platz zu klein ist.
>
> Kannst du das Relais probehalber einfach mal komplett abtrennen (Kabel
> ablöten). Wenns dann ein paar Tage störungsfrei funktioniert, ist das
> schon ein Hinweis, dass du auf der richtigen Spur sein könntest.

Kann man sagen, dass es generell etwas bringt, eine geschirmte Leitung 
für das LCD zu verwenden? Für diese eine Schaltung könnte ich wenigstens 
das noch ändern.


>> Welche Tipps gibt es prinzipiell um die Datenübertragung störungsfreier
>> in Zukunft zu gestalten?
>
> Die Störungen an der Quelle unterdrücken. Das ist immer das besser, als
> wie wenn man hinten nach Klimmzüge machen muss.

Wie kann ich solche Störungen noch unterdrücken?
Derweil geht der Ausgangspin des µC zu einem ULN2003A Darlington-Array 
(oder zu einer normalen Transistoranschaltung, je nachdem..) und dann zu 
den Relays mit je einer Freilaufdiode.

von Wolfgang K. (koksi)


Lesenswert?

Ich hab mal versuchsweise Alu-Folie rund um das Datenkabel gewickelt, um 
einen beidseitig offenen Schirm zu "simulieren". Die Störungen sind 
tatsächlich um 70% zurückgegangen. Ich schätze wenn der Schirm 
beidseitig auf Masse liegt werden die Störungen noch weniger.

Wie sieht normalerweise Eure LCD-Ansteuerung aus? Irgendwelche 
Besonderheiten, die mir auch helfen könnten?

von Lothar M. (Firma: Titel) (lkmiller) (Moderator) Benutzerseite


Lesenswert?

Wolfgang Kogler schrieb:
> Alu-Folie rund um das Datenkabel gewickelt ...
> Die Störungen sind tatsächlich um 70% zurückgegangen.
Du hast irgendeinen feudalen Bock im Aufbau...

> Wie sieht normalerweise Eure LCD-Ansteuerung aus?
Normal, eben...  Aber wie sieht deine aus?
Zeig doch mal den dazu passenden Schaltplan.
Und mach ein paar (brauchbare) Fotos von deinem Aufbau...

> Irgendwelche Besonderheiten, die mir auch helfen könnten?
Nichts, was nicht im Datenblatt stünde.

von Wolfgang K. (koksi)


Angehängte Dateien:

Lesenswert?

Hier ist der Schaltplan von dem Aufbau auf der Platine.
Die Schaltung selber ist in einem Metallgehäuse eingebaut.
K5 und K6 sind die beiden Relais, welche das Leistungsrelay schalten.
Die Motorleitungen, welche vom Leistungsrelay weggehen, sind alle 
ausserhalb des Metallgehäuses, d.h. keine Motorleitung in der Nähe 
(wegen Störung).

von Wolfgang K. (koksi)


Lesenswert?

Könnt ihr mir was zu meiner Schaltung sagen? Ist sie korrekt und passt 
alles oder gibt es Punkte zur Verbesserung (besonders beim LCD)?

mfg
Koksi

von Jürgen W. (juergenw)


Lesenswert?

Hallo,
bei mir hat schon folgendes geholfen:
- Versorgunsspannung VCC des Display's über einen 330 Ohm Widerstand
ansteuern.
- Der Metallrahmen des Display's darf keine Verbindung zum Metallgehäuse 
haben.

von Wolfgang K. (koksi)


Lesenswert?

> - Versorgunsspannung VCC des Display's über einen 330 Ohm Widerstand
> ansteuern.
> - Der Metallrahmen des Display's darf keine Verbindung zum Metallgehäuse
> haben.

Aha, das ist ja interessant, muss ich mir merken. Kannst du mir auch 
sagen warum das so ist, zwecks Verständnis... ;)

von Jürgen W. (juergenw)


Lesenswert?

> Aha, das ist ja interessant, muss ich mir merken. Kannst du mir auch
> sagen warum das so ist, zwecks Verständnis

Bei mir wurden Leistungsschütze im gleichen Schaltschrank geschaltet. 
Und da hatte ich auch das Problem, dass irgendwann der Displaytext 
durcheinander kam. Der ATMega machte mir kein Problem - aber der 
Displaycontroller. Besser wurde es, als der Metallrahmen des Display's 
nicht mehr leitend mit dem Schaltschrank verbunden war. Da der 
Schaltschrank an PE liegt ist eine Masseschleife entstanden die mir dann 
wohl die Probleme gemacht hat.

Eine Erklärung warum die Störungen mit einem 330 Ohm-Widerstand in VCC 
des Display's zu 100% beseitigt werden konnten, habe ich nicht. 
Zusätzliche Abblockkondensatoren haben bei mir nichts bewirkt.

von Wolfgang K. (koksi)


Lesenswert?

Danke Jürgen für deine ausführlichen Schilderungen deiner Erkenntnisse, 
werde diese sicherlich in den nächsten Schaltungsentwurf einfliessen 
lassen und dank auch an Karl Heinz, der mir einige neue 
Programmiertechniken geschildert hat. Auf dieses Forum ist halt 
Verlass... ;-)
Falls jemand noch weitere Erkenntnisse bezügliches dieses Thema hat, 
würde ich mich noch gerne freuen.

mfg Koksi

von Jürgen W. (juergenw)


Lesenswert?

@ Wolfgang:
Kannst Du nicht mal testweise einen Widerstand in die VCC-Leitung des 
Display's hängen um zu schauen, ob sich etwas ändert? Kann natürlich 
sein, dass Du den Widerstand etwas kleiner wählen musst, da wohl das 
4x20 Zeichen Display etwas mehr Strom benötigt als bei mir das 2x16 
Zeichen Display. Mich würde nämlich sehr interessieren, ob dies auch bei 
Dir hilft.
Gruß
Jürgen

von Wolfgang K. (koksi)


Lesenswert?

Ja werde es in der nächsten Zeit mal testweise probieren wenn ich Zeit 
habe.
Bin auch schon gespannt ob das hilft.

mfg

von R. F. (rfr)


Lesenswert?

30 cm Kabellänge sind sehr viel. Kapp das mal auch <10 cm.
Gruss
Robert

von Reinhard S. (schopfi)


Lesenswert?

Die Symthomatik hatte ich auch, habs auch lange nicht hinbekommen.
Nun betreibe ich das programm mit einem kleinen schönheitsfehler aber 
dafür habe ich mit dem display keine probleme mehr.
Ich schalte einfach im programm das display kurz ab, schalte das relais 
und schalte es danach einfach wieder ein.
ist halt für etwar 2 sekunden keine displayanzeige aber ich kann damit 
leben :-)

lg

von Pufferer (Gast)


Lesenswert?

Hatte mal ein ähnliches Problem. Ein Elko direkt an der 
Spannungsversorgung am Display hat dann Abhilfe geschaffen.

von Wolfgang K. (koksi)


Lesenswert?

Das ist ja interessant, anscheinend haben doch mehr Personen dieses 
Problem auf irgendeine Weise...

Zusammengefasst würde das dann so aussehen:

Wenn das LCD aus heiterem Himmel komische Zeichen anzeigt und/oder 
komplett abstürzt, der µC aber weiterläuft ohne Fehler, können einer 
oder mehrere Punkte von der folgenden Liste eventuell weiterhelfen:

-) Externe Störungen von Motor, Relais, usw. beseitigen
-) Kondensator in der Nähe des LCD
-) Widerstand in die Versorgungsleitung
-) Metallrahmen des Displays isoliert aufbauen
-) Kabellänge am Besten unter 10cm

von Tubie (Gast)


Lesenswert?

Hatte mal was ähnliches,

ganz wilde Zeichen sehr schnell abwechselnd. Ich hatte damals 
wahrscheinlich einen Softwarefehler in 4 Bit Modus. Und zwar wurde da 
das High und Low nibble vertauscht. Entweder ein Programmfehler oder ein 
Timing war zu kurz, sodass das Display ein Nibble nicht mitbekam. Der 
Fehler verschwand dann nach einigen Stunden aber wieder und tauchte 
genauso wieder auf.


Gruß,
Tubie

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.