Hallo,
ich möchte gern mit meinem ADC vom meinem Atmega328@20MHz ein Signal mit
10kHz abtasten. Den ADC würde ich von einem Timer triggern wollen.
Dazu sähe meine Pseudo-ISR so aus.
1
ISR(TimerOverflow)
2
{
3
ADC_lesen;
4
ADCverarbeiten;
5
neuenMuxwert;
6
}
Da der ADC bei Timeroverflow automatisch gestartet wird würde ich ihn
auslesen wenn er noch läuft. Jetzt weiss ich aber nicht, ab im
ADC-Ergebnis-Register jetzt noch der Wert der vorherigen Wandlung steht
(was ich hoffe und auch will) oder ein Teilergebnis der aktuellen
Wandlung?
Andere Alternative wäre den ADC per Hand zu starten, bevor die ISR
verlassen wird und quasi beim Betreten ausgelsen wird. Da ist der ADC ja
definitiv mit deiner Wandlung fertig.
Was meint ihr? Im DB finde ich nichts was mir weiter hilft.
VG,
Ingo
Ingo schrieb:> ein Signal mit> 10kHz abtasten. Den ADC würde ich von einem Timer triggern wollen.
Dabei soll der ADC mit 10kHz getriggert werden, liest sich so etwas
missverständlich.
VG,
Ingo
P.S.
Jetzt auch angemeldet ;)
Ingo schrieb:> Da der ADC bei Timeroverflow automatisch gestartet wird würde ich ihn> auslesen wenn er noch läuft.
Der ADC kann seinerseits einen Interrupt triggern, wenn er sein Ergebnis
fertig hat.
> ADC-Ergebnis-Register jetzt noch der Wert der vorherigen Wandlung steht> (was ich hoffe und auch will)
gute Frage. Verlassen würde ich mich nicht darauf. Ob du den
vorhergehenden Wert aus dem ADC holst oder aus einer Variablen sollte
doch eigentlich aufs gleiche rauslaufen.
> Andere Alternative wäre den ADC per Hand zu starten, bevor die ISR> verlassen wird und quasi beim Betreten ausgelsen wird. Da ist der ADC ja> definitiv mit deiner Wandlung fertig.
Ist auch eine Möglichkeit. Wenn dir der Zeitversatz nichts ausmacht, ist
es sogar gar keine schlechte Möglichkeit.
Karl Heinz schrieb:> Der ADC kann seinerseits einen Interrupt triggern, wenn er sein Ergebnis> fertig hat.
Das weiss ich, danke. Das Problem ist, dass der ADC mit 10kHz getriggert
werden soll, somit habe ich ein Zeitfenster von 100µs. Eine Wandlung
dauert aber schon 13* (20MHz/128) = 83,2µs
Somit muss das alles gut getimt werden. Von daher würde ich gern auf den
Interrupt mit seinem Overhead verzichten und lieber ein gutes Konzept
haben.
Ingo L. schrieb:> werden soll, somit habe ich ein Zeitfenster von 100µs. Eine Wandlung> dauert aber schon 13* (20MHz/128) = 83,2µs
Das ist natürlich ein Argument.
> Somit muss das alles gut getimt werden. Von daher würde ich gern auf den> Interrupt mit seinem Overhead verzichten und lieber ein gutes Konzept> haben.
Mir gefällt die Sichtweise des: am Ende der Timer-ISR den ADC starten,
beim nächsten ISR Aufruf das Ergebnis holen. Find ich gut.
Bist du unglücklich damit?
Und warum den ADC-Wert nicht über die ADC-ISR abholen?
uint16_t lastADC=0;
ISR(ADC_vect){
lastADC = ADCW;
}
auswerten kannst du lastADC ja bei der nächsten Timer-ISR aufruf.
Hallo Ingo,
Du weist schon, dass diese Rechnung falsch ist ?
Die erste Einheit ist Hz, die andere s.
Es gilt f = 1 /s oder s = 1 /f
Ingo L. schrieb:> 13* (20MHz/128) = 83,2µs
Hallo Christian,
rechne Dir mal den Interrupt Overhead aus, das macht keinen großen Sinn
bei seinen Anforderungen, wie kennen die Zeit in der ADC Verarbeitung
nicht.
Christian K. schrieb:> Und warum den ADC-Wert nicht über die ADC-ISR abholen?>> uint16_t lastADC=0;>> ISR(ADC_vect){> lastADC = ADCW;> }>> auswerten kannst du lastADC ja bei der nächsten Timer-ISR aufruf.
Uwe S. schrieb:> noch einen Tipp, man muss nicht in der Timer ISR die Bearbeitung machen,> sondern kann das Timer Interrupt Flag im Hauptprogramm abfragen.
Ja, aber ich muss halt sehr sicher sein das die 10kHz passen, da hier
ein ge-PWMtes Signal handelt, somit muss ich immer zum selben Zeitpunkt
das Signal samplen um die PWM dort zu unterdrücken.
Christian K. schrieb:> Und warum den ADC-Wert nicht über die ADC-ISR abholen?
weil
Ingo L. schrieb:> Das weiss ich, danke. Das Problem ist, dass der ADC mit 10kHz getriggert> werden soll, somit habe ich ein Zeitfenster von 100µs. Eine Wandlung> dauert aber schon 13* (20MHz/128) = 83,2µs
ich das das zu knapp finde.
Karl Heinz schrieb:> Bist du unglücklich damit?
Noch nicht, ich bin gerade dabei den "Fahrplan" zu erstellen, ich hab
noch keine Zeile Code geschrieben ;)
Du willst ein PWM-Signal abtastet?
Das ist doch nur 0 oder 1, dafür brauch man kein ADC. Du musst die Zeit
zwischen den Flanken messen.
Oder ist das PWM-Signal über einen Tiefpass geglättet?
Uwe S. schrieb:> Hallo Ingo,>> Du weist schon, dass diese Rechnung falsch ist ?> Die erste Einheit ist Hz, die andere s.> Es gilt f = 1 /s oder s = 1 /f>> Ingo L. schrieb:>> 13* (20MHz/128) = 83,2µs
Ja, uups, irgendwie das Reziprog vergessen
Uwe S. schrieb:> wie kennen die Zeit in der ADC Verarbeitung> nicht.
Ich auch noch nicht, ist aber überschaubar, sollte alles fix gehen damit
meine while(1) noch Zeit hat die langsamen Sachen wie Flags und
zeitunkritische Sachen abzuarbeiten.
uwe schrieb:> Vieleich will er die Back-EMF eines BLDC messen
Bingo ;)
https://www.youtube.com/watch?v=szgVUfyX8JM
Ich will das mal ausprobieren, die Lösung mit dem analog Komparator
gibts ja und die wird hier als "schlecht" betitelt. Mal gucken wie gut
das mit der Flussintegration geht. Hardware steht fast (noch bestücken)
und dann kanns los gehen. Wenn es gute Ergbinsse bringt mache ich evtl.
einen Artikel oder hänge mich an den bestehenden dran.
Ingo
Ingo schrieb:> Da der ADC bei Timeroverflow automatisch gestartet wird
Und warum muss das so sein?
Wie wäre es mit
Timer-ISR() {
lese ADC;
wähle neuen Kanal;
starte Wandlung;
tu, was immer du noch machen musst, während die neue Wandlung schon
läuft.
fertig}
Damit hast du immer fast 100us Zeit für die Wandlung.
Georg G. schrieb:> lese ADC;> wähle neuen Kanal;> starte Wandlung;
Deine Variante habe ich auch schon in Betracht gezogen, erscheint auch
sinnvoll.
Ingo schrieb:> Andere Alternative wäre den ADC per Hand zu starten, bevor die ISR> verlassen wird und quasi beim Betreten ausgelsen wird. Da ist der ADC ja> definitiv mit deiner Wandlung fertig.
Aber ich finde es schon interessant ob
Ingo schrieb:> Da der ADC bei Timeroverflow automatisch gestartet wird würde ich ihn> auslesen wenn er noch läuft. Jetzt weiss ich aber nicht, ab im> ADC-Ergebnis-Register jetzt noch der Wert der vorherigen Wandlung steht> (was ich hoffe und auch will) oder ein Teilergebnis der aktuellen> Wandlung?
das auch geht. Leider habe ich im Moment auch keinen Simulator zur Hand
und die Hardware läuft noch nicht.
Eine weitere schwierigkeit wird sein, die BEMF zu berechnen, da ich ja
hierfür eigentlich auch die dazugehötige Versorungsspannung benötige.
Diese habe ich natürlich mit auf den Controller geführt. Aber die muss
ja auch erstmal gesampelt werden um sie dann mit in Rechnung mit
einfliessen zu lassen. Oder man Sampelt die BEMF mit nur 5kHz und mit
den anderen 5kHz die anderen Werte wie Versorungsspannung der Endstufe,
DC-Strom, U-Sollwert. Ist halt fraglich ob man mit 5kHz noch genügend
Werte aufsammeln kann bei Vollgas. Habe hier einen BLDC mit 9000 RPM @
12V. Macht also 1,1ms pro Sektor also gerade mal 5 Samples. Sehr
fraglich...
So langsam habe ich das Gefühl ich wäre doch besser mit nem F4 ins
Gefecht gegangen :)
Ralf G. schrieb:> Du brauchst tatsächlich, unbedingt, ganz dringend alle 100µs so einen> Messwert?
Für das Integratorprinzip schon. Wenn ich quasi eine Integrationspause
mache kann ich evtl. nicht zur rechten Zeit kommutieren. Oder ich muss
zwischen zwei Werten interpolieren und quasi immer einen Wert
nachträglich ausrechnen und integrieren. Dann könnte ich evtl. wirklich
mit 5kHz abtasten...
Also das Auslesen des ADC-Registers während bereits eine neue Wandlung
läuft funktioniert ohne Probleme. Hätte man auch daraus ableiten können
das es im Free-Run ja auch gehen muss.
Vorsicht Stolperfalle:
Wenn man den ADC ausliest, darf man nicht das aktuelle Mux-Register
lesen, sondern das was vor der Wandlung gültig war, also den Mux
zwischenspeichern ;)