Hi ich möchte auf einem LCD-Display alle 10ms sieben Messwerte ausgeben lassen. Jeder Messwert hat die Länge von 5 Zeichen. Nun hab ich aber das Problem, daß mein Display für anstatt 1s für 700 Messwerte plötzlich ca. 10s braucht. Ich weiß, daß liegt an den vielen Pausen,die das Display sich gönnt. Nun meine Frage: kann man diese ganzen Pausen auch irgendwie anders lösen. Ohne das mein µC in Warteposition steht - der hat nämlich eigentlich noch anderes zu tun. Zum Beispiel diese Messwerte über einen UART rauszupusten. Ich bin für alle Lösungen offen! Danke
Hi >ich möchte auf einem LCD-Display alle 10ms sieben Messwerte ausgeben >lassen. Und wer soll das lesen??? MfG Spess
Hallo, ich erlaube mir mal die Fragem wer ein 100Hz Geflimmer von Meßwerten auf einem LCD lesen können soll? Wenn sich die Werte so oft ändern, gibt es unlesbares Geflacker und wenn sich sich nicht so oft ändern, gibt es keinen Grund, sie so oft anzeigen zu wollen. Gruß aus Berlin Michael
> alle 10ms ... Messwerte ausgeben
Kann das Display seine Kristalle überhaupt so schnell umschalten? :-o
eigentlich lese ich sogar 800 messwerte/s, aber das ist egal. Ich habs eben mal ausgerechnet: mein µC befindet sich für einmal 7 Messwerte schreiben 89,124ms in der Warteschleife. Vielleicht kann man den Schreibtakt auf 1/s herabsetzen, aber dennoch is er dann ca. 90ms mit wärmeproduzieren beschäftigt... Das muß doch besser gehen!
Hi >Ich habs eben mal ausgerechnet: mein µC befindet sich für einmal 7 >Messwerte schreiben 89,124s in der Warteschleife. In welcher Warteschleife?? MfG Spess
Die Frage hab ich mir auch schon gestellt. Das LCD braucht nach jeder Datenübertragung eine Pause um die Daten zu verarbeiten. Im Tutorial sind dazu Warteschleifen programmiert, wo der MC einfach sinnlos vor sich hin Zählt. Zum verdeutlichen der aktuellen Situation hier mal der Warteschleifen-Auszug aus meiner 8bit-Routine: (Sollte eigendlich das gleiche wie im Tutorial sein)
1 | ;********************************************************************** |
2 | ; |
3 | ; Pause nach jeder Übertragung |
4 | delay50us: ; 50us Pause |
5 | push temp1 |
6 | ldi temp1, ( XTAL * 50 / 4 ) / 1000000 |
7 | delay50us_: |
8 | nop |
9 | dec temp1 |
10 | brne delay50us_ |
11 | pop temp1 |
12 | ret ; wieder zurück |
13 | |
14 | ; Längere Pause für manche Befehle |
15 | delay5ms: ; 5ms Pause |
16 | push temp1 |
17 | push temp2 |
18 | ldi temp1, ( XTAL * 5 / 607 ) / 1000 |
19 | WGLOOP0: ldi temp2, $C9 |
20 | WGLOOP1: dec temp2 |
21 | brne WGLOOP1 |
22 | dec temp1 |
23 | brne WGLOOP0 |
24 | pop temp2 |
25 | pop temp1 |
26 | ret ; wieder zurück |
27 | |
28 | |
29 | ;********************************************************************** |
Kann man das irgendwie per Interupt regeln? Die Rechenzeit muss doch irgendwie sinnvoll zu nutzen sein... Gruss Stefan
Hi >Das LCD braucht nach jeder Datenübertragung eine Pause um die Daten zu >verarbeiten. Welches? MfG Spess
Hallo, es wurde zwar kein Display-Typ genannt, aber bei allen mir bekannten Display-Controllern kann man dann doch einfach vor der nächsten Ausgabe das Busy-Flag des Display abfragen. Man kann das natürlich auch in einen Timer-Interrupt legen und z.B. alle 5ms o.ä. ein Zeichen aus aus einem Displaybuffer ausgeben. Wenn man die Zeit passen wählt, muß man garnicht warten, höchstens bei Befehlen mit langer interner Laufzeit (Clear o.ä.). Gruß aus Berlin Michael
Ich arbeite noch nicht solange mit µC. Das ist das erste mal, daß ich
delays doof finde. Und anstatt hier doof rumzumaulen
>Welcher halbwegs intelligente Mensch benutzt DELAYS?
würde ich mich freuen, wenn ein solcher Kommentar mit einem Tipp
versehen ist.
Blöd rumkacken kann jeder...
Hallo, dann beantworte doch wenigstens die Frage wozu Du 700 Werte in einer Sekunde auf ein Display ausgeben willst! Gruß aus Berlin Michael
Na, na mal nicht so patzig. Die Botschaft lautet: Delays sind hier eine schlechte Lösung (wie meistens, aber das geht in viele Hirne nicht rein) So wie Du schreibst hast Du die Software selbst geschrieben und ab und an was abgeschaut. Es kamen schon sehr vernünftige Vorschläge wie Timerinterrupt und Busy-Flag. War da nichts dabei? Kann fast nicht sein. Also ran an den PC oder sonstwas Rechner und die Vorschläge in Programmzeilen gießen. Was hält Dich ab?
Nichts, ich war nur grad eine Rauchen. Wie das mit dem TimerInterrupt funktionieren soll, weiß ich noch nicht. Was das is, allerdings schon - auch schon häufig benutzt. Das mit der Busy-Flag is na klasse Idee - hätt ich selber drauf kommen können :) Problem daran is bloß, daß mein µC mit 3,3V arbeitet und ich für das 5V Display nen 74HCT244-Pegelwandler benutze, der leider nur in eine Richtung Wandeln kann: 3,3 -> 5,0 V Zu meinem Tonfall: Sorry, ich sitze schon 7 Std am PC... Kommt nicht wieder vor! Gruß
Du kannst mit nem Spannungsteiler ganz einfach aus den 5V 3,3V machen. Sind nur 2 Widerstände.
Mit dem Timerinterrupt ist doch ganz einfach. Im Hauptprogramm oder sonst wo bastelst Du Dir einen Ausgabestring zurecht, auf einem Array. Im Timerinterrupt gibst Du Byte für Byte an die Anzeige raus. Etwas Softwarehandshake zwischen Interrupt-Routine und Stringerstellung ist nötig. - Stringlänge, Ausgabestelle in der Anzeige - Flag für String fertiggestellt -> ausgeben im Interrupt - Flag für String ausgegeben -> neuen erstellen im HP. PC-Pause ist immer gut. Mach ich auch gleich wieder.
Ja, stimmt. Die Idee kam mir auch grad. Aber ich habe ein neues Problem. Selbst wenn ich auf die Busy-Flag warte, warte ich doch auch. Das übrige Programm hängt dann auch und die Werte, die in dieser Zeit bekomme, kann ich dann auch nicht abarbeiten. Ich müßte, und das is jetzt nur gesponnen, ein paralleles abarbeiten von zwei getrennten strängen... einen zweiten processor sozusagen. Moment, kann ich mein eingangssignal (ein I²C) auch an zwei µCs einlesen? Dafür bräuchten sie dann aber eine synchronisierte SCL... auch doof! Tipps?
Zu den Interrupts: Du meinst, ich generiere ein Timer, der 1ms läuft. Dann greift er sich die volatile mit dem messwert und zwar nur das erste, halbe byte (4-Leitungs-Bus) überträgt es. danach den timer neu starten. dann das zweite, halbe byte. dann hat das hauptprogramm einen neuen Messwert errechnet, usw usw. meinst du das so?
spess53 schrieb:
> Welcher halbwegs intelligente Mensch benutzt DELAYS?
Ich z.B..
50µs Delay ist voll o.k., das machen 99% aller LCD-Routinen so und es
ist überhaupt kein Rechenzeitproblem.
Er will ja nur 7 Werte a 5 Zeichen ausgeben, das sind dann also 1,8ms.
10ms Updaterate ist allerdings Schwachsinn.
Man sollte schon auf Ergonomie Wert legen, d.h. maximal 2..5
Aktualisierungen pro Sekunde.
Bei 5 Aktualisierungen/s sind das also 1,8ms je 200ms, also riesige
wahnsinns 0,9% CPU-Last!
Da ist es einfach nur lächerlich, auf den Delays rumzuhacken.
Das macht jede CPU mit links und 40 Fieber.
Peter
Nimm FreeRTOS, lass den LCD-Task mit niedriger Priorität laufen, benutze Multitasking-freundliche Wartefunktionen für ms-Delays (vTaskDelay ). Je komplexer das Projekt, desto eher lohnt sich FreeRTOS.
>Selbst wenn ich auf die Busy-Flag warte, warte ich doch auch. Das übrige >Programm hängt dann auch und die Werte, die in dieser Zeit bekomme, .. Nix Warten - Busy abfragen geht anders: Das Anzeigenprogramm liegt in der Hauptprogrammschleife. - das Hauptprogramm kommt beim Anzeigenprogramm vorbei - das ANZ-Porg fragt das Busy-Flag ab - Anzeige ist noch busy -> zurück ins HP weiter Messen, rechnen Uart bedienen usw. - Anzeige ist ready -> ein Byte ausgeben -> zurück ins HP Schon hast Du 2 Prozesse quasi parallel laufend.
Dietmar schrieb:
> Nimm FreeRTOS, lass den LCD-Task mit niedriger Priorität laufen,
Dann kommst Du vom Regen in die Traufe.
Die 50µs Wartezeit wird warscheinlich schon ein Taskwechsel komplett
aufbrauchen.
Für solche kleinen Wartezeiten ist ein RTOS ungeeignet.
Peter
Und hier mal eine Interruptlösung: Beitrag "Formatierte Zahlenausgabe in C" Ich setze sie aber bisher nicht praktisch ein, war mehr ne Designstudie, obs geht. Ich nehme die standard 50µs warten 4-Bit LCD Ansteuerung. Und ein Scheduler in der Mainloop ruft sie alle 200ms auf. Peter
So, ich denke, ich habs: - ich habe eben das Display an seine zeitlichen Grenzen gebracht - das hat ganzschön was gebracht. - dann habe ich mir eben noch mal angeschaut, wie 3 Messwerte/s aussehen, und man sieht, daß 100 wirklich übertrieben waren. - außerdem werde ich jetzt einen Timer entwerfen, der alle 50ms abläuft und werde dann einen messwert auf das LCD bannen (50ms * 7 = 350ms, also 2,85 Aktuallsierungen / s) Das mus reichen! Danke für allen guten Ratschläge, ich bin wieder etwas schlauer!
> Die 50µs Wartezeit wird warscheinlich schon ein Taskwechsel komplett
aufbrauchen. Für solche kleinen Wartezeiten ist ein RTOS ungeeignet.
Er soll für die ms-Wartezeiten (5ms == 5000us), die bei bestimmten
Befehlen anfalle, z.B. beim Clear-Befehl, das Multitasking-freundliche
Delay nehmen. Der Task-Switching-Overhead spielt dabei keine
erwähnenswerte Rolle. Das sind einige Dutzend us.
Die us-Wartezeiten programmiert er natürlich wie bisher als
Busy-Waiting. Das wird durch das Multitasking entschärft: Der LCD-Task
blockiert die CPU unter FreeRTOS nur bis zum nächsten Taskwechsel - der
kommt z.B. in 1ms (oder wenn ein Interrupt einen höher prioritisierten
Task aufweckt).
Insgesamt nimmt der LCD-Task so kaum Rechenleistung der CPU in Anspruch
- ohne dass man grossartig nachdenken muss. Voraussetzung ist, dass das
Display es nicht übel nimmt, wenn us-Pausen plötzlich länger dauern.
Sollte bei 4bit so sein (ist bei meinem so - das blaue 16x2 von Pollin).
Notfalls müsste man um bestimmte us-Delays herum das Task-Switching
abstellen.
Ich verwende in meinem Programm so einen LCD-Task (und eine Mess-Task
und einen InputHandler-Task usw.) und halte das für eine sehr angenehme
Lösung. Die Tasks schicken sich über Queues Nachrichten zu - z.B. was
anzuzeigen ist - und sind stark von voneinander entkoppelt. So kann man
auch sehr komplexe Programme schreiben, ohne sich im Interrupt-Kleinkram
zu vertüddeln.
Also ich würde es so machen, leg dir einen puffer für dieser 5 Zeichen an. Starte einen Timer der alle 50ms eines der Zeichen auf das Display schreibt. Dann brauchst du keine Wartezeit und über das Display brauchst du dir auch keine Gedanken machen sooo lange braucht kein Befehl. Vorteil ist halt auch das du jederzeit und belibig oft/schnell auf diesen Buffer schreiben kanns von überall aus deinem Programm heraus. Kann man natürlich auch auf das ganze LCD ausweiten .
Ich nutze seit einiger Zeit einen "Bildschirmspeicher" im AVR, in dem jede Byteposition einer Ausgabeposition entspricht. Das Hauptprogramm darf da dann jederzeit neue Texte reinschreiben. Ein vom Timer-Interrupt über Flag synchronisierter Job der Mainloop schaufelt jede Millisekunde (neben anderen Aufgaben wie z.B. Drehgeberauswertung) ein Byte davon an das LCD und entwirrt dabei den Zeilenverschachtelungssalat. Der Bildschirmspeicher hat also durchgehende Adressen und kann auch mit Fließtext beschrieben werden. Achja, in einem 1ms-Takt werden beide Nibbles des Bytes geschrieben, eine Wartezeit zwischen beiden Nibbles ist nicht nötig. In einem anderen Projekt (Bedienteil zum Parametrieren von Feuerwerks-Zündgeräten) mit Tiny2313 und LCD 4x40 (wo der SRAM nicht für einen Bildschirmspeicher reicht), habe ich das "Hauptprogramm" (Tasten abfragen, UART bedienen) in die Wartepausen des LCDs verlegt. Ein Timer setzt alle 1ms ein Flag. Die Hauptschleife gibt in diesem Takt byteweise reihum eine Überschrift, 20 Parameter und einen kontextabhängigen Menütext aus, wobei der zu ändernde Parameter blinkend dargestellt wird. Statt Busywait oder Warteschleife werden hier die anderen Jobs des Programms ausgeführt, wie jedes 16. mal (alle 16 ms) Tasten entprellen, UART auf Empfang prüfen und Byte wegräumen, UART Senden, falls erforderlich und UDR leer ist. Der optimale Lösungsweg ist immer auch etwas von der zu lösenden Aufgabe abhängig, eine Superlösung, die immer und überall optimal ist, wird es nicht geben. ...
Danke für eure Antworten! Da sind einige gute Anregungen dabei. Im nächsen Projekt werd ich die Interupt-LCD-Ansteuerung mal ausprobieren. Eigendlich hätte ich da mit ein bisschen mehr Überlegung selbst drauf kommen können, auch auf das Busy-Flag... Nochmal Danke^^ Gruss Stefan
wo wir gerade schonmal bei interrupts und lcd sind : mir ist da vor einiger zeit (ca nem jahr oder so) eine idee gekommen. wenn man im timerinterrupt die 4-6 userdefinierbaren zeichen mit einem teil aus einem frame-buffer füllt, diese 4-6 zeichen auf einem display darstellt, im nächsten interrupt dann wieder 4-6 zeichen füllen und auf dem display ausgibt (also 4-6 zeichen weiter) und so weiter ... damit müssten sich doch auf einem text-display schon fast grafiken darstellen lassen können oder ? abgesehen von den zwischenräumen zwischen den zeichen und dadurch das immer nur teile der grafiken angezeigt werden dürfte die darstellung auch nicht allzu rosig aussehen, aber denkbar wäre es oder ? hat jemand sowas schonmal ausprobiert ?
Hi, ich auch wenn ich ein bißchen die euphorie nehme, aber ich habe heute versucht, das troggeln der e-Leitung per Busy-Flag zu lösen und ich habs nich geschafft, die einmal 10us und die 20us zu ersetzen - aber vielleicht war ich auch einfach nur zu blöd... auch die interruptroutine mußte deswegen bei mir je zeichen 60us warten... doofe sache. Falls jemand die Zeiten beim KS0066U lösen kann, bitte ich um quelltext :) Gruß und danke dennoch für alle klugen köpfe!
TheMason schrieb: > wo wir gerade schonmal bei interrupts und lcd sind : > > mir ist da vor einiger zeit (ca nem jahr oder so) eine idee gekommen. > wenn man im timerinterrupt die 4-6 userdefinierbaren zeichen mit einem > teil aus einem frame-buffer füllt, diese 4-6 zeichen auf einem display > darstellt, im nächsten interrupt dann wieder 4-6 zeichen füllen und auf > dem display ausgibt (also 4-6 zeichen weiter) und so weiter ... damit > müssten sich doch auf einem text-display schon fast grafiken darstellen > lassen können oder ? abgesehen von den zwischenräumen zwischen den > zeichen und dadurch das immer nur teile der grafiken angezeigt werden > dürfte die darstellung auch nicht allzu rosig aussehen, aber denkbar > wäre es oder ? hat jemand sowas schonmal ausprobiert ? Wenn ich mich recht entsinne, wirken sich geänderte Zeichen auch auf den bereits dargestellten Text aus. Es sind also nie mehr als acht verschiedene, zusätzliche Zeichen vorhanden. Das Oszi auf dem Text-LCD (Siehe youtube) nutzt dieses "Feature", die Wellenform wird dabei nur über die anpassbaren Zeichen verändert, die aneinandergereiht den vollen "Bildschirm" von umwerfenden 8x40 Pixeln darstellen ;) Bezieht sich jetzt alles auf HD44780-Displays.
>wirken sich geänderte Zeichen auch auf den >bereits dargestellten Text aus. das ist mir bewusst ;-) deswegen dachte ich auch daran (ok ich hatte es nicht dabei geschrieben) die nicht in dem aktiven "segment" darzustellenden zeichen einfach durch spaces ersetzen. das heißt zwar das man bei allen 4 partiellen-grafik-zeichen die dargestellt werden immer das komplette display leer schreiben muß und das dürfte sich auf die helligkeit bzw darstellung eben auswirken ... aber denkbar wäre es doch oder ? ich pinsel das mal schematisch für ein 8x2 display auf 1. "1111 " " " 2. " 2222" " " 3. " " "3333 " 4. " " " 4444" die zahlen 1-4 beziehen sich auf die zeichen im cg-ram die immer in vierer-gruppen aus dem frame-buffer kopiert werden. ok. der nachteil an der lösung wäre das die helligkeit der einzelnen pixel auf 1/4 schrumpft da so oft umgeschaltet wird, aber das müsste man einfach mal austesten ...
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.