Forum: Mikrocontroller und Digitale Elektronik STM32 ADC Ungenauigkeit


von Johnny S. (sgt_johnny)


Lesenswert?

Hi,

Ich habe folgende Werte mit einem Multimeter U1273A gemessen:

Referenzeingang Vref STM32 = 2.997x V
Analogpin Eingang = 1.864x V

Die Spannungens sind sehr stabil, und auch beim Debug des ADC schwanken 
die Werte nur auf der hintersten Ziffer.

Der Maximalwert des ADC ist 4096.


Die gemessenen 1.864V sind 0.621 von 2.997

Somit 4096 * 0.621 = 2543

Der ADC Wert müsste also in diesem Fall um die 2550 liefern. In der 
Realität schwankt er um 2750..2770 herum

Wäre der Wert 2543 und man rechnet zurück, erhält man logischerweise 
1.86V

nimmt man die 2750 erhält man über 2V. Somit rund 150mv daneben, das 
sind rund 5% von der Referenz aus gesehen.

Ist es normal das der ADC um 5% daneben ist?

von HGast (Gast)


Lesenswert?

Hallo,

zeig doch mal bitte Deinen Schaltplan und Dein Layout. Hast Du eventuell 
einen Masseversatz? Wohin hast Du mit dem Multimeter gemessen, also wo 
hast Du den GND vom Multimeter angeschlossen?
Eventuell kannst Du auch mal die Spannung mit dem Oszi messen, denn es 
könnte ja ein Rauschen/Störsignal darauf sein....

von Bernd K. (prof7bit)


Lesenswert?

Ich hab schon lustige Effekte erlebt (der lustigste waren 8 
Treppenstufen die sogar am Eingangspin gemessen werden konnten) wenn

* ADC-Takt zu hoch
* Samplezeit zu kurz
* Impedanz zu hoch

von Alex D. (daum)


Lesenswert?

Bernd K. schrieb:
> * ADC-Takt zu hoch
> * Samplezeit zu kurz
> * Impedanz zu hoch

Das kann ich nur bestätigen. Ich hatte mal einen Fehler in der ADC 
Konfiguration eines STM32, der mehrere Kanäle misst. Einer der Kanäle 
war auf eine zu kurze Samplezeit eingestellt und hatte dadurch auch 
einen Fehler von ca 200mV. µC war ein STM32F303RE mit 72MHz ADC Takt.

von Johnny S. (sgt_johnny)


Lesenswert?

Einen "Schaltplan" gibt es in dieser Form nicht, ich habe auf ein Nucleo 
Board einen Lochraster gelötet und dort die Referenz sowie einen 
Spannungsteiler gesetzt. Gemessen habe ich jedoch direkt an den Pins vom 
MCU

Einstellung wie folgt:
1
/**
2
  * @brief  initialize the ADC object
3
  * @param  none
4
  * @retval none
5
  */
