Hallo. Ich habe folgendes Problem und hoffe ihr könnt mir helfen. Ich habe eine ADC-ISR, die bei erfolgter ADC-Wandlung auslöst. In der ISR speichere ich nur den ADC Wert in ein Array. Nun möchte ich alle x Messungen den ADC Kanal für die nächste Messung umschalten, zu Beispiel bei jeder achten Messung: Ch_1 Ch_1 Ch_1 Ch_1 Ch_1 Ch_1 Ch_1 Ch_2 Ch_1 Ch_1 Ch_1 Ch_1 Ch_1 Ch_1 Ch_1 Ch_2 Ch_1 Ch_1 usw. Mein Ansatz war, den Kanal für die nächste Messung zu Beginn der ISR umzuschalten. Allerdings läuft der ADC an dieser Stelle schon wieder mit der nächsten Wandlung. Dadurch würde mein Kanalwechsel erst in der übernächsten ISR wirksam. Die Verwaltung dieses "in der übernächsten ISR muss ich den Wert woandershin speichern" ist verwirrend und unschön. Wie kann man das einfacher machen? Irgendwie stehe ich gerade voll auf dem Schlauch.
Du könntest z.B. den Freerunning-Mode aufgeben, und statt dessen in der ISR die nächste Wandlung "von Hand" starten. Dann kannst du natürlich noch vor dem Start bei Bedarf den Kanal wechseln.
Consox schrieb: > übernächsten ISR wirksam. Die Verwaltung dieses "in der übernächsten > ISR muss ich den Wert woandershin speichern" ist verwirrend und unschön. Das kommt drauf an, wie du das realisiert hast. Mit 3 globalen Variablen
1 | uint8_t NrSamples; // Anzahl der Samples für den momentanen Kanal |
2 | uint8_t SampleChannel; // Auf welchem Kanal wird gesampelt |
3 | uint8_t DiscardADCResult; // Beim nächsten ISR Aufruf: Ist das ADC Ergebnis was wert |
4 | // oder solle es verworfen werden?
|
sollte sich das eigentlich ganz gut in den Griff kriegen lassen. In der ISR
1 | if( !DiscardADCResult ) { |
2 | -> Ergebnis gilt und wird für den SampleChannel abgelegt |
3 | NrSamples++; |
4 | }
|
5 | else
|
6 | DiscardADCResult = false; // dieses Ergebnis wurde verworfen, aber |
7 | // das nächste gilt wieder
|
8 | |
9 | if( NrSamples == Maximum ) { // Zeit für Kanalwechsel |
10 | SampleChannel++; |
11 | NrSamples = 0; |
12 | ADMUX umstellen; |
13 | DiscardADCResult = true; // nächstes ADC Ergebnis gilt nichts |
14 | }
|
15 | }
|
@Stefan Das wäre eine Idee. Allerdings sample ich damit Audiosignale und habe kein Gefühl dafür, wie sich die daraus resultierende Zeitverschiebung zwischen Abtastzeitpunkten auf das Ergebnis auswirkt. @Karl heinz Ähm, ich will aber keinen Wert verwerfen. Ich möchte 7x Channel 1 einlesen, dann einmal Channel 2, dann wieder 7x Channel 1 und so weiter. Das alles im gleichen Takt. Die Ergebnisse von Ch1 sollen in ein Array, die Ergebnisse von Ch2 in ein anderes Array.
Consox schrieb: > Ich möchte 7x Channel 1 > einlesen, dann einmal Channel 2, dann wieder 7x Channel 1 und so weiter. > Das alles im gleichen Takt. Die Ergebnisse von Ch1 sollen in ein Array, > die Ergebnisse von Ch2 in ein anderes Array. Ah ok. dann musst du praktisch den ADC bereits auf den nächsten Kanal weiterschalten, wenn die letzte Messung für einen Kanal gerade im laufen ist. Wo ist dann das Problem? Wenn du immer 8 ADC Messungen machen willst, schaltest du bereits nach der 7.ten den ADC in den nächsten Kanal. Du musst dir nur merken, dass die nächste Messung für die die ISR aufgerufen wird, noch für den vorhergehenden Kanal gilt. Im Prinzip genau so, wie ich das mit dem Discard gemacht habe, nur anstelle von verwerfen speicherst du den Wert noch beim vorhergehenden Kanal. Aufzeichnen auf Papier (die x Achse ist die Zeitachse) hilft, Ordnung in das Chaos zu bringen und sich anzusehen, in welcher Reihenfolge welche Dinge, beim Betreten der ISR gemacht werden müssen und warum.
Consox schrieb: > Das wäre eine Idee. Allerdings sample ich damit Audiosignale und habe > kein Gefühl dafür, wie sich die daraus resultierende Zeitverschiebung > zwischen Abtastzeitpunkten auf das Ergebnis auswirkt. > ... > Ähm, ich will aber keinen Wert verwerfen. Dann bleibt dir nichts anderes übrig, als sich mit dem "verwirrend und unschön" anzufreunden. Soo wild ist das ja aber nun auch nicht. Du lässt z.B. eine Variable von 0 bis 7 durch zählen. Bei 5 wechselst du auf Ch2, bei 6 zurück auf Ch1. Bei 0-6 hast du die Ch1-Ergebnisse, bei 7 das Ch2-Ergebnis.
Danke euch Beiden. Wenn man das mit einfachen Worten von jemand Anderem hört, sieht die Lösung gleich viel einfacher aus.
Hallo, Karl heinz Buchegger schrieb: > Wo ist dann das Problem? > Wenn du immer 8 ADC Messungen machen willst, schaltest du bereits nach > der 7.ten den ADC in den nächsten Kanal. Du musst dir nur merken, dass > die nächste Messung für die die ISR aufgerufen wird, noch für den > vorhergehenden Kanal gilt. Im Prinzip genau so, wie ich das mit dem > Discard gemacht habe, nur anstelle von verwerfen speicherst du den Wert > noch beim vorhergehenden Kanal. Dabei aber daran denken, daß der Kanal erst nach dem 2. ADC-Takt umgeschaltet werden darf, erst dann ist der Sample&Hold-Wert stabil. Das würde eine Wartezeit in der ISR bedeuten, die vermutlich auch wieder Probleme bereitet. Gruß aus Berlin Michael
Michael U. schrieb: > Dabei aber daran denken, daß der Kanal erst nach dem 2. ADC-Takt > umgeschaltet werden darf, erst dann ist der Sample&Hold-Wert stabil. > Das würde eine Wartezeit in der ISR bedeuten, die vermutlich auch wieder > Probleme bereitet. Warum denn nicht...? * Auslesen des ADC und Kanal umschalten in der ADC-ISR, Timer I-Flag zurücksetzen (siehe Unten). * ADC (kurze Zeit später) durch einen Timer-Event triggern. Timer-Trigger muss natürlich etwas länger als die Wandelzeit sein. Dadurch werden vermutlich auch die Zeitabstände zwischen den Samples gleichmäßiger.
@ Werner B. (werner-b) >Warum denn nicht...? >* Auslesen des ADC und Kanal umschalten in der ADC-ISR, Timer I-Flag >zurücksetzen (siehe Unten). >* ADC (kurze Zeit später) durch einen Timer-Event triggern. Und wozu wurde der Free running mode erfunden? >Timer-Trigger muss natürlich etwas länger als die Wandelzeit sein. >Dadurch werden vermutlich auch die Zeitabstände zwischen den Samples >gleichmäßiger. Dafür gibt es den Free running mode. Dort ist die Abtastrate absolut gleichmäsig. Aber mal rechnen. Der ADC braucht 50..200kHz, sinnvollerweise wird man ihn immer mit nahe 200kHz betreiben. Ein Takt sind also 5us. Macht bei max. 20 MHz 100 Takte. Naja, die kann man verschmerzen. In C dauert der ISR Einsprung sowieso etwas länger, weil meist mehr Register auf dem Stack landen. Dann noch ADC Ergebnis auslesen und speichern, ggf. was einfaches berechnen. Wenn dann immer noch keine 5µs vorbei sind (im Simulator prüfen), kann man ausnahmsweise ein _delay_us() einbauen, auch wenn man das in einem Interrupt sonst nicht macht. MfG Falk P S Aber irgendwie hat Atmel da gepennt. Siehe Beschreibung im Datenblatt unter "Changing Channel or Reference Selection". Wäre es nicht DEUTLICH sinnvoller, wenn eben genau WÄHREND der sampling time der Update von ADMUX gesperrt ist, und während der gesammten Conversion Time ein Update möglich ist. Denn Nach der Sampling Time ist der MEsswert doch in der Sample & Hold Stufe fest, da kann der analoge Eingang doch zappeln? Oder etwa nicht? Oder gibt es vielleicht ei Übersprechen vom Eingang in die Sample & Hold?
Hallo, Falk Brunner schrieb: > P S Aber irgendwie hat Atmel da gepennt. Siehe Beschreibung im > Datenblatt unter "Changing Channel or Reference Selection". Wäre es > nicht DEUTLICH sinnvoller, wenn eben genau WÄHREND der sampling time der > Update von ADMUX gesperrt ist, und während der gesammten Conversion Time > ein Update möglich ist. Denn Nach der Sampling Time ist der MEsswert > doch in der Sample & Hold Stufe fest, da kann der analoge Eingang doch > zappeln? Oder etwa nicht? Oder gibt es vielleicht ei Übersprechen vom > Eingang in die Sample & Hold? ja, wenn sie da noch ein Register eingebaut hätten, in das die MUX-Daten geschrieben werden und dann intern nach dem Abkoppeln der S&H diese intern übernommen hätten, müßte man darüber nicht nachdenken. Andererseits war der ADC im AVR wohl auch eher für "langsame" Sachen gedacht und da stört sowas dann weniger. Gruß aus Berlin Michael
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.