Forum: Mikrocontroller und Digitale Elektronik ADC Register lesen


von Ingo (Gast)


Lesenswert?

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
 ADC verarbeiten; 
5
 neuen Muxwert;
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

von Ingo L. (corrtexx)


Lesenswert?

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 ;)

von Karl H. (kbuchegg)


Lesenswert?

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.

von Ingo L. (corrtexx)


Lesenswert?

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.

von Karl H. (kbuchegg)


Lesenswert?

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?

von Uwe (de0508)


Lesenswert?

Hallo,

noch einen Tipp, man muss nicht in der Timer ISR die Bearbeitung machen, 
sondern kann das Timer Interrupt Flag im Hauptprogramm abfragen.
1
Warte auf das Timer Interrupt Flag
2
Starte die ADC-Wandlung
3
Loesche das Timer Interrupt Flag
4
Warte das Ende der ADC-Wandlung
5
ADC-Wert auslesen
6
ADC-Wert verarbeiten

Somit erhält man ein sauberes Zeitverhalten ohne Interrupt Overhead.

von Christian K. (the_kirsch)


Lesenswert?

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.

von Uwe (de0508)


Lesenswert?

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

von Uwe (de0508)


Lesenswert?

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.

von Ingo L. (corrtexx)


Lesenswert?

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 ;)

von Christian K. (the_kirsch)


Lesenswert?

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?

von uwe (Gast)


Lesenswert?

Vieleich will er die Back-EMF eines BLDC messen

von Ingo L. (corrtexx)


Lesenswert?

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.

von Ingo L. (corrtexx)


Lesenswert?

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

von Georg G. (df2au)


Lesenswert?

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.

von Ingo L. (corrtexx)


Lesenswert?

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.

von Ingo L. (corrtexx)


Lesenswert?

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

von Ralf G. (ralg)


Lesenswert?

Du brauchst tatsächlich, unbedingt, ganz dringend alle 100µs so einen 
Messwert?
Sonst: Mach' einfach eine größere, dafür seltenere Pause.

von Ingo L. (corrtexx)


Lesenswert?

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

von Ingo (Gast)


Lesenswert?

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 ;)

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.