Forum: Mikrocontroller und Digitale Elektronik Atmel Xmega synchrone ADCs / Quantisierungs + Schwingungs Problem


von Avr N. (balze)


Angehängte Dateien:

Lesenswert?

Hallo zusammen,

ich habe mal wieder ein (Paar) Problem(e).

zuerst ein paar erklaerende Worte zu meinem Projekt:
Ich baue ein Indiziersystem fuer einen Motorenpruefstand.
Dieses System soll den Druck im Brennraum und den Hub der Nadel der 
Einspritzduese "winkelrichtig" messen.

Hierzu habe ich den ATXMega128A1 eingesetzt, der ueber das Eventsystem 
von einem Incrementalgeber der auf der Kurbelwelle sitzt getriggert 
wird. (4096 Inkremente pro Umdrehung).
Ueber den (im Eventsystem des XMega128A1vorhandenen) Quadraturencoder 
werden die beiden getrennten (nicht gemultiplexte) Analogeingaenge des 
XMega getriggert. Sie ziehen mit steigender Flanke des Inkrementalgebers 
(A-Signal) synchron die Messwerte des Druckes und des Nadelhubes ein.

Das ganze laeuft (leider, da DFLL nicht funktioniert) mit dem internen 
kalibrierten 32MHz RC-Oszillator

Hardwaremaessig ist der Analogteil so umgeetzt wie im Anhang zu erkennen 
(analog_teil.PNG).

Am analogen Eingang 1 haengt ein Ladungsverstaerker der Firma Kistler 
(Ausgangssignal +/- 10V).
Am Eingang 2 haengt ein Messverstaerker der Firma AVL, der ueber eine 
Oscillatorbox den Messwert des induktiven Nadelhubsensors misst 
(Ausgangssignal +/- 10V).

Der Analogkanal A ist schneller eingestellt als Kanal B.
Der Teiler fuer den ADC Clock A ist auf 64, der fuer ADC Clock B auf 128 
eingestellt.

Deshalb sollte der Interrupt fuer ADC B fertig erst kommen, wenn ADC A 
sicher fertig ist.

Ueber das Interrupt des ADC B wird dann die Datenuebertragung ueber USB 
(FTDI 2232H) gestartet. (Nicht in einer ISR, sondern per Polling auf das
I-Flag, weil der ISR Overhead zu viel Performance kosten wuerde.)


Jetzt zu meinen Problemen:

Problem 1 ( gross und fuer mich sehr wichtig)

Unter bestimmten (mir nicht klaren) Umstaenden habe ich auf dem 
Analogeingang 1 ein Quantisierungsproblem.
Die 4 LSBs gehen alle auf 1.
Ich habe dann nur noch 8 bit Aufloesung (und den Fehler der 4 LSBs fest 
auf 1)
Ist der AVL Messverstaerker ausgeschaltet ist dieses Problem nicht mehr 
vorhanden. (Siehe example_w_quant_prob.png und 
example_wo_quant_prob.png)
Ebenso koennen sich die Umstaende im Laufe der Zeit so aendern, dass ein 
Uebergang (der Anteil der Messwerte mit Quantisierungsfehler geht 
langsam von 100% auf 0% zurueck!) zu einer einwandfreien Messung 
stattfindet.

Ich wuerde mich SEHR (!) freuen, wenn hier jemand einen Hinweis haette 
dieses Problem zu beseitigen.

Problem 2 ( besorgniserregend aber eher nebensaechlich da fuktionierende 
Einstellung gefunden)

Es gibt offensichtlich ein Problem mit den 2 ADCs im Xmega128A1.
Ich habe eine Zeit lang mit dem ADC Timing "spielen" muessen, bis ich 
brauchbare Messwerte bekommen habe.

Dies funktioniert nur, wenn den ADC A mit 32MHz/64 und ADC B mit 
32MHz/128 betreibe.
Stelle ich dad ADC Timing anders ein, bekomme ich eine Schwinung auf 
wenigstems einen der ADC Kanaele. (siehe A_64_B128.png und 
A_64_B_64.png)
Die Frequenz und Amplitude unterscheidet sich auch zwischen zwei XMegas. 
Den genauen Zusammenhang habe ich aber aus Zeitgruenden nicht genauer 
dokumentiert.

Auch hier wuerde ich mich ueber eine Erklaerung freuen.

Im Anhang habe ich noch Ausschnitte aus meinen Sourcen angehaengt.

Vielen Dank, schoenen Gruss,

Balze aka AVR Noob

P.S.: Sourcenausschnitt aus main():
1
....
2
  EVSYS.CH4MUX = EVSYS_CHMUX_PORTD_PIN3_gc;
3
  EVSYS.CH4CTRL = EVSYS_DIGFILT_2SAMPLES_gc;
4
5
  ADCA.EVCTRL = (uint8_t) ADC_SWEEP_0_gc |
6
                ADC_EVSEL_4567_gc |
7
                ADC_EVACT_CH0_gc;
8
9
  ADCA.CTRLB = ( ADCA.CTRLB & ~ADC_RESOLUTION_gm ) |
