Forum: Mikrocontroller und Digitale Elektronik ADC sehr ungenau


von Benjamin G. (benjamin95)


Angehängte Dateien:

Lesenswert?

Hallo!

Ich habe Probleme mit dem ADC vom STM32L476 µC. Ich habe eine PCP 
entworfen und will die Spannung an einem Pin mithilfe des ADCs messen. 
Dazu verwende ich den ADC1 mit 12bit Auflösung in DMA mode. Lege ich den 
Pin auf Ground, liefert mir der ADC einen Wert von 500 (von max. 4095). 
Lege ich 3.3V an, was auch die Spannung am VREF+ Pin entspricht, bekomme 
ich 3578 (also auch nicht das Maximum). Es scheint als würde ein sehr 
großer Offsetfehler von 500 und eine sehr starke nichtlinearität 
vorhanden sein. Wisst ihr wo der Fehler liegen kann. Schaltplan und Code 
im folgendem bzw. angehängt. (ANALOG_IN2 ist der eingangspin zum ADC, 
SENSOR_CONTROL2 ist zur zu und abschalten der Spannungsversorgung an 
einem angeschlossenem Sensor)

Mit dem Multimeter hab ich den Pin natürlich gemessen und die Spannungen 
passen!

PS: Sonst funktioniert alles einwandfrei (GPIO, UART, ...).

Code zur configuration des ADCS (mithilfe von CubeMX erstellt)

static void MX_ADC1_Init(void)
{

  ADC_MultiModeTypeDef multimode;
  ADC_ChannelConfTypeDef sConfig;

    /**Common config
    */
  hadc1.Instance = ADC1;
  hadc1.Init.ClockPrescaler = ADC_CLOCK_ASYNC_DIV12;
  hadc1.Init.Resolution = ADC_RESOLUTION_12B;
  hadc1.Init.DataAlign = ADC_DATAALIGN_RIGHT;
  hadc1.Init.ScanConvMode = ADC_SCAN_ENABLE;
  hadc1.Init.EOCSelection = ADC_EOC_SEQ_CONV;
  hadc1.Init.LowPowerAutoWait = DISABLE;
  hadc1.Init.ContinuousConvMode = ENABLE;
  hadc1.Init.NbrOfConversion = 2;
  hadc1.Init.DiscontinuousConvMode = DISABLE;
  hadc1.Init.NbrOfDiscConversion = 1;
  hadc1.Init.ExternalTrigConv = ADC_SOFTWARE_START;
  hadc1.Init.ExternalTrigConvEdge = ADC_EXTERNALTRIGCONVEDGE_NONE;
  hadc1.Init.DMAContinuousRequests = ENABLE;
  hadc1.Init.Overrun = ADC_OVR_DATA_PRESERVED;
  hadc1.Init.OversamplingMode = DISABLE;
  if (HAL_ADC_Init(&hadc1) != HAL_OK)
  {
    _Error_Handler(_FILE_, _LINE_);
  }

    /**Configure the ADC multi-mode
    */
  multimode.Mode = ADC_MODE_INDEPENDENT;
  if (HAL_ADCEx_MultiModeConfigChannel(&hadc1, &multimode) != HAL_OK)
  {
    _Error_Handler(_FILE_, _LINE_);
  }

    /**Configure Regular Channel
    */
  sConfig.Channel = ADC_CHANNEL_15;
  sConfig.Rank = ADC_REGULAR_RANK_1;
  sConfig.SamplingTime = ADC_SAMPLETIME_640CYCLES_5;
  sConfig.SingleDiff = ADC_SINGLE_ENDED;
  sConfig.OffsetNumber = ADC_OFFSET_1;
  sConfig.Offset = 0;
  if (HAL_ADC_ConfigChannel(&hadc1, &sConfig) != HAL_OK)
  {
    _Error_Handler(_FILE_, _LINE_);
  }

    /**Configure Regular Channel
    */
  sConfig.Channel = ADC_CHANNEL_16;
  sConfig.Rank = ADC_REGULAR_RANK_2;
  sConfig.OffsetNumber = ADC_OFFSET_2;
  if (HAL_ADC_ConfigChannel(&hadc1, &sConfig) != HAL_OK)
  {
    _Error_Handler(_FILE_, _LINE_);
  }

}


Vielen Dank für eure Hilfe :)

: Bearbeitet durch User
von Roland E. (roland0815)


Lesenswert?

Diode verpolt eingebaut?

von A. S. (Gast)


Lesenswert?

