Forum: Mikrocontroller und Digitale Elektronik ADC vom ADuCM362 nutzt nicht volle Auflösung


von Florian O. (iseh)


Lesenswert?

Hallo,
ich habe den ADuCM362 so programmiert, dass der interne DAC 1,2V ausgibt 
und diese Spannung am ADC-pin AIN0 wieder eingelesen wird (anliegende 
Spannung mit Messgerät kontrolliert).
Im Datenblatt 
https://www.analog.com/media/en/technical-documentation/user-guides/aducm362-363-hardware-reference-manual-ug-1048.pdf 
auf Seite 33 ist die Formel zum Umrechnen der ADC-Werte in eine Spannung 
angegeben: V = Vref / 2^28 * ADCxDAT.
Die interne Vref ist auf 1,2V eingestellt, der Gain ist auf 1 
eingestellt, die Ausgabewerte sollen "unsigned" sein.

Die Spannung 1,2V an AIN0 ergibt laut Debugger den ADC-Wert ~5577120, 
was sich mit der o.g. Formel zu 0,0249V errechnet.
Meine Erwartung ist, dass der ADC-Wert viel größer sein müsste, um mit 
der Formel wieder auf 1,2V zu kommen. Was könnte das Problem sein?


Detaillierte ADC-Einstellungen im Code:
1
// Mask in dividual ADC interupt flags
2
AdcMski (
3
pADI_ADC1, // Port
4
ADCMSKI_RDY, // mask ready interrupt
5
1); // write masks then read ADCnMSKI
6
7
// Set filter details
8
AdcFlt (
9
pADI_ADC1, // Port
10
125, // sinc decimation factor
11
0, // averaging factor
12
FLT_NORMAL); // no extra filter
13
14
// Set ADC measurement range
15
AdcRng (
16
pADI_ADC1, // Port
17
ADCCON_ADCREF_INTREF, // use internal reference (1.2V)
18
ADCMDE_PGA_G1, // gain of 1
19
ADCCON_ADCCODE_UINT); // truncate negative values to 0
20
21
// Configure ADC buffers
22
AdcBuf (
23
pADI_ADC1, // Port
24
ADCCFG_EXTBUF_OFF, // both external reference buffers powered down
25
ADCCON_BUFBYPN|ADCCON_BUFBYPP|ADCCON_BUFPOWP|ADCCON_BUFPOWN); // bypass negative/positive reference buffer, power down positive/negative reference buffer
26
27
// pin configuration
28
AdcPin (
29
pADI_ADC1, // Port
30
ADCCON_ADCCN_AIN1, // AIN1 as negative input
31
ADCCON_ADCCP_AIN0); // AIN0 as positive input

Vielen Dank für Eure Hilfe!

von Schwierig (ruelps)


Lesenswert?

Da fehlt noch einiges Code.

Warum da jetzt bei 24 Bit mit 2^28 gerechnet wird, erschließt sich mir 
spontan auch nicht.

von Stefan K. (stk)


Lesenswert?

Florian O. schrieb:
> ich habe den ADuCM362 so programmiert, dass der interne DAC 1,2V ausgibt
> und diese Spannung am ADC-pin AIN0 wieder eingelesen wird (anliegende
> Spannung mit Messgerät kontrolliert).

Auf welchem Potential liegt AIN1?

von K. H. (hegy)


Lesenswert?

Florian O. schrieb:
> auf Seite 33 ist die Formel zum Umrechnen der ADC-Werte in eine Spannung
> angegeben: V = Vref / 2^28 * ADCxDAT.
> Die interne Vref ist auf 1,2V eingestellt, der Gain ist auf 1
> eingestellt, die Ausgabewerte sollen "unsigned" sein.
>
> Die Spannung 1,2V an AIN0 ergibt laut Debugger den ADC-Wert ~5577120,
> was sich mit der o.g. Formel zu 0,0249V errechnet.

Im PDF steht in der drittletzten Zeile dies:

> Although the ADC is nominally 24 bits, [...], resulting in a useful
> signal range of ±1.2 V to 1.05 μV, which equates to approximately 2,285,000:1,
> or 21 bits. The result is placed in Bits[27:7] of ADCxDAT.

Bits[27:7] = ADC Wert = 21 Bits.

Das heißt, du musst noch Bits schieben.

Florian O. schrieb:
> der Gain ist auf 1 eingestellt

Auf S. 34 steht ganz oben, was die anderen Bits im 32-Bit Register 
bedeuten.
Bit[0:3] = 0 (Bit 0...6 würde ich es aus der Grafik so interpretieren.)
Bit[4:6] = noise
Bit[7:27] = Data
Bit[28:31] = Sign

Vermutlich ist der 24-Bit ADC-Wert in Bit[4:27], wobei die untersten 3 
Bit nur Rauschen ist und nichts aussagen.

Je nach Verstärkungsfaktor verschiebt sich auch der Speicherbereich und 
auch die Bitlänge des ADC-Wertes.

: Bearbeitet durch User
von Florian O. (iseh)


Lesenswert?

Stefan K. schrieb:
> Florian O. schrieb:
>> ich habe den ADuCM362 so programmiert, dass der interne DAC 1,2V ausgibt
>> und diese Spannung am ADC-pin AIN0 wieder eingelesen wird (anliegende
>> Spannung mit Messgerät kontrolliert).
>
> Auf welchem Potential liegt AIN1?

Hallo Stefan,

AIN1 liegt auf GND.

von Florian O. (iseh)


Lesenswert?