10
               ADC_RESOLUTION_LEFT12BIT_gc | ADC_CONMODE_bm;
11
  ADCA.PRESCALER = ( ADCA.PRESCALER & ~ADC_PRESCALER_gm ) |
12
                   ADC_PRESCALER_DIV64_gc;
13
14
  ADCA.REFCTRL = ( ADCA.REFCTRL & ~ADC_REFSEL_gm ) |
15
                 ADC_REFSEL_AREFA_gc;
16
  ADCA.CTRLA |= ADC_ENABLE_bm;
17
18
  ADCA.CH0.MUXCTRL = (uint8_t) ADC_CH_MUXPOS_PIN2_gc | ADC_CH_MUXNEG_PIN1_gc;
19
20
  ADCA.CH0.CTRL = (ADCA.CH0.CTRL & (~(ADC_CH_INPUTMODE_gm|ADC_CH_GAINFAC_gm))) |  (uint8_t) ADC_CH_INPUTMODE_DIFF_gc;
21
22
  ADCB.EVCTRL = (uint8_t) ADC_SWEEP_0_gc |
23
                ADC_EVSEL_4567_gc |
24
                ADC_EVACT_CH0_gc;
25
26
  ADCB.CTRLB = ( ADCB.CTRLB & ~ADC_RESOLUTION_gm ) |
27
               ADC_RESOLUTION_12BIT_gc| ADC_CONMODE_bm;
28
29
  ADCB.PRESCALER = ( ADCB.PRESCALER & ~ADC_PRESCALER_gm ) |
30
                   ADC_PRESCALER_DIV128_gc;
31
  ADCB.CH0.INTCTRL = (ADC_CH_INTMODE_COMPLETE_gc | ADC_CH_INTLVL_MED_gc);
32
33
  ADCB.REFCTRL = ( ADCB.REFCTRL & ~ADC_REFSEL_gm ) |
34
                 ADC_REFSEL_AREFB_gc;
35
  ADCB.CTRLA |= ADC_ENABLE_bm;
36
37
  ADCB.CH0.MUXCTRL = (uint8_t) ADC_CH_MUXPOS_PIN2_gc | ADC_CH_MUXNEG_PIN1_gc;
38
39
  ADCB.CH0.CTRL = (ADCB.CH0.CTRL & (~(ADC_CH_INPUTMODE_gm|ADC_CH_GAINFAC_gm))) |  (uint8_t) ADC_CH_INPUTMODE_DIFF_gc;
40
41
for (;;) {
42
  while (!ADCB.INTFLAGS){
43
  }
44
45
  ADCB.INTFLAGS |= 0x01;
46
47
  PORTJ.OUT = TCC0.CNTL; // Zaehler der Inkremente low
48
  PORTH.OUT &= ~(PIN0_bm);
49
  PORTH.OUT |= (PIN0_bm);
50
51
  PORTJ.OUT = TCC0.CNTH; // Zaehler der Inkremente high
52
  PORTH.OUT &= ~(PIN0_bm);
53
  PORTH.OUT |= (PIN0_bm);
54
55
  PORTJ.OUT = ADCB.CH0RESL;
56
  PORTH.OUT &= ~(PIN0_bm);
57
  PORTH.OUT |= (PIN0_bm);
58
59
  PORTJ.OUT = ADCA.CH0RESL | ADCB.CH0RESH;
60
  PORTH.OUT &= ~(PIN0_bm);
61
  PORTH.OUT |= (PIN0_bm);
62
63
  PORTJ.OUT = ADCA.CH0RESH;
64
  PORTH.OUT &= ~(PIN0_bm);
65
  PORTH.OUT |= (PIN0_bm);
66
}

von Avr N. (balze)


Angehängte Dateien:

Lesenswert?

Hier der analoge Teil

von Avr N. (balze)


Lesenswert?

Nachtrag:

Ich habe zum Testen mal den AVL Messverstaerker gegen eine 
Festspannungsquelle (Kalibrator) getauscht.

Das Quantisierungsproblem tritt auf, wenn die Eingangsspannung des 2. 
ADC Stufe negative wird (das differentielle Signal ebenfalls negativ 
wird)

Ich bin fuer jeden Tipp dankbar.

MfG,

Balze aka AVR Noob

von Helmut (Gast)


Lesenswert?

Hallo Avr Noob,
Das ist mir aufgefallen:
Du hast ADC_RESOLUTION_LEFT12BIT_gc eingestellt. Ist das ein Versehen 
oder Absicht? Die 4 LSBs kannst Du dann wegschmeissen- oder Du schiebst 
nachträglich noch richtig. Dann hast Du Deine Referent auf external 
gestellt: ADC_REFSEL_AREFA_gc. Geht diese über 2V hinaus? Ich habe 1,8 V 
ext. Referenz eingestellt und bin mit dem Ergebnis zufrieden (siehe 
Errata, Rev H)

Gruß
Helmut

von Helmut (Gast)


Lesenswert?