6
void PLATFORM::hw_ADC_Init(void){
7
8
        logger1.log(&logbyte);
9
        logger1.wrap(INFO);
10
        logger1.save("ADCINIT:");
11
12
  ADC_ChannelConfTypeDef sConfig;
13
14
      /**Common config
15
      */
16
    hadc1.Instance = ADC1;
17
    hadc1.Init.ClockPrescaler = ADC_CLOCK_ASYNC_DIV1;
18
    hadc1.Init.Resolution = ADC_RESOLUTION_12B;
19
    hadc1.Init.DataAlign = ADC_DATAALIGN_RIGHT;
20
    hadc1.Init.ScanConvMode = ADC_SCAN_ENABLE;
21
    hadc1.Init.EOCSelection = ADC_EOC_SINGLE_CONV;
22
    hadc1.Init.LowPowerAutoWait = DISABLE;
23
    hadc1.Init.ContinuousConvMode = ENABLE;
24
    hadc1.Init.NbrOfConversion = 3;
25
    hadc1.Init.DiscontinuousConvMode = DISABLE;
26
    hadc1.Init.ExternalTrigConv = ADC_SOFTWARE_START;
27
    hadc1.Init.ExternalTrigConvEdge = ADC_EXTERNALTRIGCONVEDGE_NONE;
28
    hadc1.Init.DMAContinuousRequests = ENABLE;
29
    hadc1.Init.Overrun = ADC_OVR_DATA_PRESERVED;
30
    hadc1.Init.OversamplingMode = DISABLE;
31
    if (HAL_ADC_Init(&hadc1) != HAL_OK)
32
    {
33
      _Error_Handler(__FILE__, __LINE__);
34
    }
35
36
      /**Configure Regular Channel
37
      */
38
    sConfig.Channel = ADC_CHANNEL_7;
39
    sConfig.Rank = ADC_REGULAR_RANK_1;
40
    sConfig.SamplingTime = ADC_SAMPLETIME_640CYCLES_5;
41
    sConfig.SingleDiff = ADC_SINGLE_ENDED;
42
    sConfig.OffsetNumber = ADC_OFFSET_NONE;
43
    sConfig.Offset = 0;
44
    if (HAL_ADC_ConfigChannel(&hadc1, &sConfig) != HAL_OK)
45
    {
46
      _Error_Handler(__FILE__, __LINE__);
47
    }
48
49
      /**Configure Regular Channel
50
      */
51
52
    sConfig.Channel = ADC_CHANNEL_8;
53
    sConfig.Rank = ADC_REGULAR_RANK_2;
54
    sConfig.SamplingTime = ADC_SAMPLETIME_640CYCLES_5;
55
    sConfig.SingleDiff = ADC_SINGLE_ENDED;
56
    sConfig.OffsetNumber = ADC_OFFSET_NONE;
57
    sConfig.Offset = 0;
58
    if (HAL_ADC_ConfigChannel(&hadc1, &sConfig) != HAL_OK)
59
    {
60
      _Error_Handler(__FILE__, __LINE__);
61
    }
62
63
      /**Configure Regular Channel
64
      */
65
    sConfig.Channel = ADC_CHANNEL_9;
66
    sConfig.Rank = ADC_REGULAR_RANK_3;
67
    sConfig.SamplingTime = ADC_SAMPLETIME_640CYCLES_5;
68
    sConfig.SingleDiff = ADC_SINGLE_ENDED;
69
    sConfig.OffsetNumber = ADC_OFFSET_NONE;
70
    sConfig.Offset = 0;
71
    if (HAL_ADC_ConfigChannel(&hadc1, &sConfig) != HAL_OK)
72
    {
73
      _Error_Handler(__FILE__, __LINE__);
74
    }
75
76
}

von Karl (Gast)


Lesenswert?

ADC Kalibrierung durchgeführt aka RTFM?

von Guido Körber (Gast)


Lesenswert?

Wert der Bandgap-Referenz ausgelesen?

Die STM32 ADC verwenden Vdda als obere Referenz, also muss man gegen 
diese kalibrieren.

RTFM

von Andreas S. (Firma: Schweigstill IT) (schweigstill) Benutzerseite


Lesenswert?

Du solltest mal direkt am Eingang des ADC, d.h. mit maximal 1cm 
Leiterlänge, einen kleinen Kondensator gegen Masse anbringen.

Ich hatte er neulich auch das Problem, dass der interne Multiplexer 
eines Multifunktionsbausteins beim Umschalten einiger ADC-Kanäle jeweils 
einen sehr kurzen (1ns) Spike erzeugte und hierdurch einen Messfehler 
von 8% verursachte. Die vorgeschalteten Treiber "sahen" diese Spikes 
nicht und konnten sie folglich auch nicht ausregeln.

Bei der Bemessung eines Kondensators sollte man sich an der maximal 
zulässigen kapazitiven Last des Treibers sowie der nötigen Bandbreite 
orientieren. Falls der Treiber sehr pingelig sein sollte, hilft ein 
kleiner Serienwiderstand (10-50 Ohm). In meinem o.a. Fall brachten 330pF 
schon den gewünschten Erfolg. Da der Treiber ausgangsseitig bis zu 1nF 
vertrug, lag ich mit 330pF (+ Leiterbahnen) völlig auf der sicheren 
Seite.

