Forum: Mikrocontroller und Digitale Elektronik Zeitproblem - 8 Kanal AD Wandlung


von Jnes Erwin (Gast)


Lesenswert?

Hallo,

Ich programmiere in Assembler.

Wenn ich hintereinander 8 Kanäle messen will, muss ich immer nach
Umstellung des Kanals (in ADMUX) einen Moment warten, sonst
überschneiden sich die Kanäle.

Habt Ihr Erfahrung mit dem Problem.

Meine Lösung bisher:

Mein Programm kontrolliert ständig (ähnlich Windows) Tasten, Anzeige,
Ausgabe usw. auch die AD-Eingänge, stellt dann den nächsten Eingang ein
und eine Wartezeit und kehrt wieder zurück, um die anderen Sachen zu
machen.

Also kein Warten - das Programm ist ständig aktiv, kontrolliert
permanent "Timer" und wenn abgelaufen, macht es eben diese Dinge.
Das geht schon ganz gut ...

Trotzdem meine Frage -- nach dem Zeitproblem, wie lange braucht der MC
zum Umschalten in den nächsten Kanal.

Auch wenn ich ADIF und ADEN abfrage, löse ich es nicht.

Danke

von Rolf Magnus (Gast)


Lesenswert?

> Wenn ich hintereinander 8 Kanäle messen will, muss ich immer nach
> Umstellung des Kanals (in ADMUX) einen Moment warten, sonst
> überschneiden sich die Kanäle.

Das wäre mir neu.

> Mein Programm kontrolliert ständig (ähnlich Windows) Tasten,
> Anzeige, Ausgabe usw. auch die AD-Eingänge, stellt dann den
> nächsten Eingang ein und eine Wartezeit und kehrt wieder zurück,
> um die anderen Sachen zumachen.

Ich hoffe mal, daß Windows das nicht so macht.


> Trotzdem meine Frage -- nach dem Zeitproblem, wie lange braucht
> der MC zum Umschalten in den nächsten Kanal.

Eigentlich sollte das Umschalten sofort gehen, es sei denn, eine
Wandlung ist gerade am Laufen. Dann wird gewartet, bis die zu Ende ist.

von ope (Gast)


Lesenswert?

>> Wenn ich hintereinander 8 Kanäle messen will, muss ich immer nach
>> Umstellung des Kanals (in ADMUX) einen Moment warten, sonst
>> überschneiden sich die Kanäle.

>Das wäre mir neu.

das hängt vom Konzept des (Multichannel) DAC ab, ob die einzelnen
Kanäle jeweils durch einen S&H gepuffert sind oder brutal per MUX die
Kanäle auf einen S&H gewürfelt werden, um dann gewandelt zu werden.

Viele Grüße
Olaf

von Simon (Gast)


Lesenswert?

Hi!

Benutz doch einfach einen Timerinterrupt und stoss dort alle
x ms die Wandlung an.
Dann speicher die Werte in globalen Variablen
also zb
int adc_0
int adc_1
... (oder auch nen array)

Die Timerroutine updatet nach und nach die 8 adc Variablen.
Evtl brauchst du noch nen Flag das angibt welcher wert gerade
geupdatet wird oder so.

Könntest auch den ADC Conversion Interrupt nehmen, nach einer
Wandlung wird der aufgerufen, globale var gesetzt, neue Wandlung
gestartet.


Bye, Simon

von TravelRec. (Gast)


Lesenswert?

Wenn Du direkt nach dem Starten des A/Ds einen kleinen Moment wartest
(so 5 NOPs, je nach ADC-Vorteiler, ausprobieren) und dann den nächsten
MUX-Kanal anwählst, während der A/D noch zuendewandelt, gewinnst Du
einiges an Zeit. Guck doch nochmal in´s Datenblatt, ich denke S/H ist
nach 1,5 ADC-Clocks gegessen und direkt danach kannst Du auch den Kanal
schon umschalten.

von Andi K. (Gast)


Lesenswert?

Wozu warten.
Vor dem Umschalten auf einen anderen Kanal einfach das Bit ADSC
abfragen ob low (0).
Es wird zwar durch setzen auf 1 damit eine Wandlung gestartet bleibt
aber so lange auf 1 bis die Wandlung fertig ist.
Wenn fertig, setzt der Controller das Bit automatisch auf 0.
Also einfach mit "SBIC ADCSR,ADSC" prüfen, ob die vorige Wandlung
fertig ist. Als zweiter Befehl kommt so was wie ein "RJMP ADC-Busy"
oder so was den Teil zum Umschalten und Start einer Wandlung
überspringt was nach dem RJMP beginnt.