relevant (und unkritisch) sind nur die 100R und die Diode.

Benjamin G. schrieb:
> Mit dem Multimeter hab ich den Pin natürlich gemessen und die Spannungen
> passen!

Wo zwischen genau? Der Teil fehlt vollkommen.

von Possetitjel (Gast)


Lesenswert?

Benjamin G. schrieb:

> eine PCP entworfen

VUA

von Harlekin (Gast)


Lesenswert?

Wie sind Vref-, Vref+, VSSA und VDDA beschalten?
Spannung zwischen den Pins Vref- und Vref+ sowie VSSA und VDDA prüfen.

von Harlekin (Gast)


Lesenswert?

Den Code habe ich jetzt nicht studiert. Wie verhalten sich mehrere 
Messwerte nacheinander?

von Harlekin (Gast)


Lesenswert?

Wo im Code wird Vref gewählt?

/The internal voltage reference buffer supports two voltages:
• 2.048 V
• 2.5 V
An external voltage reference can be provided through the VREF+ pin when 
the internal voltage reference buffer is off.
The VREF+ pin is double-bonded with VDDA on some packages. In these 
packages the internal voltage reference buffer is not available./

von Matthias S. (Firma: matzetronics) (mschoeldgen)


Lesenswert?

Ich sehe an der Sensorversorgung keinerlei Siebmittel, sondern eher was, 
was die Versorgung schlechter (hochohmiger) macht, nämlich einen MOSFet. 
Es wäre also evtl. sinnvoll, die Versorgung abzublocken.

von M.Edy (Gast)


Lesenswert?

Benjamin G. schrieb:
> Ich habe eine PCP entworfen ...

Alles klar
https://www.urbandictionary.com/define.php?term=PCP

von Andreas S. (igel1)


Lesenswert?

Ohne Code und Schaltplan genau gesichtet zu haben, hier nur ein Hinweis:

Es gibt eine Menge "Application Notes" von ST zum Thema ADC-Genauigkeit.
Ich habe mir z.B. folgende abgespeichert (Filenamen sind von mir frei 
gewählt - Du erkennt an den Namen aber, wonach Du suchen musst):

AN4073.Improve_ADC_accuracy_STM32F2xx_STM32F4xx.pdf
AN3116.STM32s ADC modes.pdf
AN2834.ADC_accuracy_in_STM32Fx_and_STM32L1_series.pdf
AN1636.Understanding_and_Minimising_ADC_Conversion_Errors.pdf

Viele Grüße

Igel1

von ADC Freund (Gast)


Lesenswert?

klingt so, als würdest du das Signal auf den falschen Kanal legen und 
lediglich das Übersprechen messen. Wenn der eigentliche Messkanal 
floatend ist, misst der so in etwa das was der falsche Kanal am Eingang 
liegen hat.

Beitrag #5399381 wurde vom Autor gelöscht.
von Benjamin G. (benjamin95)


Lesenswert?

OK also:

Diode ist richtig drinnen

Die Spannung habe ich jetzt noch einmal direkt am Pin gemessen. Wenn ich 
den Sensor auf GND hänge, liegen am Pin 0,077 V an. Wenn ich ihn auf VCC 
(3,23 V hänge) liegen 3,1 V an. Also nicht wirklich ideal! Aber das 
erklärt noch immer nicht die große Ungenauigkeit.  Vref-, Vref+, VSSA 
und VDDA sind laut dem Datenblatt des µCs beschalten. Also Vref- auf 
GND, Vref+ auf VCC. VSSA auf GND und VDDA über eine Induktivität von VCC 
entkoppelt verbunden.

VREF+ wird doch automatisch als Referenzspannung für den ADC verwendet. 
Also im user Manual habe ich nichts gefunden.

Auch wenn ich die Versorgung des Sensors weglasse, bekomme ich ungenaue 
Werte.

Die Pins sind richtig verbunden, also ich messe mit dem ADC nicht das 
Übersprechen.

Mehrere Messwerte hintereinander ergeben immer das gleiche Ergebnis.

PS: PCB.... nicht PCP ^^

von A. S. (Gast)


Lesenswert?

Benjamin G. schrieb:
> Die Spannung habe ich jetzt noch einmal direkt am Pin gemessen.

was ist mit "Pin" gemeint? Ich hoffe, der AD-Eingangs-Pin am 
µController? Dann bleibt der zweite Teil der Frage weiterhin offen:

Achim S. schrieb:
> Wo zwischen genau? Der Teil fehlt vollkommen.