Auch in vielen Datenblättern und Applikationsschriften der Hersteller 
finden man kleine Kondensatoren an den ADC-Eingängen.

von Karl (Gast)


Lesenswert?

Und, was wars?

von Johnny S. (sgt_johnny)


Lesenswert?

Guido Körber schrieb:
> Wert der Bandgap-Referenz ausgelesen?
>
> Die STM32 ADC verwenden Vdda als obere Referenz, also muss man gegen
> diese kalibrieren.
>
> RTFM

Wie macht man so eine Kalibration?
Ich habe noch wenig erfahrung mit SMT32. Bei anderen MCU reicht eine 
Referenzspannung anzulegen und gut ist.



Andreas S. schrieb:
> Du solltest mal direkt am Eingang des ADC, d.h. mit maximal 1cm
> Leiterlänge, einen kleinen Kondensator gegen Masse anbringen.
> In meinem o.a. Fall brachten 330pF
> schon den gewünschten Erfolg. Da der Treiber ausgangsseitig bis zu 1nF
> vertrug, lag ich mit 330pF (+ Leiterbahnen) völlig auf der sicheren
> Seite.

Ich habe dort 100n, vielleicht zu viel?



Karl schrieb:
> Und, was wars?

Ist immernoch

von Bernd K. (prof7bit)


Lesenswert?

Johnny S. schrieb:
> Wie macht man so eine Kalibration?
> Ich habe noch wenig erfahrung mit SMT32.

Lies mal das entsprechende Kapitel im Handbuch durch (Pflichtlektüre!). 
Es gibt wahrscheinlich auch Beispielcode der den ADC verwendet und wo 
man sieht wann und wie die automatische Kalibrierung gestartet wird.

von Karl (Gast)


Lesenswert?

Welchen Controller hast du genau? Bei machen stm32 muss man den ADC 
kalibrieren bevor er halbwegs funktioniert. Dafür gibt es ein Bit in 
einem Register.

Du machst es einem nicht leicht...

von Mw E. (Firma: fritzler-avr.de) (fritzler)


Lesenswert?

Bernd K. schrieb:
> und wo
> man sieht wann und wie die automatische Kalibrierung gestartet wird.

Ein F205 hat die zB nicht.
Ist zumindest nirgends im Refman ADC Kapitel erwähnt.
(Der TO nutzt aber wohl einen anderen STM32)

von Karl (Gast)


Lesenswert?

Mw E. schrieb:
> Ein F205 hat die zB nicht.

Na genau deswegen Frage ich doch. Ich kenn es vom l4 und ich glaub 
einigen f3. Der f4 zb. Hat's auch nicht. So ein willkürlicher Offset war 
beim L4 auch vorhanden. Ich hätte gehofft, dass der OP selbst drauf 
kommt danach im Manual zu suchen...

von Claudia C. (Gast)


Lesenswert?

die Frage ist halt, selbst "wenn man drauf kommt2 was schon wieder so 
einen passiv agressiven Unterton hat..ist halt die Unwissenheit, ob es 
wirklich erforderlich ist.
Weil die Funktion vorhanden ist, bedeutet es ja nicht zwangsläufig das 
die auch genutzt werden muss..wenn dem so wäre, wäre es ja sinnvoll wenn 
der Controller es sowieso von sich aus machen würde..daher steht die 
Frage im Raum..weshalb ist die Option überhaupt vorhanden?

von Stefan F. (Gast)


Lesenswert?

Claudia C. schrieb:
> Weil die Funktion vorhanden ist, bedeutet es ja nicht zwangsläufig das
> die auch genutzt werden muss

Ich denke, dass die Empfehlungen im Referenzhandbuch deutlich genug 
sind. Bei den Modellen, wo es nötig ist, weist der Text deutlich darauf 
hin. Eine Nutzung ohne Kalibrierung ist doch gar nicht erwähnt.

> weshalb ist die Option überhaupt vorhanden?

