---
# System prepended metadata

title: How to calibrate temperature on STM32 IoT device?
tags: [stm32]

---

Calibrating the [temperature sensor](https://www.onzuu.com/category/temperature-sensors) on an [STM32](https://www.ampheo.com/search/STM32) IoT device (like the [B-L475E-IOT01A](https://www.onzuu.com/search/B-L475E-IOT01A) with [HTS221](https://www.ampheo.com/product/hts221tr-26836612) or similar boards) is crucial for accurate readings. Here's a comprehensive guide:
![STM32-Blue-Pill-DS18B20-Sensor-with-OLED-view-temperature-readings](https://hackmd.io/_uploads/HyYpmojalg.jpg)

**Types of STM32 Temperature Sensors**
**1. Internal Die Temperature Sensor** 
* Built into the STM32 MCU core
* Measures the chip's junction temperature
* Less accurate (± few °C) but useful for monitoring chip temperature

**2. External Humidity/Temperature Sensors (HTS221 on IoT Node)**
* More accurate for ambient temperature
* Typically ±0.5°C accuracy (can be improved with calibration)

3. Dedicated Temperature ICs (if connected externally)
**Method 1: Calibrating the Internal Die Sensor**
The internal sensor requires a 2-point calibration for reasonable accuracy.

**Calibration Procedure:**
**1. Read the Factory Calibration Data**
STM32 chips have factory-calibrated temperature values stored in system memory.

```
c

// For STM32L4 series (check your reference manual for addresses)
#define TEMP30_CAL_ADDR  ((uint16_t*) ((void*) 0x1FFF75A8))
#define TEMP130_CAL_ADDR ((uint16_t*) ((void*) 0x1FFF75CA))
#define VREFINT_CAL_ADDR ((uint16_t*) ((void*) 0x1FFF75AA))

// Read calibration values
uint16_t temp30_cal = *TEMP30_CAL_ADDR;
uint16_t temp130_cal = *TEMP130_CAL_ADDR;
uint16_t vrefint_cal = *VREFINT_CAL_ADDR;
```
**2. Implementation Code**

```
c

float read_calibrated_internal_temp(ADC_HandleTypeDef* hadc) {
    uint32_t vrefint_raw, tsense_raw;
    float temperature;
    
    // Read VREFINT and temperature sensor
    HAL_ADC_Start(hadc);
    vrefint_raw = read_adc_channel(hadc, ADC_CHANNEL_VREFINT);
    tsense_raw = read_adc_channel(hadc, ADC_CHANNEL_TEMPSENSOR);
    HAL_ADC_Stop(hadc);
    
    // Calculate actual VREFINT voltage (from calibration)
    float vrefint_voltage = (3.0f * vrefint_cal) / vrefint_raw;
    
    // Calculate temperature using 2-point calibration
    temperature = ((float)(tsense_raw - temp30_cal)) 
                  * (130.0f - 30.0f) 
                  / (temp130_cal - temp30_cal) 
                  + 30.0f;
    
    return temperature;
}
```
**Method 2: Calibrating External HTS221 Sensor (STM32 IoT Node)**
The HTS221 humidity/temperature sensor is much more accurate and easier to calibrate.

**One-Point Offset Calibration:**
**1. Reference Measurement**

* Use a calibrated, accurate thermometer as reference
* Place both [sensors](https://www.ampheo.com/c/sensors) in a stable temperature environment
* Wait for temperatures to stabilize (15-30 minutes)

**2. Calculate Offset**

```
c

// Pseudo-code for offset calculation
float reference_temp = 23.5f; // From calibrated thermometer
float hts221_temp = read_hts221_temperature(); // Raw reading

// Calculate calibration offset
float temp_offset = reference_temp - hts221_temp;

// Store this offset in non-volatile memory
store_calibration_data(temp_offset, 0, 0); // Store offset, 0, 0 for 1-point cal
```

**3. Apply Calibration**

```
c

float read_calibrated_temperature(void) {
    float raw_temp = read_hts221_temperature();
    float temp_offset = load_temp_offset(); // Load from Flash/EEPROM
    return raw_temp + temp_offset;
}
```
**Two-Point Calibration (More Accurate):**
**1. Take measurements at two different known temperatures**

```
c

// Calibration at point 1 (e.g., room temperature)
float ref_temp1 = 25.0f;
float raw_temp1 = read_hts221_temperature();

// Calibration at point 2 (e.g., warmer environment)
float ref_temp2 = 35.0f; 
float raw_temp2 = read_hts221_temperature();

// Calculate gain and offset
float gain = (ref_temp2 - ref_temp1) / (raw_temp2 - raw_temp1);
float offset = ref_temp1 - (raw_temp1 * gain);
```
**2. Apply Two-Point Calibration**

```
c

float apply_two_point_calibration(float raw_temp) {
    float gain = load_temp_gain();
    float offset = load_temp_offset();
    return (raw_temp * gain) + offset;
}
```
**Method 3: Multi-Point Calibration with Curve Fitting**
For highest accuracy across a wide temperature range:

```
c

// Take multiple reference points
typedef struct {
    float reference_temp;
    float sensor_reading;
} cal_point_t;

// Example calibration points
cal_point_t cal_points[] = {
    {15.0f, 14.8f},
    {25.0f, 24.7f},
    {35.0f, 34.6f},
    {45.0f, 44.4f}
};

// Calculate polynomial coefficients (linear fit for simplicity)
void calculate_calibration_coefficients(float* slope, float* intercept) {
    float sum_x = 0, sum_y = 0, sum_xy = 0, sum_xx = 0;
    int n = sizeof(cal_points) / sizeof(cal_points[0]);
    
    for (int i = 0; i < n; i++) {
        sum_x += cal_points[i].sensor_reading;
        sum_y += cal_points[i].reference_temp;
        sum_xy += cal_points[i].sensor_reading * cal_points[i].reference_temp;
        sum_xx += cal_points[i].sensor_reading * cal_points[i].sensor_reading;
    }
    
    *slope = (n * sum_xy - sum_x * sum_y) / (n * sum_xx - sum_x * sum_x);
    *intercept = (sum_y - *slope * sum_x) / n;
}
```
**Complete Implementation for STM32 IoT Node**
**HTS221 Calibration Example:**
```
c

#include "hts221.h"
#include "stdio.h"

// Calibration structure
typedef struct {
    float temp_offset;
    float temp_gain;
    uint8_t calibrated;
} temp_calibration_t;

temp_calibration_t temp_cal = {0.0f, 1.0f, 0};

void calibrate_temperature_sensor(float known_reference_temp) {
    float raw_temp;
    float temp_sum = 0;
    int num_samples = 100;
    
    // Take multiple samples for stability
    for (int i = 0; i < num_samples; i++) {
        HTS221_GetTemperature(&raw_temp);
        temp_sum += raw_temp;
        HAL_Delay(100);
    }
    
    float avg_raw_temp = temp_sum / num_samples;
    
    // Simple one-point offset calibration
    temp_cal.temp_offset = known_reference_temp - avg_raw_temp;
    temp_cal.calibrated = 1;
    
    printf("Calibration complete:\n");
    printf("Reference: %.2f°C, Sensor: %.2f°C, Offset: %.2f°C\n", 
           known_reference_temp, avg_raw_temp, temp_cal.temp_offset);
    
    // Save to Flash
    save_calibration_data();
}

float read_calibrated_temperature(void) {
    float raw_temp;
    HTS221_GetTemperature(&raw_temp);
    
    if (temp_cal.calibrated) {
        return raw_temp + temp_cal.temp_offset;
    } else {
        return raw_temp; // Return uncalibrated with warning
    }
}
```
**Storage in Flash Memory:**
```
c

#define CALIBRATION_FLASH_ADDR 0x0801F000  // Last sector of Flash

void save_calibration_data(void) {
    HAL_FLASH_Unlock();
    
    // Erase page
    FLASH_EraseInitTypeDef erase;
    erase.TypeErase = FLASH_TYPEERASE_PAGES;
    erase.Page = 127; // Adjust for your MCU
    erase.NbPages = 1;
    
    uint32_t error;
    HAL_FLASHEx_Erase(&erase, &error);
    
    // Write data
    uint32_t* data = (uint32_t*)&temp_cal;
    for (int i = 0; i < sizeof(temp_cal)/4; i++) {
        HAL_FLASH_Program(FLASH_TYPEPROGRAM_WORD, 
                         CALIBRATION_FLASH_ADDR + i*4, 
                         data[i]);
    }
    
    HAL_FLASH_Lock();
}

void load_calibration_data(void) {
    temp_calibration_t* stored_cal = (temp_calibration_t*)CALIBRATION_FLASH_ADDR;
    
    if (stored_cal->calibrated == 1) {
        temp_cal = *stored_cal;
        printf("Loaded calibration: offset=%.2f, gain=%.2f\n", 
               temp_cal.temp_offset, temp_cal.temp_gain);
    }
}
```
**Practical Calibration Setup**
**Equipment Needed:**
1. Reference thermometer (accurate to ±0.1°C or better)
2. Temperature-controlled environment (or stable room temperature)
3. Thermal insulation to ensure both sensors at same temperature
4. Adequate stabilization time (15-30 minutes)

**Calibration Process:**
1. Place sensors in close thermal contact
2. Wait for stabilization - minimum 15 minutes
3. Record reference temperature
4. Take multiple sensor readings (average them)
5. Calculate calibration parameters
6. Store parameters in non-volatile memory
7. Verify with a different known temperature

**Environmental Considerations:**
* Avoid self-heating: Don't place sensors near MCU or other heat sources
* Ensure good airflow for ambient temperature sensing
* Avoid direct sunlight or heat sources
* Allow thermal stabilization after power-on

**Validation and Testing**
```
c

void validate_calibration(void) {
    printf("Calibration Validation:\n");
    printf("======================\n");
    
    for (int i = 0; i < 10; i++) {
        float cal_temp = read_calibrated_temperature();
        printf("Reading %d: %.2f°C\n", i+1, cal_temp);
        HAL_Delay(1000);
    }
    
    // Check stability
    float min_temp = 100.0f, max_temp = -100.0f, sum = 0;
    for (int i = 0; i < 50; i++) {
        float temp = read_calibrated_temperature();
        min_temp = fminf(min_temp, temp);
        max_temp = fmaxf(max_temp, temp);
        sum += temp;
        HAL_Delay(200);
    }
    
    printf("Stability: Min=%.2f°C, Max=%.2f°C, Avg=%.2f°C\n", 
           min_temp, max_temp, sum/50);
}
```
This approach will significantly improve your [STM32](https://www.ampheoelec.de/search/STM32) IoT device's temperature measurement accuracy, typically achieving ±0.5°C accuracy or better with proper calibration.