Messe mal wirklich (bei 0V) genau zwischen dem AD-Eingangs-Pin und dem 
GND-Ref-Pin.

Gegen VCC entsprechend gegen den HIGH-REF-Pin.

von Benjamin G. (benjamin95)


Lesenswert?

Ja natürlich der Analog eingangspin des ADCs!

Also die Spannung zwischen deim Eingangspin und dem VREF- beträgt 0,05V. 
Ich bekomme jedoch einen Digitalwert von 543 (bei 12 bit Auflösung). 
Wenn ich den Sensor auf GND schalte.

Wenn ich den Eingang auf VCC schalte, hab ich eine Spannung von -0,163 V 
zwischen dem Pin und VREF+ (also VREF+ ist um 0,163V höher als der 
Eingangspin des ADCs) Der Digitalwert beträgt dabei 3634.

von Peter S. (Gast)


Lesenswert?

Hat das S&H-Glied des ADCs denn genug Zeit, um sich auf die 
Eingangsspannung aufzuladen? So ein ADC multiplext in der Regel ja 
mehrere Eingänge auf ein S&H-Glied und wenn man zu schnell zwischen den 
Eingängen umschaltet hängt die Spannung, die am Ende rauskommt, auch 
irgendwie davon ab, was an den anderen Eingängen anliegt.

von Harlekin (Gast)


Lesenswert?

Harlekin schrieb:
> An external voltage reference can be provided through the VREF+ pin when
> the internal voltage reference buffer is off.

http://www.st.com/resource/en/reference_manual/dm00083560.pdf
Seite 680f Kapitel 21 Voltage reference buffer (VREFBUF)

Register VREFBUF_CSR: Der Default-Wert ist extern, somit müsste es 
eigentlich passen.

Benjamin G. schrieb:
> 0,05V. Ich bekomme jedoch einen Digitalwert von 543
(4.8)
> 3.067V 3634
(301)

Ich habe das Datenblatt noch nicht verstanden: könnte wegen der 
Kalibriermöglichkeit ein Faktor 10 enthalten sein?

von Harlekin (Gast)


Lesenswert?

Das Kalibrieren ist in folgendem Kapitel beschrieben:
18.4.8 Calibration (ADCAL, ADCALDIF, ADCx_CALFACT) auf Seite 515

von Benjamin G. (benjamin95)


Lesenswert?

Update.

Eine Kalibrierung habe ich laut reference Manual durchgeführt. Ich habe 
jetzt eine identische zweite Platine angefertigt. Bei der funktioniert 
der ADC mit dem exakt gleichem Programm perfekt. Ich habe aber die 
komplett gleiche Schaltung aufgebaut und mehrmals kontrolliert.

Mir ist jedoch aufgefallen, dass bei der Platine bei welcher der ADC 
nicht funktioniert zwischen dem µC ADC Eingangs PIN und dem Pin des 
Steckers welcher mit dem Eingangs PIN des ADCs über einen 100 Ohm 
Widerstand (R40) und einer Diode (D2) gegen Ground verbunden ist(siehe 
Schaltplan oben), eine Spannung von 0,051 V herrscht, wenn der 
Eingangspin mit Ground verbunden ist. Dies ist bei der anderen Platine 
nicht der Fall.

Meine Idee war nun, dass ein Strom aus dem Eingangspin des ADCs 
rausfließt und einen Spannungsabfall am Widerstand verursacht. Dieser 
Gedanke hat sich durch Messen auch Bestätigt! Es fließt ein Strom von 
0,6 mA über den 100 Ohm Widerstand nach Ground. Dies erklärt schon 
einmal die Spannungsdifferenz. Mir ist aber nicht bewusst, warum dort 
ein Strom fließt?  Der Pin ist eindeutig richtig konfiguriert (bei der 
andern Platine funktioniert das Programm ja). Kann es sein, dass der µC 
kaputt ist? (beim Einlöten etwas beschädigt, oder so)

PS: Bei der anderen Platine fließt dort kein Strom!

Eure Meinungen dazu würden mich interessieren!

LG Benjamin

von Sven B. (scummos)


Lesenswert?

Klingt nach ESD-Schaden. Controller wegwerfen und neuen einbauen. 
Passiert.

von Stefan F. (Gast)


Lesenswert?

Sehe ich auch so. Der Eingang ist wohl defekt.

von Benjamin G. (benjamin95)


Lesenswert?

Ja klingt logisch!

Hab den µC ausgetauscht und es funktioniert!

Danke euch :)

: Bearbeitet durch User
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.