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