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!
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:
case0:// 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
case1:// 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
case1:// 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.
Ja, der automatische Trigger ist ziemlich nutzlos.
Nimm doch einfach den Timerinterrupt.
Timerinterrupt:
- ADC auslesen (vorherige Wandlung)
- MUX weiterschalten
- ADC starten.
Peter
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.
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
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
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
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?
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
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
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 ;).
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
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.
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
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