Hallo! Ich habe folgendes Problem: Ich möchte sieben 7-Segment-Anzeigen multiplexen und jede Minute eine A/D-Wandlung vornehmen. Mir ist klar, dass die Wandlung einige ms in Anspruch nimmt und nehme es in Kauf, dass jede Minute während der Wandlung die Anzeige kurz flackert. Allerdings flackert die Anzeige ab der ersten Wandlung ständig. Bis 60s läuft alles normal und sobald die erste Wandlung vollzogen wird flackert die Anzeige ständig bis in alle Ewigkeit. Der ausgelesene Wert wird allerdings auch dann nur alle 60s aktualisiert, woraus ich schließe , dass die Wandlung auch nur alle 60s vollzogen wird (oder eben doch nicht?). Was ich mir auch gut vorstellen kann ist, dass der ADC mit der ersten Wandlung aktiv wird und ständig wandelt, allerdings der aktuelle Wert dann nur alle 60s herausgegeben wird. Kann mir wer helfen? MfG Tom
Hallo, die A/D-Wandlung wird in der 59. Sekunde nicht nur einmal berechet, sondern so oft wie die Hauptschleife in der 59.Sekunde durchlaufen wird. Ich würde im Interrupt nicht den Sekundenzähler inkrementieren, sondern nur ein Flag für das Hauptprogramm setzen wenn die Sekundenaktionen durchzuführen sind. (Das Flag im Hauptprogramm zurücksetzen nicht vergessen). Die nachfolgende Umrechnung ist floating-Point und braucht entsprechend Zeit. Ich würde die nicht ständig rechnen sondern nur dann wenn sich auch tatsächlich was geändert hat. (In die IF-Abfrage für die 59. Sekunde hineinziehen). Vermutlich ist alles gut solange der ADC-Wert noch = null ist, da dann die Multiplikationsroutine optimieren kann. Falls das nichts hilft wird es schwierig: reichen die String-Längen aus oder sind die doch um 1 Zeichen zu klein? (Ich kenne mich in BASCOM nicht aus, in "C" müßte man die Stringdefinition immer 1 länger machen als den String damit das Terminierungszeichen 0x00 noch hineinpaßt).
Ich dachte jetzt immer, man würde mit einem Timer multiplexen und nicht freilaufend in der Hauptschleife. :D Im Interrupt hat's nämlich den Vorteil, daß das Multiplexen vorrangig ausgeführt wird, und höchstens von anderen Interrupts gestört werden kann. Die Hauptschleife wird dann immer abgearbeitet, wenn Zeit vorhanden ist und nicht gerade gemultiplext wird. Außerdem mach' mal den Aufruf der Int0 ISR raus, wenn Du die nicht verwendest: --> Enable Timer0. Die Umrechnung kann man locker mit ausreichender Genauigkeit über Integers, bzw. Long machen, das geht viel schneller. Man muss halt die Konstante vorher auf die notwendige Genauigkeit erweitern, also Const Adc_faktor = 48828 Der ADC Wandler hat sowieso nur 10 Bit Genauigkeit, also 4 Stellen, da machen Fließkommaoperationen mit 10 Stellen hinter dem Komma nur begrenzt, bis keinen Sinn. Eine Wandlung kann man auch noch anders als über GetADC erreichen. GetADC blockiert die Programmausführung bis die Wandlung fertig ist. Es ist möglich die ADC Wandlung in Sekunde 59 anzustoßen und in Sekunde 0 den Wert abzuholen, nach 1 Sekunde steht das Ergebnis längst bereit, das geht im Hintergrund und man muss auf gar nix warten. Allerdings nicht möglich mit der GetADC Funktion, ist aber nicht schwer das zu machen.
Hallo! > Die nachfolgende Umrechnung ist floating-Point und braucht entsprechend > Zeit. Ich würde die nicht ständig rechnen sondern nur dann wenn sich > auch tatsächlich was geändert hat. Genau das war das Problem. Die Berechnung wurde ständig in der Hauptschleife durchgeführt, solange der Wert null war, wurde sie praktisch "übersprungen" und sobald ein Wert da war (nach der ersten Wandlung) immer wieder neu berechnet. Ich habe die Sache nun so abgeändert, dass die Berechnung nur einmalig nach jeder Wandlung durchgeführt wird -> funktioniert. > Falls das nichts hilft wird es schwierig: reichen die String-Längen aus > oder sind die doch um 1 Zeichen zu klein? (Ich kenne mich in BASCOM > nicht aus, in "C" müßte man die Stringdefinition immer 1 länger machen > als den String damit das Terminierungszeichen 0x00 noch hineinpaßt). Bascom fügt automatisch das Terminierungszeichen hinzu. > Ich dachte jetzt immer, man würde mit einem Timer multiplexen und nicht > freilaufend in der Hauptschleife. :D > Im Interrupt hat's nämlich den Vorteil, daß das Multiplexen vorrangig > ausgeführt wird, und höchstens von anderen Interrupts gestört werden > kann. Die Hauptschleife wird dann immer abgearbeitet, wenn Zeit > vorhanden ist und nicht gerade gemultiplext wird. Da habe ich mit der Realisierung Probleme: Die Multiplex-Frequenz muss nämlich synchron mit jener Frequenz sein, mit der die Anzeigen gedimmt werden - sonst flimmerts. Ich stehe leider am Schlauch wie ich das anstellen sollte... MfG Tom
>> Die Multiplex-Frequenz muss nämlich synchron mit jener Frequenz sein, >> mit der die Anzeigen gedimmt werden - sonst flimmerts. Wenn ich das richtig verstehe, dann wird mit Timer0 gedimmt, über Portd.5, Timer0 dient auch zum Multiplexen, aber eben per Abfrage in der Hauptschleife. Sehr ungewöhnlich, m.E. wenig sinnvoll. Was hindert Dich daran, das Gemultiplexe in den Timer0 zu packen und je nach Zählerstand auszutasten, so wie Du es jetzt auch schon machst ?
Wenn die PWM-Frequenz und die Multiplex-Frequenz nicht übereinstimmen, flimmert die Anzeige. Das will ich damit unterbinden.
Die Synchronisierung findet über Timer0 statt und nicht in der Hauptschleife. Also wäre eine Multiplexroutine in der Timer0 ISR synchron mit der durch Timer0 erzeugten PWM. Korrigier mich, wenn die PWM zum Dimmen anders erzeugt wird. Der Unterschied liegt aber darin, daß die ISR vorrangig ausgeführt wird. Ist also die Ausgabe fällig, so wird z.B. die Berechnung eines neuen Ausgabewertes unterbrochen und sofort das Segment ausgegeben. Damit stören in der Hauptschleife gemachte Berechnungen nicht mehr die Ausgabe ducrh Flackern. Wenn man es ganz genau machen möchte, kann man wenn alle 7 Anzeigen durch sind, eine Zählvariable hochzählen und mit deren Hilfe dimmen. Also z.B. Display ein bis 7, danach aus, wenn 10 erreicht, dann Zählerreset.
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.