Forum: Mikrocontroller und Digitale Elektronik [BASCOM] A/D-Wandler und Software PWM


von Thomas E. (tomedl)


Angehängte Dateien:

Lesenswert?

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

von Anja (Gast)


Lesenswert?

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).

von MWS (Gast)


Lesenswert?

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.

von Thomas E. (tomedl)


Lesenswert?

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

von MWS (Gast)


Lesenswert?

>> 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 ?

von Thomas E. (tomedl)


Lesenswert?

Wenn die PWM-Frequenz und die Multiplex-Frequenz nicht übereinstimmen, 
flimmert die Anzeige. Das will ich damit unterbinden.

von MWS (Gast)


Lesenswert?

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
Noch kein Account? Hier anmelden.