Forum: Mikrocontroller und Digitale Elektronik Free-Running and Compare Match A Auto-Triggering AD-Wandler


von Sebastian O. (sebas)


Angehängte Dateien:

Lesenswert?

Das Ziel meiner Applikation ist die Messung von analogen Werte durch den 
AD-Wandler. Deswegen habe ich die zwei folgende Möglichkeiten 
ausgewählt:

1) Aktivierung des AD-Wandlers mit Auto-Triggering. Als Trigger-Quelle 
wird der "COMPARE MATCH A" des Timers 0 verwendet. Damit die Flag für 
COMPARE MATCH A wieder für die Aktivierung des AD-Wandlers verwendet 
werden kann, wird diese Flag durch die Interrupt-Aufruf gelöst.

- Hier habe ich zwei Probleme: die Flag für COMPARE MATCH A (OCF0A) wird 
nur manchmal gesetzt und der AD-Wandler wird nie aktiviert (ADSC=0).


2) Aktivierung des AD-Wandlers mit Auto-Triggering. Als Trigger-Quelle 
wird "Free-Running" verwendet. Damit der AD-Wandler starten werden kann, 
wird das Bit ADSC des Registers ADCSRA gesetzt in der Initialisierung 
des AD-Wandlers.

-Hier habe ich folgendes Problem: nach der ersten Konvertierung (die zu 
meinem Zeit-Design auch nicht passt) wird die Interrupt-Flag des 
Interrupts gesetzt und der AD-Wandler wird nie wieder aktiviert, da das 
Bit ADSC gelöst wird.

Ich wäre sehr dankbar, wenn jemand mir einen Vorschlag geben könnte.

Anbei die zwei "main" Dateien.

Viele Grüße,

Sebas

von spess53 (Gast)


Lesenswert?

Hi

>Ich wäre sehr dankbar, wenn jemand mir einen Vorschlag geben könnte.

Für beide Fälle: ADC-Complete-Interrupt verwenden.

MfG Spess

von Rudi (Gast)


Lesenswert?

>die Flag

die Flag != dis Flag
die Flag wird geschrieben auch mit "k"  und is (war) Kanone.
dis Flag ist im englischen ein "Fähnchen"

;) nicht ernst, bitte

von Sebastian O. (sebas)


Lesenswert?

Hi,

danke für die Rückmeldungen.


> Für beide Fälle: ADC-Complete-Interrupt verwenden.

Sollte die Konvertierung nicht automatisch starten?

1) Auto-Triggering mit Compare Match A: die Konvertierung sollte mit der 
Interruptserzeugung des Timers gestartet werden.

2) Auto-Triggering mit Free-Running: nachdem der AD-Wandler einmal 
gestartet wird, sollte der AD-Wander frei and kontinuierlich laufen.


Warum sollte die ADC-Complet-Interrupt aufgerufen werden?


Viele Grüeße,

sebas

PS: sorry, aber ich lerne Deutsch nur seit 2 Jahre. Deswegen ist meine 
Sprache nicht ganz richtig.

von Karl H. (kbuchegg)


Lesenswert?

Sebastian O. schrieb:

> Ich wäre sehr dankbar, wenn jemand mir einen Vorschlag geben könnte.

Woher weißt du eigentlich so genau, welches Flag wann und warum nicht 
mehr gesetzt wird?
Ich rate mal: Aus dem Simulator

Dann lass dir gesagt sein, dass der Simulator so manches Problem hat und 
nicht alle Details des realen Chips korrekt nachbildet.

von spess53 (Gast)


Lesenswert?

Hi

>Warum sollte die ADC-Complet-Interrupt aufgerufen werden?

An irgend einer Stelle musst du den AD-Wert ja auslesen. Da bietet sich 
der Interrupt an. Und im 1.Fall kannst dort gleic das 
Timer-Interrupt-Flagzurück setzen.

MfG Spess

von Sebastian O. (sebas)


Lesenswert?

Hi,


> An irgend einer Stelle musst du den AD-Wert ja auslesen. Da bietet sich
> der Interrupt an. Und im 1.Fall kannst dort gleic das
> Timer-Interrupt-Flagzurück setzen.

in beiden Fälle wird die Interrupt-Routine nie aufgerufen, obwohl das 
Bit ADIE vom Register ADCSRA gesetzt wird. Das bedeutet, dass der 
AD-Wandler läuft überhaupt nicht, aber ich verstehe das nicht.


Grüße
sebas

von avion23 (Gast)


Lesenswert?

nicht lachen: sei() ?

Ich habe auch Probleme mit dem free running modus. Probier mal deine ISR 
ab zu specken, z.B. nur led togglen. Dann schauen, wie oft die led 
togglet.

Bei mir gibt es aktuell, dass der free running modus nur funktioniert, 
wenn ich jeden zweiten ADC-Wert verwerfe. Ich denke das liegt am channel 
wechsel (bei mir). Auch mal deaktiveren.

Wie debuggst du?

von Sebastian O. (sebas)


