Forum: Mikrocontroller und Digitale Elektronik AVR: Wechseln des Kanals mit automatischem Trigger


von AVR (Gast)


Lesenswert?

Hi,

ich bin gerade dabei ein Beschleunigungssensor am AVR zu verarbeiten. 
Der Sensor ist mit seinen X, Y und Z Achsen an PC0, PC1 bzw. PC2 
angeschlossen (Kanal 0 - 2).

Die ADC Komponente ist so konfiguriert, dass sie beim CTC Match von 
Timer/Counter0 eine Konvertierung startet. Der Timer/Counter0 hingegen 
"löst" 300 Mal pro Sekunde einen CTC Match aus.

Nun würde ich gerne in der ADC ISR den Kanal "weiterschalten". Dafür 
muss ich ADMUX ändern.

Im Datenblatt findet sich nun folgendes:

> If both ADATE 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:
>  a. When ADATE or ADEN is cleared.
>  b. During conversion, minimum one ADC clock cycle after the trigger
>     event.
>  c. 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.

Da ich das Ganze Interrupt gesteuert abhandle, kann ich leider nicht 
sicherstellen, dass Punkt b oder c zutreffen. Insofern muss ich mich um 
Punkt a.) kümmern, was im Wesentlichen bedeutet, dass ich ADATE vor dem 
Wechsel des Kanals "cleare" und anschließend wieder aktiviere.

Das klappt auch alles wunderbar, allerdings stell sich mir die Frage, ob 
das in meinem Fall überhaupt notwendig ist. Funktionieren tut es 
jedenfalls auch ohne das explizite Deaktivieren des automatischen 
Triggers.

Insbesondere verstehe ich folgende Aussage nicht so recht:
> If both ADATE and ADEN is written to one, an interrupt event can occur
> at any time.

Wieso kann ein Interrupt "zu jeder Zeit" stattfinden? In meinem Fall 
tritt der Interruptrequest regelmäßig mit 300 Hz ein. Das ein Interrupt 
"verschluckt" wird, schließe sich jetzt einfach mal aus, denn meine ISRs 
sind recht kurz und auch ohne es explizit durchgerechnet zu haben, 
sollte die Zeit locker zu Abarbeitung reichen. 300 Hz sind ja jetzt 
nicht so viel. Muss ich dennoch den automatischen Trigger beim Wechsel 
des Kanals deaktivieren?

Wenn ja, wieso? So ganz erschließen will sich mir das nämlich nicht. Ich 
will jetzt hier nicht das Datenblatt zu meinen Gunsten auslegen, aber 
ich kann auch ohne das Deaktivieren keine Einschränkung der 
Funktionalität feststellen und verstehe die o.g. Aussage im Datenblatt 
nicht so recht. Meiner Meinung wäre bezieht sich das wohl eher auf 
"zufällig" ausgelöste Interrupts wie z.B. einen externen Interrupt oder 
den Free Running Mode.

Vielen Dank!

von bitte löschen (Gast)


Lesenswert?

AVR schrieb im Beitrag #2878806:
> ich bin gerade dabei ein Beschleunigungssensor am AVR zu verarbeiten.

Es gibt unterschiedliche AVRs. ;-) Handelt es sich hier um einen 
ATmega44/88/168 oder komplatiblen?

> Die ADC Komponente ist so konfiguriert, dass sie beim CTC Match von
> Timer/Counter0 eine Konvertierung startet. Der Timer/Counter0 hingegen
> "löst" 300 Mal pro Sekunde einen CTC Match aus.
..

Warum lässt Du nicht einfach den Timer in Ruhe und nimmst den ADC im 
Free Running Mode mit dem ADC-Interrupt als Ersatz-Timer?
Vorteil: Totale Synchronizität zwischen dem, was Dein Programm macht und 
dem, was Dein ADC macht.
Wenn Du in der ADC-ISR den Kanal wechselst, musst Du nur 
berücksichtigen, dass die bereits laufende nächste Konvertierung noch 
den zuletzt eingestellten Kanal hat und das Ergebnis des neuen Kanals 
beim übernächsten Aufruf zu erwarten ist. Wenn Du die Kanäle immer in 
der gleichen Reihenfolge abfragst, ist das ja auch kein Problem.
Etwa so:
1
#define SETADMUX_KANAL(x) ADMUX = ADMUX & (~15 | x);
2
3
switch(ErgebnisKanal)
4
{
5
  case 0: // Ergebnis von Messung 0, es läuft Messung 1, setzte Kanal 2
6
    VerarbeiteKanal0(ADC);
7
    SETADMUX_KANAL(2);
8
    Ergebniskanal = 1;
9
    break;
10
  case 1: // Ergebnis von Messung 1, es läuft Messung 2, Setzte Kanal 0
11
    VerarbeiteKanal1(ADC);
12
    SETADMUX_KANAL(0);
13
    Ergebniskanal = 2;
14
    break;
15
  case 1: // Ergebnis von Messung 2, es läuft Messung 0, Setzte Kanal 1
16
    VerarbeiteKanal2(ADC);
17
    SETADMUX_KANAL(1);
18
    Ergebniskanal = 0;
19
    break;
20
}

