Forum: Mikrocontroller und Digitale Elektronik AD-Wandlung dauert zu lange (30µs) [Atmega32]


von Funkenschlosser (Gast)


Lesenswert?

Ich lasse den AD-Wandler frei laufen, da eine single conversion zu lange 
dauert. Eine 20 kHz PWM stößt bei der steigenden Flanke ein Interrupt an 
(Timer1 Overflow ist die steigende Flanke) und in diesem Interrupt wird 
der AD-Wandler enabled.

Um zu erkennen, wie lange die Wandlung dauert, wird ein Port 
eingeschaltet und nach der Wandlung wieder ausgeschaltet. Mit dem 
Oszilloskop messe ich 30µs, was bei einer Periodendauer der PWM von 50µs 
viel zu lange ist, da ich während den Flanken nicht messen will, um 
Einflüsse zu vermeiden. Die PWM ist im Betrieb die größte Zeit fast voll 
aufgefahren. Wie erreicht man die im Datenblatt angegebenen 7µs?
1
ISR(TIMER1_OVF_vect) //Wird bei pos. PWM-Flanke ausgeführt
2
{
3
   PORTC |= (1<<PC0); // Pin high für Zeitmessung des ADC´s am Oszi
4
   ADCSRA |= (1<<ADEN); //ADC enable
5
   ADCSRA |= (1<<ADSC); //ADC starten
6
}
7
8
ISR(ADC_vect)
9
{  
10
    UIST = ADCW; // Wert holen
11
    ADCSRA &=  ~(1<<ADEN); // ADC deaktivieren
12
  
13
    PORTC &= ~(1<<PC0);  // Pin low, Zeitmessung ende
14
    messen = TRUE; // Berechnung freischalten
15
}
16
17
main:
18
{
19
....
20
ADMUX = 4; // Kanal waehlen
21
ADMUX |= (1<<REFS0); // interne Referenzspannung nutzen
22
ADCSRA |= (1<<ADATE)| (1<<ADIE) | (1<<ADPS2) | (0<<ADPS1); // 250 kHz
23
ADCSRA |= (1<<ADSC); 
24
25
sei();
26
27
...

von Sinusgeek (Gast)


Lesenswert?

Der ADC soll mit 50kHz bis 200kHz getaktet werden.

Eine Wandlung in der schnellsten Betriebsart (im Free-Run-Mode ohne 
Quellenumschaltung) dauert 13 ADC-Takte

Das sind 65µs im günstigsten Fall.

Wenn ich es richtig verstanden habe (C ist nicht mein Ding) nutzt Du 
aber nicht den Free-Run-Mode, sondern den Auto-Trigger-Mode (per Timer), 
wodurch weitere Verzögerungen entstehen.

Zusätzlich schaltest Du die Messquelle um (ADMUX), das erfordert eine 
Erstmessung, die 26 ADC-Takte dauert oder (bei Free-Run) das Verwerfen 
des ersten Messwertes.

Was erwartest Du eigentlich, wenn Dir 30µs schon zuviel sind?

~

von spess53 (Gast)


Lesenswert?

Hi

>Wie erreicht man die im Datenblatt angegebenen 7µs?

Welches Datenblatt?

MfG Spess

von Michael U. (amiga)


Lesenswert?

Hallo,

ADC-Takt 250kHz sind bei mir 4µs pro Takt.
Eine Wandlung dauert 13 Takte macht also 52µs.
Da Du den ADC unsinnigerweise auch noch jedesmal erst einschaltest, 
braucht die Wandlung als erste Wandlung sogar 25 Takte, also 100µs.

Atmel gibt 13-260µs Wandlungszeit im Datenblatt an.
13µs ergibt dann aber höchstens noch 6-7 Bits nutzbare Auflösung.
Ich weiß also nicht so recht, wo Deine Werte herkommen.

Gruß aus Berlin
Michael

von Sinusgeek (Gast)


Lesenswert?

Das mit der Umschaltung der Mess-Quelle nehme ich zurück, da habe ich 
mich verguckt... - Sorry

~

von Funkenschlosser (Gast)


Lesenswert?

Das erste Beispiel war ein Schnellschuß. Ich habe den Wandler immer 
wieder aktiviert/deaktiviert. Jetzt mache ich es so, dass ich den 
ADC-Interrupt erst bei der steigender Flanke freischalte, kurz warte und 
dann den Wert hole. Der Wandler läuft dauernd.
1
ISR(TIMER1_OVF_vect) //steigende Flanke
2
{
3
   TCNT2 = 200; //Timer2 vorladen (Overflow bei 255)
4
   TIFR  |= (1<<TOV2); //alte Overflows löschen
5
   TIMSK |= (1<<TOIE2); //Timer2 Interrupt aktvieren
6
}
7
8
ISR(TIMER2_OVF_vect) //Overflow kommt ca. 5µs nach steigender PWM-Flanke
9
{
10
   PORTC |= (1<<PC0); //Zeit messen am Oszi
11
   ADCSRA|= (1<<ADIE); //AD-Wandler Interrupt aktivieren
12
   TIMSK &= ~(1<<TOIE2); //Timer2 Interrupt löschen, nicht mehr benötigt
13
}
14
15
ISR(ADC_vect)
16
{  
17
    UIST = ADCW;
18
    ADCSRA &=  ~(1<<ADIE); //AD-Overflow löschen, nicht mehr benötigt
19
    PORTC &= ~(1<<PC0); //Messung Ende
20
21
    berechnen = TRUE;
22
}
23
24
main()
25
{
26
 ....
27
 //Timer1-PWM 20 kHz = 50µs Periodendauer
28
29
 TCCR2 |= (1<<CS20); //Timer2 (8bit) mit CPU-Takt
30
31
 ADMUX = 4;                      // Kanal waehlen
32
 ADMUX |= (1<<REFS0); // interne Referenzspannung nutzen
33
 // ADC aktivieren, Teiler 64 -> 250 kHz, Free-Running
34
 ADCSRA |= (1<<ADEN)|(1<<ADATE)|(1<<ADSC)|(1<<ADPS2)|(0<<ADPS1); 
35
36
 ....
37
 //berechnen etc.
38
}

Ich bin jetzt bei gemessenen 12µs inkl. setzen der Flags. Das sieht 
schonmal besser aus, damit kann ich leben und das ist auch das was im 
Datenblatt steht (13µs). Allerdings sehe ich beim Debuggen, dass die 
AD-Werte noch wesentlich öfter kommen. Alle paar CPU-Takte steht ein 
neuer AD-Wert im ADC. Dann bezieht sich die Angabe im Datenblatt also 
auf die gesamte Zeit, bis man einen AD-Wert geholt hat und ihn in einer 
Variable speichert zur weiteren Verarbeitung? Die eigentlich 
Sample&Hold-Wandlung geht wohl wesentlich schneller als das Abholen der 
Werte aus dem Register? Eigentlich müsste es bei 250 kHz mindestens 4µs 
dauern? Das wäre ja ein AD-Wert pro 64 CPU-Takte.

@ Was erwartest Du eigentlich, wenn Dir 30µs schon zuviel sind?

Der Atmega ersetzt einen 9 Jahre alten HC12, bei dem die single 
conversion laut Oszi-Messung auch nicht mehr als 10µ dauert. Da habe ich 
vom Mega32 schon etwas mehr erwartet. Es muss hier sehr schnell gehen, 
da die PWM eine große Leistung schaltet und ich das Messen während den 
Schaltvorgängen vermeiden will.

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.