MfG
Andi

von TravelRec. (Gast)


Lesenswert?

@andi:
es ging doch gerade darum, Zeit zu sparen - wenn Du auf die komplette
Wandlung wartest, hast Du doch nichts gekonnt - besser wäre es, den Mux
WÄHREND der noch laufenden Wandlung umzuschalten...

von Jnes Erwin (Gast)


Lesenswert?

Danke allen,

die letzte Meinung scheint mir am sinnvollsten, ich will keine nops und
Warteschleifen einbauen und auf keine Flags warten müssen (zumal das
eben nicht funktioniert mit Warten auf ADSC - warum auch immer).

So ähnlich habe ich das auch gemacht ... der AVR muss immerhin noch
"nebenbei" eine Wavedatei und/oder Midi ausgeben und Daten aus
Eeproms holen usw.

Ich dachte ja nur, dass das Problem irgendwo genauer beschrieben ist,
als im Datenblatt.

...

von Andi K. (Gast)


Lesenswert?

Wer hat denn von warten geschrieben?
Ich sicher nicht!

Folgendes:
 SBIC ADCSR,ADSC    ;Ist die aktuelle Wandlung fertig (ADSC=0)?
 RJMP ADC-Busy      ;Wenn nicht, dann weiter zu anderen Dingen.
 .....              ;Ansonsten Mux umschalten und Wandlung starten.
ADC_Busy:
 .....              ;Andere Dinge (bereits vorhandene) erledigen.

Hier wird im "vorbeigehen" geprüft, ob eine Wandlung fertig ist, und
wenn nicht, werden in der Main-Loop die anderen Dinge ab "ADC_Busy"
erledigt.
Wenn eine Wandlung fertig ist und die nächste gestartet wird geht es
danach von selber zur Marke "ADC_Busy" zu den anderen Dingen.
KEIN Warten vor der nächsten Wandlung nur ein Check ob die letzte
fertig ist.

MfG
Andi

von Jnes Erwin (Gast)


Lesenswert?

Danke Andi,

das ist es, was ich will, aber komischer Weise stellen sich eigenartige
Dinge ein. Ich lasse alle 8 Kanäle in dieser Art abfragen und speichere
sie im SRAM ab. Jedesmal wenn sich was ändert sende ich die neuen
Ergebnisse zum Terminal mit einem Erkennungsbyte vorneweg (Kanal1 Wert1
usw.).

Jetzt passiert es aber, dass Kanal1 auch Kanal2 beeinflusst bis dahin,
dass der Wert von Kanal2 z.B. im Kanal1 steht usw., also eine
gegenseitige Beeinflussung stattfindet. Ich danke ja, dass das
Umschalten zu früh passiert oder Zeit fordert.

Hier eine Skizze! des Programms ...

rcall AD_Wandeln   ;auch mit Warten auf Bits (ADIF usw.)
                   ;schieben und einen 8Bitwert machen

rcall WennAndersDannSenden   ;ggf. alt=neu und in SRAM abspeichern

ldi  temp,2          ;umschalten
out  ADMUX,temp

rcall  AD_Wandeln

... usw. ...

sobald ich hinter AD_Wandlen eine kleine Pause einschiebe, geht alles
wunderbar

von Andi K. (Gast)


Lesenswert?

Hier ein Auszug über die Kanaländerung aus dem ATMega8:
"Changing Channel or Reference Selection
The MUXn and REFS1:0 bits in the ADMUX Register are single buffered
through a temporary register to which the CPU has random access. This
ensures that the channels and reference selection only takes place at a
safe point during the conversion. The channel and reference selection is
continuously updated until a conversion is started.
Once the conversion starts, the channel and reference selection is
locked to ensure a sufficient sampling time for the ADC. Continuous
updating resumes in the last ADC clock cycle before the conversion
completes (ADIF in ADCSRA is set). Note that the conversion starts on
the following rising ADC clock edge after ADSC is written. The user
is thus advised not to write new channel or reference selection values
to ADMUX until one ADC clock cycle after ADSC is written.
If both ADFR and ADEN is written to one, an interrupt event can occur
at any time. If the ADMUX Register is changed in this period, the user
cannot tell if the next conversion is based on the old or the new
settings. ADMUX can be safely updated in the following ways:
1. When ADFR or ADEN is cleared.
2. During conversion, minimum one ADC clock cycle after the trigger
event.
3. After a conversion, before the Interrupt Flag used as trigger source
is cleared.
When updating ADMUX in one of these conditions, the new settings will
affect the next ADC conversion."

