Forum: Mikrocontroller und Digitale Elektronik STM32L476 interner Temperatursensor


von David (Gast)


Lesenswert?

Hallo,

ich hab hier ein STM32 Nucleo L476 vor mir liegen und versuche micht 
gerade am auslesen des internen Temperatursensors. Ich benutze den HAL 
und CubeMX von ST und hab mir den Code für den ADC generieren lassen:

  hadc1.Instance = ADC1;
  hadc1.Init.ClockPrescaler = ADC_CLOCK_ASYNC_DIV8;
  hadc1.Init.Resolution = ADC_RESOLUTION_12B;
  hadc1.Init.DataAlign = ADC_DATAALIGN_RIGHT;
  hadc1.Init.ScanConvMode = ADC_SCAN_DISABLE;
  hadc1.Init.EOCSelection = ADC_EOC_SINGLE_CONV;
  hadc1.Init.LowPowerAutoWait = DISABLE;
  hadc1.Init.ContinuousConvMode = ENABLE;
  hadc1.Init.NbrOfConversion = 1;
  hadc1.Init.DiscontinuousConvMode = DISABLE;
  hadc1.Init.ExternalTrigConv = ADC_SOFTWARE_START;
  hadc1.Init.ExternalTrigConvEdge = ADC_EXTERNALTRIGCONVEDGE_NONE;
  hadc1.Init.DMAContinuousRequests = DISABLE;
  hadc1.Init.Overrun = ADC_OVR_DATA_PRESERVED;
  hadc1.Init.OversamplingMode = DISABLE;
  hadc1.Init.Oversampling.Ratio = ADC_OVERSAMPLING_RATIO_64;
  hadc1.Init.Oversampling.RightBitShift = ADC_RIGHTBITSHIFT_6;
  hadc1.Init.Oversampling.TriggeredMode = 
ADC_TRIGGEREDMODE_SINGLE_TRIGGER;
  hadc1.Init.Oversampling.OversamplingStopReset = 
ADC_REGOVERSAMPLING_CONTINUED_MODE;
  if (HAL_ADC_Init(&hadc1) != HAL_OK)
  {
    Error_Handler();
  }


    /**Configure Regular Channel
    */
  sConfig.Channel = ADC_CHANNEL_TEMPSENSOR;
  sConfig.Rank = 1;
  sConfig.SamplingTime = ADC_SAMPLETIME_12CYCLES_5;
  sConfig.SingleDiff = ADC_SINGLE_ENDED;
  sConfig.OffsetNumber = ADC_OFFSET_NONE;
  sConfig.Offset = 0;
  if (HAL_ADC_ConfigChannel(&hadc1, &sConfig) != HAL_OK)
  {
    Error_Handler();
  }

Meine Messung der Temperatur läuft so ab:

  while(HAL_ADC_PollForConversion(&hadc1,10) != HAL_OK);
  temp = (int)HAL_ADC_GetValue(&hadc1);

Laut ST Reference Manual lässt sich die Temperatur folgendermaßen 
berechnen:
T (in °C) = ((110°C - 30°C)/(TS_CAL2 - TS_CAL1))*(TS_DATA - 
TS_CAL1)+30°C

Die Werte TS_CALx stellen Kalibirierungswerte von ST für 30°C und 110°C 
dar. Sie liegen bei 1040 und 1321. Ich messe jedoch immer Werte um 950. 
Eingesetzt ergibt sich dann eine Temperatur knapp über dem Nullpunkt. 
Glaubt mir, bei mir ist es wärmer.

Vielleicht sieht jemand einen Fehler in meinem Code. Habe jetzt schon 
viele Kombinationen aus ADC clock prescaler und sampling time durch, 
daran sollte es nicht liegen...

Danke und Gruß

von Uwe B. (Firma: TU Darmstadt) (uwebonnes)


Lesenswert?

ADC_SAMPLETIME_12CYCLES_5

Ich habe jetzt keine Lust in den Cube Quellen nachzuschlagen...

Der Temperatursensor braucht wirklich lange Samplezeiten.  Kodiert das 
der Wert oben?

von ide (Gast)


Lesenswert?

HAL_ADC_Start(...) vergessen bevor du HAL_ADC_GetValue aufrufst?

von David (Gast)


Lesenswert?

Uwe B. schrieb:
> ADC_SAMPLETIME_12CYCLES_5
>
> Ich habe jetzt keine Lust in den Cube Quellen nachzuschlagen...
>
> Der Temperatursensor braucht wirklich lange Samplezeiten.  Kodiert das
> der Wert oben?

Könnte das Problem sein, werde einfach mal noch längere Zeiten 
ausprobieren.

ide schrieb:
> HAL_ADC_Start(...) vergessen bevor du HAL_ADC_GetValue aufrufst?

Das hab ich wohl vergessen zu in den Thread zu kopieren, aber klar wird 
aufgerufen. Jegliche Messung abgesehen vom Temperatursensor funktioniert 
einwandfrei.

von David (Gast)


Lesenswert?

Der Temperatursensor funktioniert, wenn ich den Finger auflege, steigt 
der gemessene Wert. So langsam vermute ich das der Sensor defekt oder so 
ziemlich ungenau ist. Die laut den Electrical Specifications geforderten 
5µs Abtastzeit halte ich nun mehr als ausreichend ein.

Das mach ich auch alles (CCR Register passt):
To use the sensor:

1. Select the ADC1_IN17 or ADC3_IN17 input channels (with the 
appropriate sampling time).
2. Program with the appropriate sampling time (refer to electrical 
characteristics section of the device datasheet).
3. Set the CH17SEL bit in the ADCx_CCR register to wake up the 
temperature sensor from power-down mode.
4. Start the ADC conversion.
5. Read the resulting VTS data in the ADC data register.

Vielleicht noch jemand Ideen?

von David (Gast)


Lesenswert?

So, Problem ist gelöst. Nach langer Google-Suche hatte ich Code gefunden 
der das selbe Problem beschrieb. Die Lösung ist relativ simpel.

Es gibt in den Low-Level-Treiben, speziell in stm32l4xxx_ll_adc.h ein 
Makro __LL_ADC_CALC_TEMPERATURE(...). Das berechnet auf magische Weise 
eine Temperatur von 30°C (ADC-Wert: 950), was gut der Temperatur in 
meinem Raum entspricht.

Das Makro selber hab ich noch nicht zerpflückt, aber es wird wohl mehr 
gerechnet als es im Reference Manual steht.

von Helmut64 (Gast)


Lesenswert?

Mal ein Frage, gibst Du bei "__LL_ADC_CALC_TEMPERATURE()" die aktuelle 
Betriebsspannung mit ein oder fest den Wert 3300.

Bei 3302 gibt es bei mir Fehler (Overflow)

Zusätzlich war am Anfang noch ein HAL_ADC_DeInit(&hadc1) notwendig, 
ansonsten geht es nicht zuverlässig.


Gruß Helmut

von Helmut64 (Gast)


Lesenswert?

Sorry ich meinte 3002 geht nicht. (also 3V).

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.