Forum: Mikrocontroller und Digitale Elektronik STM32F072 ADC Genauigkeit trotz Kalibrierung nicht optimal


von Chris (Gast)


Lesenswert?

Hallo zusammen,

ich versuche gerade die best mögliche Genauigkeit aus dem ADC eines 
Nucleo-F072RB (STM32F072) zu bekommen. Hintergrund ist, dass ich eine 
Eingangsspannung nach einem Spannungsteiler messen möchte. Wenn dabei 
schon der angenommene/ermittelte Wert der Referenzspannung für die 
Berechnung falsch ist, passt natürlich der gemessene Wert nicht, schon 
gar nicht nach dem Spannungsteiler.

Daher hatte ich versucht den ADC mit den intern gespeicherten Werten der 
Referenzspannung zu kalibrieren. Zum Einen durch die 
Selbstkalibrierungsroutine, zum Anderen durch die Ermittlung der 
tatsächlich anliegende Spannung an VDDA, welche für die weiteren 
Messungen als Referenzwert genutzt wird.

Leider komme ich bereits bei dieser Ermittlung auch eine Differenz von 
etwa 15 mV. Mit zwei kalibrierten Multimetern und einem Oszi messe ich 
(direkt an den uC Pins 12 und 13 ) stabile 3.310 V mit etwa 5 mVpp 
Ripple und keine Einbrüche während den Messungen. Direkt an den VDDA- 
und GNDA-Pins habe ich 2x10nF, 1x 100nF und 1x10uF KerKos versucht und 
kombiniert. Die Messung und Berechnung vom STM32 ergibt stabile ~3.296 V 
(+-1 LSB), also 14 mV Abweichung. Der ADC ist auf 12-Bit und die längste 
Samplerate von 239 Cycles eingestellt.

Hat schon jemand ein ähnliches Problem gehabt und bestenfalls gelöst? 
Anbei die wichtigen Ausschnitte aus meinem Code zur Kalibrierung:
1
// ADC self calibration, has to be done before any ADC Start/Enable
2
while(HAL_ADCEx_Calibration_Start(&hadc) != HAL_OK);
3
4
// values for calculation of actually VDDA-supply and reference voltage
5
volatile uint32_t VREFINT_CAL, VREF_3V3 = 330000;
6
const uint16_t *p = (uint16_t *)0x1FFFF7BA; // 2 Byte at this address is VRefInt @3.3V/30°C
7
VREFINT_CAL = *p; // read the value at pointer address
8
9
// Start ADC with DMA support
10
volatile uint16_t adc_value[4] = {0, 0, 0, 0};
11
HAL_ADC_Start_DMA(&hadc, (uint32_t*)adc_value, 4);
12
 