Angehängte Dateien:

Lesenswert?

Hi

> nicht lachen: sei() ?

im Code für die Auto-Triggering mit Compare Match A hatte ich es schon. 
Der Interrupt für ADC wird nie aufgerufen.

Mit Free-Running wird die Routine nicht aufgerufen, aber es wird ein 
Reset erzeugt. Wieso denn? Sollte ich der Watchdog Timer ausschalten?

> Bei mir gibt es aktuell, dass der free running modus nur funktioniert,
> wenn ich jeden zweiten ADC-Wert verwerfe. Ich denke das liegt am channel
> wechsel (bei mir). Auch mal deaktiveren.

Ich verwende immer den gleichen Kanal (ADC3), so verstehe ich auch 
nicht, warum ich werte verwerfen muss.


> Wie debuggst du?

Ich debbuge mit Debugging von AVR Studio 4. Zurzeit habe ich die 
Leiterplatte noch nicht fertig. Deswegen simuliere ich nur.

Grüße,

Sebastian

von spess53 (Gast)


Lesenswert?

Hi

>in beiden Fälle wird die Interrupt-Routine nie aufgerufen, obwohl das
>Bit ADIE vom Register ADCSRA gesetzt wird. Das bedeutet, dass der
>AD-Wandler läuft überhaupt nicht, aber ich verstehe das nicht.

Ein kleines Testprogramm (Assembler) mit Autotrigger durch Timer0 läuft 
bei mir im Simulator problemlos.

MfG Spess

von Sebastian O. (sebas)


Lesenswert?

Hi,


> Ein kleines Testprogramm (Assembler) mit Autotrigger durch Timer0 läuft
> bei mir im Simulator problemlos.


hast du mit meinem C-Code probiert?

Wäre es empfehlenswert, mit Assembler statt C zu programmieren?


Grüße,

Sebas

von spess53 (Gast)


Lesenswert?

Hi

>hast du mit meinem C-Code probiert?

Nein. Ich benutze kein C.

>Wäre es empfehlenswert, mit Assembler statt C zu programmieren?

Ehe grössere Dikussionen aufkommen: Nimm das, was du am besten kannst.

Bei dir hängt es allerdings nicht nur an der Programmiesprache.

MfG Spess

von avion23 (Gast)


Lesenswert?

1
ISR (ADC_vect)
2
{
3
  ADCSRA &= ~(1<<ADIF);
4
  PORTB &= ~(1<<PB0);
5
  result = ADCH;
6
}
Warum nicht ADC abfragen an Stelle von ADCH? Ärger vermeiden:
1
When ADCL is read, the ADC Data Register is not updated until ADCH is read.
2
Consequently, if the result is left adjusted and no more than 8-bit 
3
precision is required, it is sufficient to read
4
ADCH. Otherwise, ADCL must be read first, then ADCH.
 Datenblatt attiny25

Kommentar in deinem Code, nicht nachgeprüft:
1
 // Prescaler=8(FADC=1MHz)
f_adc_max = 200kHz.

Bei mir gibt es im Code auch noch ein ADCSC, bei dir nicht. Ohne 
funktioniert es nicht
1
In Single Conversion mode, write this bit to one to start each 
2
conversion. In Free Running mode, write this bit to one to start the first 
3
conversion


UND: Im Simulator funktioniert der ADC nicht. Habe ich nicht selbst 
überprüft, aber an x Stellen gelesen.

von spess53 (Gast)


Lesenswert?

Hi

>UND: Im Simulator funktioniert der ADC nicht. Habe ich nicht selbst
>überprüft, aber an x Stellen gelesen.

AVR Studio Hilfe:

Analog to Digital Converter (ADC)

Analog input is not supported. However, based on the ADC Prescaler 
Select bits (ADPS), the ADIF flag is set after the correct number of 
cycles. The ADC completion interrupt is also simulated correctly.
The ADC Data register (ADCH/ADCL) can be manually set e.g in the I/O 
view.

Zum Simulieren langt es. Im Simulator2 kannst du sogar über ein 
Stimuli-File ADCL/H auf bestimmte Werte setzen.

MfG Spess

von Sebastian O. (sebas)


Lesenswert?

Hi
> Warum nicht ADC abfragen an Stelle von ADCH? Ärger vermeiden:

Weil es nur für meine Applikation notwendig ist. Wichtig ist es nur, ob 
der Eigang die Spannungsreferenz erreicht hat.


> Kommentar in deinem Code, nicht nachgeprüft:
>
1
 // Prescaler=8(FADC=1MHz)
> f_adc_max = 200kHz.

Es wird auch gesagt, dass für niedrige Auflösung eine Frequenz bis 1 MHz 
vewerdet werden kann.

> Bei mir gibt es im Code auch noch ein ADCSC, bei dir nicht. Ohne
> funktioniert es nicht
>
1
In Single Conversion mode, write this bit to one to start each
2
> conversion. In Free Running mode, write this bit to one to start the
3
> first
4
> conversion
>