Helmut schrieb:
> Hallo Avr Noob,
> Das ist mir aufgefallen:
> Du hast ADC_RESOLUTION_LEFT12BIT_gc eingestellt. Ist das ein Versehen
> oder Absicht? Die 4 LSBs kannst Du dann wegschmeissen- oder Du schiebst
> nachträglich noch richtig. Dann hast Du Deine Referenz auf external
> gestellt: ADC_REFSEL_AREFA_gc. Geht diese über 2V hinaus? Ich habe 1,8 V
> ext. Referenz eingestellt und bin mit dem Ergebnis zufrieden (siehe
> Errata, Rev H)
>
> Gruß
> Helmut

von Avr N. (balze)


Lesenswert?

Hallo Helmut,

danke fuer Dein Antwort.

Helmut schrieb:
> Hallo Avr Noob,
> Du hast ADC_RESOLUTION_LEFT12BIT_gc eingestellt. Ist das ein Versehen
> oder Absicht?

Das ist Absicht. Ich schreibe spaeter beide 12 Bit ADC Werte in 3 Bytes 
und habe die beiden Bytes mit nur 4 besetzten Bits verodert um sie 
gemeinsam senden zu koennen. (Das funktioniert auch wunderbar.) Ich muss 
diese Werte dann nur auf Host-Seite (PC-Software) wieder auseinander 
nehmen.
1
  ....
2
3
  PORTJ.OUT = ADCB.CH0RESL;
4
  PORTH.OUT &= ~(PIN0_bm);
5
  PORTH.OUT |= (PIN0_bm);
6
7
  PORTJ.OUT = ADCA.CH0RESL | ADCB.CH0RESH;
8
  PORTH.OUT &= ~(PIN0_bm);
9
  PORTH.OUT |= (PIN0_bm);
10
11
  PORTJ.OUT = ADCA.CH0RESH;
12
  PORTH.OUT &= ~(PIN0_bm);
13
  PORTH.OUT |= (PIN0_bm);
14
15
  ....

Helmut schrieb:
>  ...Dann hast Du Deine Referent auf external
> gestellt: ADC_REFSEL_AREFA_gc. Geht diese über 2V hinaus?

Nein, die Referenzspannung betraegt 1,024 V. (ISL60002-10 = 
Referenzspannungsquelle 1,024V)
Es funktioniert allerdings auch nicht mit VCC/1,6 als Referenzspannung 
(3,3V / 1,6 = 2,0625V).

Schoenen Gruss,

Balze aka AVR Noob

von Avr N. (balze)


Lesenswert?

Hallo zusammen,

ich habe meine Probleme beim Atmel Support beschrieben und die Loesung 
des ersten Problemes erhalten:

Avr Noob schrieb:
> Unter bestimmten (mir nicht klaren) Umstaenden habe ich auf dem
> Analogeingang 1 ein Quantisierungsproblem.
> Die 4 LSBs gehen alle auf 1.
> Ich habe dann nur noch 8 bit Aufloesung (und den Fehler der 4 LSBs fest
> auf 1)

Avr Noob schrieb:
> Das Quantisierungsproblem tritt auf, wenn die Eingangsspannung des 2.
> ADC Stufe negative wird (das differentielle Signal ebenfalls negativ
> wird)

Avr Noob schrieb:
1
> ....
2
> 
3
>   PORTJ.OUT = ADCB.CH0RESL;
4
>   PORTH.OUT &= ~(PIN0_bm);
5
>   PORTH.OUT |= (PIN0_bm);
6
> 
7
>   PORTJ.OUT = ADCA.CH0RESL | ADCB.CH0RESH;
8
>   PORTH.OUT &= ~(PIN0_bm);
9
>   PORTH.OUT |= (PIN0_bm);
10
> 
11
>   PORTJ.OUT = ADCA.CH0RESH;
12
>   PORTH.OUT &= ~(PIN0_bm);
13
>   PORTH.OUT |= (PIN0_bm);
14
> 
15
>   ....

Das Problem liegt (natuerlich :) bei mir. Was mir entgangen ist, steht 
im Datenblatt (doc8077.pdf) auf Seite 308 (Section 25.16.10.2)

Zitat:
"25.16.10.2 12-bit mode, right adjusted
 • Bits 7:4 - Reserved
      These bits will in practice be the extension of the sign bit
      CHRES11 when ADC works in differential mode and set to zero
      when ADC works in signed mode.
 • Bits 3:0 - CHRES[11:8]: ADC Channel Result, high byte
      These are the 4 MSB of the 12-bit ADC result."

Die 4 hoeherwertigen Bits (von CHnRESH) des rechtsbündigen ADC Wertes 
sind eine Kopie des Vorzeichens (was ja auch gut ist, um das Ergebnis 
als int16_t vorzeichenrichtig zu erhalten).

Damit schreibe ich mir natuerlich die 4 niederwertigen Bits des anderen 
ADCs kaputt:
1
PORTJ.OUT = ADCA.CH0RESL | ADCB.CH0RESH;

aendern in
1
PORTJ.OUT = ADCA.CH0RESL | (ADCB.CH0RESH & 0x0F);

sollte dieses Problem also loesen.

MfG,

Balze aka AVR Noob

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.