> Insbesondere verstehe ich folgende Aussage nicht so recht:
>> If both ADATE and ADEN is written to one, an interrupt event can occur
>> at any time.

Ich denke, dass damit ein ADC-Interrupt gemeint ist.

Nachtrag:
Denke daran, dass die ADC-Eingänge bei ständigen Kanalwechseln 
niederohmig zu treiben sind, da der Sample&Hold-Kondensator ständig 
umgeladen werden muss und nicht einfach einem Signal folgen muss.

von Peter D. (peda)


Lesenswert?

Ja, der automatische Trigger ist ziemlich nutzlos.
Nimm doch einfach den Timerinterrupt.

Timerinterrupt:
- ADC auslesen (vorherige Wandlung)
- MUX weiterschalten
- ADC starten.


Peter

von AVR (Gast)


Lesenswert?

Philipp K. schrieb:
> Es gibt unterschiedliche AVRs. ;-) Handelt es sich hier um einen
> ATmega44/88/168 oder komplatiblen?
Ok, das habe ich ganz vergessen. Es handelt sich um einen ATmega88.

Philipp K. schrieb:
> Warum lässt Du nicht einfach den Timer in Ruhe und nimmst den ADC im
> Free Running Mode mit dem ADC-Interrupt als Ersatz-Timer?
Der Free Running Mode gefällt mir nicht so recht, weil ich in der Tat 
"nur" 300 Hz benötige (100 pro Kanal). Die Möglichkeiten der 
Prescalerwahl sind ja recht beschränkt.

Philipp K. schrieb:
> Etwa so:
Ja, das mache ich jetzt im Prinzip auch schon so.

Philipp K. schrieb:
> Nachtrag:
> Denke daran, dass die ADC-Eingänge bei ständigen Kanalwechseln
> niederohmig zu treiben sind, da der Sample&Hold-Kondensator ständig
> umgeladen werden muss und nicht einfach einem Signal folgen muss.
Leider bin ich was die dahinterstehende Elektrotechnik angeht, noch sehr 
grün hinter den Ohren. Was heißt denn hier "niederohmig"? Es befindet 
sich zumindest kein dedizierter Widerstand in der Leitung. Die Ausgänge 
des Beschleunigungssensors sind direkt mit den entsprechenden Pins des 
AVRs verbunden. Das müsste so schon hinhauen, oder?

Peter Dannegger schrieb:
> Ja, der automatische Trigger ist ziemlich nutzlos.
> Nimm doch einfach den Timerinterrupt.
Naja, funktionieren tut es ja wie es soll - auch ohne das Deaktivieren 
des automatischen Triggers. Mich würde hauptsächlich nur interessieren 
wie die entsprechende Passage im Datenblatt zu interpretieren ist, weil 
sie für mich nicht wirklich Sinn ergibt.

Peter Dannegger schrieb:
> Timerinterrupt:
> - ADC auslesen (vorherige Wandlung)
> - MUX weiterschalten
> - ADC starten.
Im Prinzip mache ich genau das in meiner ADC ISR bereits. Natürlich 
könnte ich das in die Timer ISR stecken, aber mir gefällt es gerade 
besser das "logisch" dem ADC zuzuordnen und nicht dem Timer. Außerdem 
bleibt es mir so möglich die Timer ISR kurz zu halten, sofern ich sie 
denn mal benötigen würde.

von spess53 (Gast)


Lesenswert?

Hi

Ich benutze den Autotriggermode mit Multiplexerumschaltung im 
ADC-Interrupt  schon seit Jahren in veschiedenen Anwendungen. 
Funktioniert problemlos.

>Mich würde hauptsächlich nur interessieren
>wie die entsprechende Passage im Datenblatt zu interpretieren ist, weil
>sie für mich nicht wirklich Sinn ergibt.

Die machen dann Sinn, wenn man in die Überlegung einbezieht, das die 
MUX-Umstellung auch an anderer Stelle im Programm, sozusagen 
'asynchron', erfolgen kann.