In meinem Code wird folgendes geschrieben:
ADCSRA |= (1<<ADSC);
    // Start the conversion


Sorry, aber ich weiss nicht, was ich noch prüfen kann. Gibt es noch eine 
Stelle, die geprüft werden müsste?

Danke.

von avion23 (Gast)


Lesenswert?

Hallo Sebastian,
in deinem zweiten Code Abschnitt wird der ADC nicht gestartet. Darauf 
habe ich mich bezogen.

Was du noch tun kannst:
Ganz allgemein alle Fehlerquellen ausschalten. Also erstmal den normalen 
Modus an's laufen bringen, dann Dinge wie f = 1MHz testen. Am Ende Code 
der bei mir läuft, vielleicht hilft dir das.

@spess
Danke, wusste ich nicht. Ich habe bis jetzt nur gegenteiliges gehört.


1
void initADC() {
2
  // ADC Multiplexer Selection Register
3
  ADMUX = 0; // Reset ADMUX
4
5
  // 110 = internal 2.56V reference
6
  // 010 = internal 1.1V reference
7
  // X00 = Vcc as reference
8
  //ADMUX |= (1<<REFS2);
9
  ADMUX |= (1 << REFS1);
10
  //ADMUX |= (1<<REFS0);
11
  //ADMUX = (1<<ADLAR);             // left adjustment for adc results
12
13
14
  // ADC Control and Status Register A
15
  uint8_t ADCSRA_temp = 0;
16
  ADCSRA_temp |= (1 << ADEN); // Enables ADC
17
  ADCSRA_temp |= (1 << ADSC); // Start Conversion is enabled
18
  ADCSRA_temp |= (1 << ADATE); // auto trigger enable
19
  //ADCSRA_temp |= (1 << ADIF); // ADC interrupt flag
20
  ADCSRA_temp |= (1 << ADIE); // ADC Interrupt enable
21
  ADCSRA_temp |= (1 << ADPS2);
22
  ADCSRA_temp |= (1 << ADPS1); // Set ADC Prescaler to 64
23
  ADCSRA_temp |= (1 << ADPS0);
24
  ADCSRA = ADCSRA_temp;
25
26
  // ADC Control and Status Register B
27
  ADCSRB = 0;
28
  //ADCSRB |= (1<<BIN);      // defines bipolar mode. only useful for differential mode
29
  //ADCSRB |= (1<<IPR);        // input polarity reversal mode.
30
  //ADCSRB |= (1<<ADTS2);      // Auto trigger source. 000 = free running
31
  //ADCSRB |= (1<<ADTS1);
32
  //ADCSRB |= (1<<ADTS0);
33
} // end initADC()
34
35
// 1111 = temperature on attiny25
36
// Turns on Single Channel Measurement
37
inline void setADC(unsigned char channel) {
38
  ADMUX &= ~(1 << MUX3) & ~(1 << MUX2) & ~(1 << MUX1) & ~(1 << MUX0); // Set all ADC Channel bits to 0
39
  ADMUX |= (channel & 0x0f); // sets the bits again,
40
}
41
42
ISR(ADC_vect){
43
44
}

von Sebastian O. (sebas)


Lesenswert?

Hi,

na ja, meine Einstellungen sind gleich.

Ich werde nochmal alles prüfen.

Vielen Dank.

sebas

von Sebastian O. (sebas)


Angehängte Dateien:

Lesenswert?

Hi,

ich habe nochmal den Code für Free-Running Funktion angeschaut. Die 
Interrupt-Routine wird angerufen, aber das Bist ADSC wird nicht mehr 
gesetzt. Ich habe probiert, das Bit ADSC manuell zu setzen. In diesem 
Fall läuft der AD-Wander mit falscher Free-Running Funktion, weil 
manuell das Bit setzten muss. In diesem Fall würde ich Single Conversion 
Mode verwenden, da die gleiche Funktionalität hat.

Grüsse,

sebas

von spess53 (Gast)


Angehängte Dateien:

Lesenswert?

Hi

>Die Interrupt-Routine wird angerufen, aber das Bist ADSC wird nicht mehr
>gesetzt.

Warum auch? Wird nur für die erste Wandlung gebraucht.

>Ich habe probiert, das Bit ADSC manuell zu setzen. In diesem
>Fall läuft der AD-Wander mit falscher Free-Running Funktion, weil
>manuell das Bit setzten muss. In diesem Fall würde ich Single Conversion
>Mode verwenden, da die gleiche Funktionalität hat.

Ich habe es auch probiert. Das angehängte läuft wunderbar im Simulator2.

MfG Spess

von Sebastian O. (sebas)


Angehängte Dateien:

Lesenswert?

Hi,

ich habe die zwei Coden mit Simulator2 und die Interrupt-Routine des 
AD-Wandlers wird aufgerufen. Das bedeute, dass die Konvertierung gemacht 
wird. Trotzdem bleibt das Bit ADSC gelöst. Wie kann das möglich sein?

Grüsse,

sebas

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.