13
while (1)
14
{
15
   //toggle LED
16
   HAL_GPIO_TogglePin(LD2_GPIO_Port, LD2_Pin);
17
   HAL_Delay(50);
18
19
   // calculate 3.3 V supply voltage with the factory stored in VREFINT_CAL value
20
   // adc_value[2] contains the raw ADC_IN17 value of the internal voltage reference (~1530)
21
   VREF_3V3 = (330000 * VREFINT_CAL) / adc_value[2];
22
   // VREFINT_CAL = 1529
23
   // adc_value[2] = 1530
24
   // VREF_3V3 = ~329568 (~3.29568 V calculated)

von pegel (Gast)


Lesenswert?

Chris schrieb:
> stabile 3.310 V

Aber in deinen Berechnungen benutzt du 3,30V !?

von Chris (Gast)


Angehängte Dateien:

Lesenswert?

pegel schrieb:
> Chris schrieb:
>> stabile 3.310 V
>
> Aber in deinen Berechnungen benutzt du 3,30V !?

Die 3.3 V ist der Referenzwert von ST (VRefInt @3.3V/30°C). Durch das 
Verhältnis aus den im Werk gespeicherten Wert in VREFINT_CAL (Register 
0x1FFFF7BA) und den vom ADC eingelesenen Wert VREFINT_DATA (bzw. 
adc_value[2]) lässt sich dann auf die aktuell tatsächlich anliegende 
VDDA schließen.

von Marcus H. (Firma: www.harerod.de) (lungfish) Benutzerseite


Angehängte Dateien:

Lesenswert?

Wie siehst Du Deine Fragestellung vor dem Hintergrund des Datenblatts?
STM32F072xx datasheet rev5 Februar 2017

von Jim M. (turboj)


Lesenswert?

Bei solchen Sachen hacke ich das Ganze immer testweise in Excel (oder 
LibreOffice Calc) ein. Dazu lasse ich mir im Debugger die Rohwerte des 
ADCs ausgeben.

Bei C macht man gerne subtile Fehler in den Formeln - mit den 
Zwischenergebnissen aus Excel findet man die recht schnell.

Beispielsweise könnte
1
330000 * VREFINT_CAL
überlaufen - diese Multiplikation wäre nur mit dem 64-bittigem 330000ULL 
sicher.

Netter Nebeneffekt: Man sieht auch sofort wenn der ADC außerhalb seines 
Messbereichs betrieben wird, weil dann Null oder 4095 als Rohwert 
auftaucht.

von Geb (Gast)


Lesenswert?

Das wird so nix werden. VDDA als Referenz ist nicht gut genug. Die 
Idioten von ST haben bei diesem Teil keinen Vref Anschluss 
herausgeführt. Vlt. die Interne Referenz verwenden und entsprechend 
kalibrieren. Ich verwende den STM32F103Z im 144pol. Geh. und mit 
externer Präzisionsreferenz von 2,5V.Da arbeitet der ADC schon aufs Bit 
genau.

Grüsse

von Bauform B. (bauformb)


Lesenswert?

Es gibt Referenzspannungs-ICs, die 3.3V, 10mA liefern können. Damit 
könnte man den VDDA/VREF-Pin versorgen. Bei der L4-Familie (jedenfalls 
beim STM32L471) darf VDDA auch viel kleiner sein als VDD, bei den 
älteren Chips darf die Differenz evt. nicht zu groß sein.

von Chris (Gast)


Lesenswert?

Marcus H. schrieb:
> Wie siehst Du Deine Fragestellung vor dem Hintergrund des Datenblatts?
> STM32F072xx datasheet rev5 Februar 2017

Gehe ich davon aus, dass bei jedem möglichem Fehler der Maximalwert 
zutrifft, also insgesamt 10 LSB, dürfte man doch immernoch "nur" etwa 8 
mV Fehler haben, oder denke ich falsch? ( (3.3 V / 4095) * 10 LSB = 8.06 
mV).

Jim M. schrieb:
> Beispielsweise könnte 330000 * VREFINT_CAL
> überlaufen - diese Multiplikation wäre nur mit dem 64-bittigem 330000ULL
> sicher.

VREFINT_CAL kann maximal den Wert 4095 haben, daher sollte das Ergebnis 
in ein 32-bit unsigned int passen. Bei den restlichen Berechnungen wird 
ein ausreichend großer Datentyp natürlich beachtet.

Geb schrieb:
> Vlt. die Interne Referenz verwenden und entsprechend kalibrieren.
Die interne Referenz ist auch nicht wirklich genau (1.2 - 1.25 V). Daher 
ist der Ansatz ja die Kalibrierung wie oben beschrieben. Wenn diese in 
regelmäßigen Abständen durchgeführt wird, sollte auch eine sich (z.B. 
durch Temperatur) ändernde VDDA-Spannung genutzt werden können.

Außerdem liegt das Problem ja nicht mal darin, dass diese Spannung in 
irgend einer Art und Weise schwankt oder nicht stabil ist. Kann es sein 
dass die intern gespeicherten Werte in VREFINT_CAL einfach falsch sind? 
Also nicht nur um das letzte Bit, sondern deutlich mehr?

von Marcus H. (Firma: www.harerod.de) (lungfish) Benutzerseite


Lesenswert?

Chris schrieb:
> Marcus H. schrieb:
>> Wie siehst Du Deine Fragestellung vor dem Hintergrund des Datenblatts?
>> STM32F072xx datasheet rev5 Februar 2017
>
> Gehe ich davon aus, dass bei jedem möglichem Fehler der Maximalwert
> zutrifft, also insgesamt 10 LSB, dürfte man doch immernoch "nur" etwa 8
> mV Fehler haben, oder denke ich falsch? ( (3.3 V / 4095) * 10 LSB = 8.06
> mV).

Dann habe ich das "+-1 LSB" in Deinem Kommentar falsch interpretiert:
"Die Messung und Berechnung vom STM32 ergibt stabile ~3.296 V
(+-1 LSB), also 14 mV Abweichung."

ST gibt im Datenblatt als Werkskalibrierbedingung 3,3V+-10mV an. Das ist 
das bestmögliche zu erwartende Ergebnis. Wenn Du es präziser brauchst, 
musst Du in Deiner Applikation nachkalibieren.

Bei absoluten Genauigkeitsanforderungen jenseits 8bit würde ich zu einem 
externen ADC raten.

: Bearbeitet durch User
von Chris (Gast)


Lesenswert?

Marcus H. schrieb:
> Dann habe ich das "+-1 LSB" in Deinem Kommentar falsch interpretiert:
> "Die Messung und Berechnung vom STM32 ergibt stabile ~3.296 V
> (+-1 LSB), also 14 mV Abweichung."

Das war eigentlich so gemeint, dass die ADC Messung der internen 
Referenzspannung einen Wert von 1529, 1530 oder 1531 liefert, also das 
letzte Bit in seltenen Fällen hüpft, evtl durch die Erwärmung während 
der Laufzeit.

Schade, ich hätte gehofft etwas präziser messen zu können da ich schon 
von Genauigkeiten von +-1 mV gelesen habe, und dort auch keine externe 
Referenzspannung verwendet wurde. Das waren dann aber vmtl nur 
Glückstreffer oder es war doch eine externe und genaue Referenzspannung 
im Einsatz.

Dennoch vielen Dank für die Hilfe

von Gerd E. (robberknight)


Lesenswert?

Chris schrieb:
> Schade, ich hätte gehofft etwas präziser messen zu können da ich schon
> von Genauigkeiten von +-1 mV gelesen habe, und dort auch keine externe
> Referenzspannung verwendet wurde. Das waren dann aber vmtl nur
> Glückstreffer oder es war doch eine externe und genaue Referenzspannung
> im Einsatz.

Niemand hindert Dich daran einmalig einen genaueren Wert für die interne 
Referenz als VREFINT_CAL mit einem guten Multimeter zu vermessen und im 
Flash zu speichern.

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.