K. H. schrieb:
> Florian O. schrieb:
>> auf Seite 33 ist die Formel zum Umrechnen der ADC-Werte in eine Spannung
>> angegeben: V = Vref / 2^28 * ADCxDAT.
>> Die interne Vref ist auf 1,2V eingestellt, der Gain ist auf 1
>> eingestellt, die Ausgabewerte sollen "unsigned" sein.
>>
>> Die Spannung 1,2V an AIN0 ergibt laut Debugger den ADC-Wert ~5577120,
>> was sich mit der o.g. Formel zu 0,0249V errechnet.
>
> Im PDF steht in der drittletzten Zeile dies:
>
>> Although the ADC is nominally 24 bits, [...], resulting in a useful
>> signal range of ±1.2 V to 1.05 μV, which equates to approximately 2,285,000:1,
>> or 21 bits. The result is placed in Bits[27:7] of ADCxDAT.
>
> Bits[27:7] = ADC Wert = 21 Bits.
>
> Das heißt, du musst noch Bits schieben.
>
> Florian O. schrieb:
>> der Gain ist auf 1 eingestellt
>
> Auf S. 34 steht ganz oben, was die anderen Bits im 32-Bit Register
> bedeuten.
> Bit[0:3] = 0 (Bit 0...6 würde ich es aus der Grafik so interpretieren.)
> Bit[4:6] = noise
> Bit[7:27] = Data
> Bit[28:31] = Sign
>
> Vermutlich ist der 24-Bit ADC-Wert in Bit[4:27], wobei die untersten 3
> Bit nur Rauschen ist und nichts aussagen.
>
> Je nach Verstärkungsfaktor verschiebt sich auch der Speicherbereich und
> auch die Bitlänge des ADC-Wertes.

Hallo,

vielen Dank für Dein Feedback.
Die anderen Seiten im Datenblatt habe ich mit Kopfzerbrechen auch 
durchgeschaut. Es steht aber trotzdem klar drin: "The ADCxDAT register 
output format allows the user to easily calculate the voltage measured 
by the ADC". Die Formel dazu habe ich oben erwähnt, warum also sollte 
man trotzdem anfangen müssen, an dem ADC-Wert rumzuwerkeln? Ich verstehe 
Deinen Gedanken, vor allem mit Sicht auf Seite 34. Aber was kann ich 
jetzt ändern? Wenn ich an der Formel einige Bits runtergehe (2^24, 2^21) 
passt das Ergebnis nicht. Wenn ich am ADC-Wert Bits wegnehme, wird der 
Wert ja noch kleiner...

Die ADC-Read-Funktion sieht übrigens so aus:
1
/**
2
   @brief int32_t AdcRd(ADI_ADC_TypeDef *pPort)
3
         ==========Reads the ADC status.
4
   @param pPort :{pADI_ADC0, pADI_ADC1}
5
      - pADI_ADC0 for ADC0.
6
      - pADI_ADC1 for ADC1.
7
   @return ADC data (ADCxDAT).  MSb of data is bit 27.  Bits 28 to 31
8
      give extended sign.  \n
9
      Value of 0x0fffffff => VRef.  \n
10
      Value of 0x00000000 => 0V.    \n
11
      Value of 0xF0000000 => -Vref. \n
12
   @warning Returns ADCxDAT even if it does not contain new data.
13
**/
14
15
16
int32_t AdcRd(ADI_ADC_TypeDef *pPort)
17
{
18
   return pPort->DAT;
19
}

Das bedeutet, mit meinen 1,2V (=Vref) an AIN0, müsste ich vom ADC einen 
Wert in der Nähe von 0x0fffffff bekommen?

von K. H. (hegy)


Lesenswert?

Florian O. schrieb:
> Es steht aber trotzdem klar drin: "The ADCxDAT register
> output format allows the user to easily calculate the voltage measured
> by the ADC".

Das steht doch immer drin, denn so'n PDF ist ja auch ein Werbeblatt. Die 
Konkurrenz liest mit.

Florian O. schrieb:
> Die Formel dazu habe ich oben erwähnt, warum also sollte
> man trotzdem anfangen müssen, an dem ADC-Wert rumzuwerkeln?

Dann macht das wohl die Funktion AdcRd() bzw. deren Subfunktionen.

Florian O. schrieb:
> Wenn ich an der Formel einige Bits runtergehe (2^24, 2^21)
> passt das Ergebnis nicht.

Du sollst nicht mit den Bits runtergehen, sondern ausblenden bzw. nur 
die ADC-Werte Bits nehmen und dann entsprechend shiften, also von [27:4] 
nach [23:0] schieben und dann die untersten 3 Bits vernachlässigen 
(noise) =>
[23:0] &= 0x7FFFF8 (wenn ich mich nicht verzählt habe). Das wird wohl 
die AdcRd()-Funktion machen. Vllt. mal mim Debugger reinspringen und 
ankucken.

Florian O. schrieb:
> ich habe den ADuCM362 so programmiert, dass der interne DAC 1,2V ausgibt
> und diese Spannung am ADC-pin AIN0 wieder eingelesen wird (anliegende
> Spannung mit Messgerät kontrolliert).

I.d.R. ist es so, dass wenn der ADC sampled, der Eingangswiderstand des 
ADC klein wird (ein paar hundert Ohm bis ein paar kOhm) und dann die 
Spannung am ADC-Eingang zusammenbricht. Das sieht man mit einem Scope 
aber nicht mit einem Messgerät. Von daher ist es immer sinnvoll, einen 
Buffer vor dem ADC-Eingang zu schalten bzw. den eingebauten zu 
aktivieren.
Vllt. mal mim Debugger bis kurz vor AdcRD()-Fkt. durchlaufen und dann 
Step by Step über die AdcRD() laufen und mim Scope mal kucken, wie dann 
die Spannung am Eingang AIN0 sich verhält. Möglicherweise siehst du dann 
einen kurzen Einbruch.

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.