Ich versuche aktuell, die Formel für die Berechnung der Temperatur des
internen Sensors zu verstehen. Den Wert, den ich vom ADC zurückbekomme
ist 1733. Die Formel lautet:
((V25-Vsense) / Slope) + 25
V25 ist 1.43V, Vsense wäre:
1733 * 3.0/4096 = 1.27V
((1.43V-1.27V)*1000 / 4.3mV/°C) + 25°C = 62°C
Das ist schon recht weit von der Wirklichkeit entfernt, hab ich
irgendwas in meinen Berechnung vergessen / übersehen?
Sind 3.0V nun die Referenzspannung? Wenn ich Channel 17 messe, der laut
dieser Application Note mit Vrefint verbunden ist
(http://www.st.com/content/ccc/resource/technical/document/application_note/b9/21/44/4e/cf/6f/46/fa/DM00035957.pdf/files/DM00035957.pdf/jcr:content/translations/en.DM00035957.pdf)
bekomme ich den Wert 2080 zurück. Damit kann ich doch jetzt nicht viel
anfangen, da ich die Referenzspannung nicht weiß und somit nicht auf die
tatsächliche Spannung schließen kann?
Im selben Abschnitt ist noch diese Formel gegeben:
Val_VREFINT = VREFINT 2^12 / VREF+ = VREFINT x 4096 / VDDA
Von der kenne ich aber Vref+ und VDDA nicht? Ich blick da nicht durch.
Fuer modernere STM32 als den F1 gibt es im "ROM" Kalibarationswerte, die
bei Chiptest bei 30 und 110 und 3.3V gemessen wurden. Setzt man die
Werte aus dem Rom in die Formel ein, bekommt man deutlich realistischere
Werte.
Fuer den F103 finde ich keine Hinweis, dass diese Kalibrationswerte
verfuegbar sind. Wenn Du nur die typischen Datenblattwerte nimmt, musst
Du mit grossen Toleranzen leben, kannst aber immer noch Tendenzen sehen.
Zwischen V25 Max und Min liegen 180 mV, bei Min Avg-Slope 4 mV sind das
45 (+/- 22.5) Grad moegliche Abweichung.
Ausserdem musst Du die Samplezeiten fuer den Temperaturkanal sehr lang
waehlen, den richtigen Kanal wahlen und TSVREFE richtig gesetzt haben.
Viel raum also fuer Fehler. Lass Dir doch erstmal nur die Spannung des
Temperatursensor ausgeben und schau ob die Werte ungefaehr passen.
Uwe B. schrieb:> Ausserdem musst Du die Samplezeiten fuer den Temperaturkanal sehr lang> waehlen, den richtigen Kanal wahlen und TSVREFE richtig gesetzt haben.> Viel raum also fuer Fehler.
So sieht die ADC-Initialisierung aus:
1
RCC->APB2ENR |= (1<<9); //Enable ADC1 Clock
2
RCC->CFGR |= (0b10<<14); //set ADC Prescaler '6'
3
ADC1->SMPR1 |= (0b100<<18); //41.5 cycles sample time
4
ADC1->CR2 |= (1<<23); //Enable Temperature Sensor & Vref
5
6
ADC1->CR2 |= (1<<0); //Enable ADC and start conversion
while(ADC1->CR2 & (1<<3)){ //Wait until calibration register initialized
10
;
11
}
12
13
ADC1->CR2 |= (1<<2); //Enable calibration
14
while(ADC1->CR2 & (1<<2)){ //Wait until calibration completed
15
;
16
}
und so das Auslesen:
1
uint32_t getADCTempValue(uint16_t channel){
2
ADC1->SQR3 |= (channel<<0);
3
ADC1->CR2 |= (1<<0); //Enable ADC and start conversion
4
while(!(ADC1->SR & (1<<1))){ //Wait until end of conversion
5
;
6
}
7
return ADC1->DR;
8
}
Uwe B. schrieb:> Lass Dir doch erstmal nur die Spannung des> Temperatursensor ausgeben
Die Spannung direkt bekomme ich doch nicht, oder? Sondern nur einen
Wert, den ich mit der Formel:
adc_value * Vref / (2^12)
in eine Spannung umrechnen kann.
Max M. schrieb:> RCC->CFGR |= (0b10<<14); //set ADC Prescaler '6'> ADC1->SMPR1 |= (0b100<<18); //41.5 cycles sample time
Gibt das die in rm0008 geforderten mindestens 17.1 us?
(
> Die Spannung direkt bekomme ich doch nicht, oder? Sondern nur einen> Wert, den ich mit der Formel:>> adc_value * Vref / (2^12)>> in eine Spannung umrechnen kann.
Ja, genau, lass der den ADC Wert als Spannung oder einfach nur als Wert
ausgeben und schau als erstes, ob der Wert der Erwartung entspricht. Mit
mit "finger drauf" und/oder Kaeltespray kanns Du dann die Chiptemperatur
veraendern un dem Wert beobachten.
Uwe B. schrieb:> Ja, genau, lass der den ADC Wert als Spannung oder einfach nur als Wert> ausgeben und schau als erstes, ob der Wert der Erwartung entspricht.
Ich hab den Wert 1750 bekommen, laut diversen Tutorials im Internet
entspräche ein Wert von 1750 ca. 25°C (darauf komm ich rechnerisch
auch, wenn 3.3V Vref wäre). Der Wert würde also ungefähr passen (gefühlt
sind es aber eher 23°C).
Das Board unter eine Glühlampe zu halten, senkt den Wert.
Uwe B. schrieb:> Gibt das die in rm0008 geforderten mindestens 17.1 us?
Der ADC Prescaler ist auuf 6, also wäre die Frequenz: 72MHz / 6 =
12MHz. Das sind 12 * 10^6 Cycles pro Sekunde. Jeder Cycle braucht also
12us, wenn 41.5 cycles gewartet wird, entspricht das 498u us, müsste
also rein rechnerisch passen, oder?
Edit: Das stimmt ja gar nicht, ein Cycle braucht 1 / 12MHz, also
8.3*(10^-8)s. 41.5 cycles brauchen also 3.46us.
Uwe B. schrieb:> Setze doch erst einmal auf maximale Sampledauer (111 statt 100) in> ADC_SMPRx.
Hab ich gemacht, jetzt hat sich der Wert leicht nach oben korrigiert,
auf 1755. Ich hab inzwischen eine Vermutung aufgestellt, wie die
Formel funktionieren könnte. Um die Spannung zu bekommen, die der
Temperatursensor liefert, muss man diesen mit der Referenzspannung und
der Auflösung des ADC verrechnen (wie oben schon angemerkt). Dann läuft
das so:
(V25 - Vtemp) * 1000 / 4.3 + 25
Soweit ich das sehe, bekommt man aber den richtigen Wert von V25 nicht
raus, da mein STM32F103 keinen Referenzpin hat, er liegt aber wohl im
Bereich zwischen 1.34V und 1.52V.
Mit der oben genannten Formel komme ich dann auf ~25°C.
Hm, kenne mich ja nur mit AVRs aus, aber wenn ich beim STM32F103
in's Datenblatt schaue, kann ich die interne Temperatur-Erfassung
mit 12 Bit Auflösung nicht sooo toll finden:
Guckt man tiefer in's Datenblatt:
2.3.28 Temperature sensor
-------------------------
The temperature sensor has to generate a voltage that varies
linearly with temperature. The conversion range is between
2 V < V DDA < 3.6 V.
Erkenntnis 1:
=============
2 V ... 3,6 V an V_DDA macht einen großen Unterschied
- Da sollte man schon mal wissen, was an V_DDA anliegt - und
in die Berechnung einfließen lassen.
5.3.21 Temperature sensor characteristics
-----------------------------------------
Für 25 °C liefert der Sensor 1,34...1,52 V
Die Änderung für 1 °C ist 4,0 mV/°C ... 4,6 mV/°C
Bei 4,3 mV / °C entspricht die Spanne von 1,52 V - 1,34 V
= 0,18 V = 180 mV, einer Unsicherheits-Spanne von
180 mV / 4,3 mV/°C = 41 °C
Erkenntnis 2:
=============
25 °C +/- 20,5 °C sind für Absolut-Messung SEHR ungeeignet.
Ohne eine Kalibrierung ist also nur Müll zu messen....
Fazit:
======
Deine schlechten Testergebnisse zeigen einfach nur die
grottenschlechte Temperaturerfassung des STM32F103.
Jakob schrieb:> The temperature sensor has to generate a voltage that varies> linearly with temperature. The conversion range is between> 2 V < V DDA < 3.6 V.>> Erkenntnis 1:> =============> 2 V ... 3,6 V an V_DDA macht einen großen Unterschied> - Da sollte man schon mal wissen, was an V_DDA anliegt - und> in die Berechnung einfließen lassen.
Das hast du falsch verstanden: Vdda, die Versorgungsspannung für den
Analogbereich des µCs, muss innherhalb von 2V bis 3,6V liegen, damit der
Temperatursensor spezifikationsgemäß funktioniert.
Wo Vdda innerhalb dieses Bereichs genau liegt, ist nicht so spannend:
Zuerst misst Du den Wert der internen Referenz. Deren Wert kennst Du
relativ genau, daraus kannst Du dann den aktuellen Wert von Vdda
zurückrechnen.
Und damit liest Du nun den Temperatursensor aus.
Vrefint = Val_Vrefint * Vdda / 4096
Mit einem Wert von z.B. 2060 für Val_Vrefint:
Vrefint = 2060 * 3.3V / 4096 = 1.66V
Kommt mir irgendwie wenig vor?
Gerd E. schrieb:> daraus kannst Du dann den aktuellen Wert von Vdda> zurückrechnen.
Okay, wie würde das funktionieren?
Wenn du im Ref.Manual mal ganz unten schaust sollte es ein Code-Beispiel
geben, das dir das ganze auch direkt in °C umrechnet. Die Rechnung ist
echt Hahnebüchen, aber funktioniert.
Max M. schrieb:> Vdda (also die Versorgungsspannung) ist in meinem Fall 3.3V.
Konstant, z.B. mit Spannungsregler?
> Der> gemessene Wert von Channel 17 (Val_Vrefint)...> schwankt zwischen diesen Werten:>>
1
> 1983
2
> 2189
3
> 2008
4
> 2199
5
> 2016
6
> 2202
7
>
Während Du konstante 3.3V an Vdda anliegen hast?
Dann ist schon an der Stelle was ziemlich faul:
Spannungsversorgung mit Kondensatoren nach Datenblatt genau des
verwendeten Controllers abgeblockt? Siehe u.a. Fig. 14 im Datenblatt.
ADC nach jedem Booten des µC kalibriert?
ADC läuft die ganzen 17.1µs für das Sampeln der Vrefint?
Den richtigen ADC verwendet? Lt. Refman ist der Vrefint nur an ADC1
verfügbar.
Geh auch nochmal das Errata-Sheet durch, vielleicht gibt es irgendwelche
Pins bei deren Benutzung der ADC empfindlich reagiert. So ähnlich wie
PC13, PC14, PC15.
Die Vrefint muss lt. Datenblatt Tabelle 5.3.4 zwischen 1.16V und 1.24V
liegen. Bei 3,3V und 1,2V kommt da 1487 raus, Dein Wert sollte da
irgendwo in der Nähe liegen.
Gerd E. schrieb:> Konstant, z.B. mit Spannungsregler?
Hm, der Strom kommt von einem USB / UART Konverter, auf dem Board
(dieses: http://img.dxcdn.com/productimages/sku_395848_2.jpg) ist einer
drauf.
Gerd E. schrieb:> Während Du konstante 3.3V an Vdda anliegen hast?
Okay, gerade nachgemessen: Es sind 3.24V
Gerd E. schrieb:> Spannungsversorgung mit Kondensatoren nach Datenblatt genau des> verwendeten Controllers abgeblockt? Siehe u.a. Fig. 14 im Datenblatt.
Ich benutze ein fertiges Board, ich gehe mal davon aus, dass es richtig
verschaltet ist, auch wenn es Chinaware ist.
Gerd E. schrieb:> ADC nach jedem Booten des µC kalibriert?>> ADC läuft die ganzen 17.1µs für das Sampeln der Vrefint?>> Den richtigen ADC verwendet? Lt. Refman ist der Vrefint nur an ADC1> verfügbar.
Nicht böse gemeint, aber mein Code steht hier:
Beitrag "Re: STM32F103 interner Temperatursensor"
Der erfüllt, denke ich, die Anforderungen.
Die Anzahl der Wartezyklen wurde inzwischen auf 239.5 cycles erhöht, das
dürfte passen (Nach 5.3.18 entsprechen 239.5 cycles 17.1us bei 14MHz
ADC-Frequenz, da mein Prescaler bei 6 liegt, ist die Frequenz 12 MHz).
Gerd E. schrieb:> Die Vrefint muss lt. Datenblatt Tabelle 5.3.4 zwischen 1.16V und 1.24V> liegen. Bei 3,3V und 1,2V kommt da 1487 raus, Dein Wert sollte da> irgendwo in der Nähe liegen.
Ich hab gerade mal debugged. Wenn ich durchsteppe, bekomme ich auf dem
Terminal Window auf einmal eine ziemlich stabile Zahl um 1513. Warum
ändert sich der Wert auf über 2000 wenn ich den Controller nicht
debugge? Mit einem Wert von 1513 und 3.24V kommt man auf 1.20V.
Max M. schrieb:>> Konstant, z.B. mit Spannungsregler?>> Hm, der Strom kommt von einem USB / UART Konverter, auf dem Board> (dieses: http://img.dxcdn.com/productimages/sku_395848_2.jpg) ist einer> drauf.
Vielleicht nicht perfekt, verursacht aber vermutlich nicht solche
Sprünge.
Häng es vielleicht aber zur Sicherheit dennoch mal an nen anderen
USB-Hub, USB-Port oder PC. Ich hatte schon einen USB-Hub mit einem
Netzteil, dessen Kondensatoren defekt waren. Das machte ähnliche Effekte
schon unter leichter Last.
>> Spannungsversorgung mit Kondensatoren nach Datenblatt genau des>> verwendeten Controllers abgeblockt? Siehe u.a. Fig. 14 im Datenblatt.>> Ich benutze ein fertiges Board, ich gehe mal davon aus, dass es richtig> verschaltet ist, auch wenn es Chinaware ist.
Da hab ich so meine Zweifel. Kontrolliere das bitte. Vor allem wenn Du
solche Fehler siehst. Kerkos nachmessen oder gegen welche tauschen bei
denen Du Dir wegen der Werte sicher bist.
> Ich hab gerade mal debugged. Wenn ich durchsteppe, bekomme ich auf dem> Terminal Window auf einmal eine ziemlich stabile Zahl um 1513.
So sollte der Wert sein.
> Warum> ändert sich der Wert auf über 2000 wenn ich den Controller nicht> debugge?
Es gibt 2 Möglichkeiten:
a) Software
Dein Programm macht im Hintergrund (Interrupts, PWM,...) irgendetwas,
was den ADC durcheinanderbringt. Beim Debuggen läuft das nicht, oder nur
so langsam, daß es keinen Schaden anrichtet.
b) Hardware
Beim Debuggen zieht der µC nicht kontinuierliche Peaks aus den falsch
dimensionierten Kondensatoren, sondern zwischen den Debugger-Steps haben
die genug Zeit sich wieder aufzuladen.
oder
Beim Debuggen wartet der µC meist auf den nächsten Befehl, dadurch
entstehen nicht so starke Schwankungen auf Masse / Vcc. Die bringen den
ADC durchandender wg. schlechtem Routing oder ähnlichem.
Gerd E. (robberknight) schrieb:
> das hast du falsch verstanden...
Dass der Grundwert für 25 °C mit (typically) +/-20,5 °C Unsicherheit
belastet ist, muss man nur als Pipifax abtun...
Schon hat man: Endlosen Spaß beim weiteren Schwafeln!
Jakob schrieb:> Gerd E. (robberknight) schrieb:>>> das hast du falsch verstanden...>> Dass der Grundwert für 25 °C mit (typically) +/-20,5 °C Unsicherheit> belastet ist, muss man nur als Pipifax abtun...
Wo habe ich das geschrieben oder angedeutet?
Ich bin nur auf Deine "Erkenntnis 1" eingegangen, weil die meiner
Meinung nach nicht korrekt war. Das sagt nichts über Deine "Erkenntnis
2" aus.
Gerd E. schrieb:> a) Software>> Dein Programm macht im Hintergrund (Interrupts, PWM,...) irgendetwas,> was den ADC durcheinanderbringt. Beim Debuggen läuft das nicht, oder nur> so langsam, daß es keinen Schaden anrichtet.
Hm, Interrupts und PWM hab ich nicht im Code. Fällt euch da etwas auf?
1
#include "stm32f10x_gpio.h"
2
#include <stdio.h>
3
#include <string.h>
4
5
void delay(long cycles);
6
void delay(long cycles){
7
while(cycles > 0)
8
cycles--;
9
}
10
11
void initADC(){
12
RCC->APB2ENR |= (1<<9); //Enable ADC1 Clock
13
RCC->CFGR |= (0b11<<14); //set ADC Prescaler '8'
14
15
ADC1->SMPR1 |= (0b111<<18); //239.5 cycles sample time
16
ADC1->CR2 |= (1<<23); //Enable Temperature Sensor & Vref
17
ADC1->CR2 |= (1<<0); //Enable ADC and start conversion