MfG Spess

von Peter D. (peda)


Lesenswert?

spess53 schrieb:
> Ich benutze den Autotriggermode mit Multiplexerumschaltung im
> ADC-Interrupt  schon seit Jahren in veschiedenen Anwendungen.
> Funktioniert problemlos.

Man muß dann aber beachten, daß man den Timerinterrupt auch noch 
ausführt, damit dessen Flag gelöscht wird.
Man hat also einen Interrupt inklusive Push/Pop-Gedöns mehr auszuführen.
Oder man löscht das Flag händisch im ADC-Interrupt.
Sparen tut man also durch Autotrigger rein garnix.


Peter

von spess53 (Gast)


Lesenswert?

Hi

>Man muß dann aber beachten, daß man den Timerinterrupt auch noch
>ausführt, damit dessen Flag gelöscht wird.
>Man hat also einen Interrupt inklusive Push/Pop-Gedöns mehr auszuführen.
>Oder man löscht das Flag händisch im ADC-Interrupt.

Bei mir reicht ein einfaches RETI, ohne push/pop-Orgie. Aber meist wird 
dazu ein Timer benutzt, der eh schon etwas in der ISR macht. Also kein 
nenneswerter zusätzlicher Aufwand. Dagegen muss beim manuellen Starten 
in der Timer-ISR dort immer der Aufwand betrieben werden.

>Sparen tut man also durch Autotrigger rein garnix.

Man hat die komplette ADC-Behandlung in einem Interrupt und nicht auf 
zwei Baustellen. Ich sehe das als Vorteil.

MfG Spess

von bitte löschen (Gast)


Lesenswert?

AVR schrieb im Beitrag #2879058:
> Philipp K. schrieb:
>> Warum lässt Du nicht einfach den Timer in Ruhe und nimmst den ADC im
>> Free Running Mode mit dem ADC-Interrupt als Ersatz-Timer?
> Der Free Running Mode gefällt mir nicht so recht, weil ich in der Tat
> "nur" 300 Hz benötige (100 pro Kanal). Die Möglichkeiten der
> Prescalerwahl sind ja recht beschränkt.
Darf ich mal fragen, welchen Systemtakt Du hast?
Und noch eine: Wie genau müssen es 300Hz sein?

> Philipp K. schrieb:
>> Nachtrag:
>> Denke daran, dass die ADC-Eingänge bei ständigen Kanalwechseln
>> niederohmig zu treiben sind, da der Sample&Hold-Kondensator ständig
>> umgeladen werden muss und nicht einfach einem Signal folgen muss.
> Leider bin ich was die dahinterstehende Elektrotechnik angeht, noch sehr
> grün hinter den Ohren. Was heißt denn hier "niederohmig"? Es befindet
> sich zumindest kein dedizierter Widerstand in der Leitung. Die Ausgänge
> des Beschleunigungssensors sind direkt mit den entsprechenden Pins des
> AVRs verbunden. Das müsste so schon hinhauen, oder?
Das hängt von der Ausgangsimpedanz deines Sensors ab. Hast Du da ein 
Datenblatt bzw. eine Typenbezeichnung?

von Peter D. (peda)


Lesenswert?

spess53 schrieb:
> Man hat die komplette ADC-Behandlung in einem Interrupt und nicht auf
> zwei Baustellen. Ich sehe das als Vorteil.

Wo ist die 2. Baustelle?
Den ADC-Interrupt brauche ich ja nicht, der Timrinterrupt macht bereits 
alles.


Peter

von spess53 (Gast)


Lesenswert?

Hi

>Wo ist die 2. Baustelle?
>Den ADC-Interrupt brauche ich ja nicht, der Timrinterrupt macht bereits
>alles.

Stimmt. Ich hatte das:

> - ADC auslesen (vorherige Wandlung)

überlesen. Ändert aber nichts daran, das ich keine gravierende Vorteile 
gegenüber dem Autotriggermode sehe.

MfG Spess

von AVR (Gast)


Lesenswert?

Peter Dannegger schrieb:
> Oder man löscht das Flag händisch im ADC-Interrupt.

Ja, wobei das "hässlich" ist, weil man dann in der Tat zwei Baustellen 
hätte. Daher führe ich den Timer/Counter0 Interrupt aus (reti).

Philipp K. schrieb:
> Das hängt von der Ausgangsimpedanz deines Sensors ab. Hast Du da ein
> Datenblatt bzw. eine Typenbezeichnung?