Soll wohl heißen, das man nach dem Umschalten des Kanals mindestens 1
ADC-Clock warten muß bevor die nächste Konvertierung gestartet wird.
Also bei einem Prescaler von 64 wären das dann 64 Takte.
Dann trifft das von TravelRec zu wo der ADC-Kanal im voraus während
einer ADC-Wandlung umgeschaltet wird.
Also nach dem man die Konvertierung von Kanal 0 gestartet hat, 5 Takte
später auf den Kanal 1 umschalten und weiter den Kanal 0 Wandeln lassen
usw.

MfG
Andi

von TravelRec. (Gast)


Lesenswert?

So dachte ich, danke Andi!

von gerd (Gast)


Lesenswert?

Hallo.

Wenn ich so die Diskussion verfolge, schleicht sich bei mir der
Eindruck ein: Scheinbar sind Interrupts out. Die AD-Wandler lassen sich
herrlich transparent mit dem ADC-Ready-Interrupt steuern. Mit der
ADC-Taktfrequenz lässt sich prima vorwählen, in welchem Takt die
Wandlung und damit die Anzahl Messungen pro (Milli-)Sekunde passieren
soll. Nix mit irgendwelchen Warteschleifen oder andauerndem Polling. 16
Bytes im SRAM dürften auch noch frei sein, da legt der AD-Wandler dann
seine Ergebnisse ab. Und man holt sie völlig asynchron dort ab, wenn
man sie gerade braucht.
Aber wie geschrieben: Interrupts scheinen (AT-)mega-out zu sein. Warum
nur?

mfg
gerd

von TravelRec. (Gast)


Lesenswert?

Interrupts sind nicht out, müssen aber verstanden werden, was für den
Anfänger nicht so einfach ist. Dein Vorschlag ist gut, habe ich auch
schon gemacht. Bevor man aber in die höhere Programmkunst einsteigt,
sollte man sich erstmal über den zeitlichen Ablauf der A/D-Wandlung und
der entsprechenden Peripherie und über die Interpretation des
Datenblatt-Textes im Klaren sein.

von Jnes Erwin (Gast)


Lesenswert?

Ich programmiere wirklich schon lange und komplizierte Sachen. Natürlich
habe ich den Interrupt probiert.

Mir geht es einzig darum, wann ich den AD-Kanal umschalten kann. Denn
leider klappt es nicht, nach einem Interrupt den Kanal umzuschalten und
eine neue Wandlung zu starten. Dann ist beim nächsten Interrupt meist
ein nicht gültiger Wert. Sicher ich kann dann mehrere Interrupts
abwarten, Werte vergleichen usw. -- nur wollte ich wissen, ob jemand
auch diese Problem kennt/hat.

Aber vielleicht beschäftige ich mich noch mal intensiv damit.

Danke allen:

von gerd (Gast)


Lesenswert?

@Andi: Das Warten von einem ADC clock cycle bezieht sich ausschließlich
auf den Fall, dass ADSC bereits gestartet wurde und danach der Kanal
umgeschaltet werden soll. Wenn der ADC-Start nicht automatisch erfolgt,
sondern im Single Conversion Mode per ADSC gestartet wird, ist es nicht
nötig, zwischen MUX und ADSC länger zu warten.

Zu den schwankenden Werten: Ich habe bisher mit ATmega8 und 16 die
Erfahrung gemacht, dass die Messwerte bei gleichbleibender Spannung um
ein Digit rauf oder runter klappern. Keinesfalls klappern mehr Bits.
Wenn das der Fall ist, würde ich den Fehler bei der externen Hardware
suchen (HF-Einstrahlung auf dem Eingangssignal, mangelndes Abblocken
der AD-Versorgung über Drossel/Kondensator und ähnliches).

Eine Fehlerquelle bei der Software kann noch sein, wenn beim
Interrupt-Betrieb SLEEP-Instruktionen verwendet werden. Wenn ADEN an
ist, startet SLEEP die ADC-Wandlung ebenfalls, und das unabhängig von
anderen Einstellungen der ADC-Einheit. Eine etwas abstruse Konstruktion
von Atmel. Das stört erheblich die Synchronisation mit einem Timer. Da
hilft es nur, ADEN abzuschalten und gleichzeitig mit ADSC wieder
einzuschalten (wird mit verlängerter Wandlungszeit bestraft).

mfg
gerd

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.