Weil die Kalibrierung erstn nach der Einschwingzeit der betroffenen 
Kompinenten funktioniert. Würde der Chip das ganz schnell während des 
Reset machen, wäre der ADC sehr ungenau. Auch das ist im 
Referenzhandbuch erklärt.

von Karl (Gast)


Lesenswert?

Claudia C. schrieb:
> die Frage ist halt, selbst "wenn man drauf kommt2 was schon wieder so
> einen passiv agressiven Unterton hat..
Heul doch. Netiquette nicht beachten aber den Hintern gepudert bekommen 
wollen. Es kann nun keiner behaupten es wäre kein Hinweis auf ein 
mögliches Problem vorhanden.
>ist halt die Unwissenheit, ob es
> wirklich erforderlich ist.
Na klar. Ein 4 Bit ADC reicht manchen auch, dann kann man sich die zwei 
Zeilen Code sparen.
> Weil die Funktion vorhanden ist, bedeutet es ja nicht zwangsläufig das
> die auch genutzt werden muss..wenn dem so wäre, wäre es ja sinnvoll wenn
RTFM ^2
> der Controller es sowieso von sich aus machen würde..daher steht die
Kopfschütteln. Sonst nichts.
> Frage im Raum..weshalb ist die Option überhaupt vorhanden?
Zum selben Zweck wie du: den unbedarften Leser trollen.

von Johnny S. (sgt_johnny)


Lesenswert?

Karl schrieb:
> Welchen Controller hast du genau? Bei machen stm32 muss man den ADC
> kalibrieren bevor er halbwegs funktioniert. Dafür gibt es ein Bit in
> einem Register.
>
> Du machst es einem nicht leicht...

Ich habe einen STM32L433 im Einsatz. Das Projekt soll aber aus 
kostengründen am schluss mit einem L431 laufen, welcher fast identisch 
ist.

von Karl (Gast)


Lesenswert?

Dann lese zu deinem eigenen wohl das Manual des ADC. Der hat das 
kalibrierbit und hat bei mir auch in dieser Größenordnung falsch 
gemessen wenn man die nicht vor Benutzung ausführt.
Sag Bescheid ob erfolgreich.

von olibert (Gast)


Lesenswert?

https://www.st.com/resource/en/application_note/cd00211314.pdf
How to get the best ADC accuracy in STM32 microcontrollers

Schon heruntergeladen und komplett durchgelesen?
Falls nicht, warum nicht?

von Guido Körber (Gast)


Lesenswert?

BAZINGA!
Die RTFMs fliegen heute wieder schnell in der Donnerkuppel!

von Stefan F. (Gast)


Lesenswert?

Guido Körber schrieb:
> Die RTFMs fliegen heute wieder schnell in der Donnerkuppel!

Wenn du 5 Tage schnell findest, dann möchte ich nicht dein Kunde sein.

von noreply@noreply.com (Gast)


Lesenswert?

Guido Körber schrieb:
> BAZINGA!
> Die RTFMs fliegen heute wieder schnell in der Donnerkuppel!

Mag dämlich klingen, aber RTFM ist sehr wichtig. Ich habe mich durch 
gefühlt 4 Dokumente gequält.

Der Gewinner ist, wenn man erkennt, das die ADC mit Kapazitäten 
aufgebaut sind und das Design entsprechend gestaltet.

Ich habe auch noch in Erinnerung, das bei Entwicklerboards sich STM 
nicht unbedingt an seine eigenen Empfehlungen hält.

von Karl (Gast)


Lesenswert?

Und nun?

von Andreas S. (Firma: Schweigstill IT) (schweigstill) Benutzerseite


Lesenswert?

Wie sehr unterscheiden sich denn die Messwerte, wenn Du mehrere 
Messungen hintereinander machst, ohne zwischendurch den ADC-Kanal 
umzuschalten?

von Karl (Gast)


Lesenswert?

Und was war es jetzt?

von Karl (Gast)


Lesenswert?

Karl schrieb:
> Und was war es jetzt?

Komm, lass uns nicht dumm sterben.

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.