ADXL335. Habe da im Datenblatt (auf die Schnelle nichts über die 
Ausgangsimpedanz gefunden). An den Ausgängen hängen jeweils noch 0.1 μF 
Kondensatoren, was wohl 50 Hz entspricht. Daher würde ich gerne mit 100 
Hz pro Kanal "abtasten".

Philipp K. schrieb:
> Darf ich mal fragen, welchen Systemtakt Du hast?
> Und noch eine: Wie genau müssen es 300Hz sein?

Naja, doppelt so viel wie die analoge Bandbreite darf (soll) es schon 
sein. Zur Zeit läuft der Mikrocontroller mit 8 MHz, aber da hab ich mich 
ehrlich gesagt noch nicht wirklich festgelegt und muss erst einmal ein 
wenig mit der Anwendung "herumspielen". Diese ist nämlich 
Batteriebetrieben und da ist weniger oft mehr ;).

von Spess53 (Gast)


Lesenswert?

Hi

>> Oder man löscht das Flag händisch im ADC-Interrupt.
>Ja, wobei das "hässlich" ist, weil man dann in der Tat zwei Baustellen
>hätte. Daher führe ich den Timer/Counter0 Interrupt aus (reti).

Das händische Zurücksetzen ist aber schneller als das Ausführen des 
Interrupts. Auch wenn der nur ein Reti abarbeitet.

MfG Spess

von bitte löschen (Gast)


Angehängte Dateien:

Lesenswert?

AVR schrieb im Beitrag #2879554:
> ADXL335. Habe da im Datenblatt (auf die Schnelle nichts über die
> Ausgangsimpedanz gefunden). An den Ausgängen hängen jeweils noch 0.1 μF
> Kondensatoren, was wohl 50 Hz entspricht. Daher würde ich gerne mit 100
> Hz pro Kanal "abtasten".

Auf folgendem Datenblatt ist ein Blockschaltbild von dem Teil:
http://www.analog.com/static/imported-files/data_sheets/ADXL335.pdf

Da sind in den Ausgängen Widerstände von etwa 32K eingezeichnet.
Im Datenblatt vom ATmega44/88/168 heißt es:
"The ADC is optimized for analog signals with an output impedance of 
approximately 10kΩ or less."

AVR schrieb im Beitrag #2879554:
> An den Ausgängen hängen jeweils noch 0.1 μF Kondensatoren
Das ist auch eine Möglichkeit, ausreichend Power zum Füllen des 
Sample&Hold Kondensators (14pF) zur Verfügung zu stellen.

Ich würde erst mal in einem Versuchsaufbau probieren, ob es Unterschiede 
gibt, wenn ich noch jeweils einen Impedanzwandler dazwischen schalte 
oder nicht. Da das gerade mit einem Beschleuningungssensor schwer 
reproduzierbar zu bewerkstelligen ist, würde ich wahrscheinlich auf 
Nummer Sicher gehen.
Laut Datenblatt liefert das Teil etwa 300mV/g bei einem Messbereich von 
typ. 3,6g, also ein gutes Volt bei Vollausschlag. Ein Rail-to-Rail OP 
muss es also nicht sein, aber einer, der mit entsprechend wenig 
Versorgung klarkommt. (3,6V Versorgung verträgt der Sensor maximal.)
Ich habe mal eine Vergleichsliste von Motorola angehängt.
Vielleicht hilft das bei der Auswahl.

von Stephan (Gast)


Lesenswert?

In ner Heizungssteuerung (ATMega128) starte ich den ADC (8*32sps) per 
Timer (genauer gesagt in der Hauptschleife wenn die ADC-Zeitscheibe 
wieder dran ist).
Mittelung und MUX-Umschaltung im ADC-Interrupt.

MUX unmittelbar vor der Wandlung umgeschaltet führte bei mir trotz 10nF 
an den ADC-Eingängen zu deutlichem Übersprechen. Der Sprung am Eingang 
war aber groß (0/5V > ca.2.5V) und der Wertebereich schlecht ausgenutzt 
(nur 512+-32 relevant). Der Fehler war jedenfalls größer als der 
relevante Messbereich.
Die Bandbreite des Eingangs ist aber auch nur mit 38.5kHz angegeben, 
also nicht weiter verwunderlich.


Stephan

von Spess53 (Gast)


Lesenswert?

Hi

>MUX unmittelbar vor der Wandlung umgeschaltet führte bei mir trotz 10nF
>an den ADC-Eingängen zu deutlichem Übersprechen.

Ist oft ein Indiz dafür, das der ADC-Takt zu hoch ist.

MfG Spess

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.