Interface LM35 temperature sensor

Solving Approach:

How do you plan to solve it?

  1. Create a Project
    • Open STM32CubeIDE, start a new project, and select the NUCLEO-F103RB board.
  2. Basic Configuration (via CubeMX inside CubeIDE)
    • Clock: Use the default HSI oscillator with PLL enabled (as configured in SystemClock_Config).
    • GPIO: Enable clocks for PORTA, PORTB, PORTC, and PORTD.
    • ADC Configuration
      • Two ADC peripherals used: ADC1 and ADC2.
      • ADC1
        1. Channel: ADC_CHANNEL_0 (PA0).
        2. Mode: Single conversion, software-triggered.
        3. Resolution: 12-bit (0–4095).
      • ADC2
        1. Channel: ADC_CHANNEL_1 (PA1).
        2. Same settings as ADC1.
      • Sampling time: 239.5 cycles for better accuracy.
      • Both ADCs use polling mode for conversion.
    • USART2: Enabled at 115200 baud, 8-N-1.
  3. Code Generation
    • CubeMX will automatically generate all the startup code, including:
      • HAL_Init() → Initializes HAL and system tick.
      • SystemClock_Config() → Configures system clock (HSI + PLL).
      • MX_GPIO_Init() → Initializes GPIO ports.
      • MX_USART2_UART_Init() → Configures UART2.
      • MX_ADC1_Init() → Configures ADC1 for analog input.
      • MX_ADC2_Init() → Configures ADC2 for analog input.
    • This code sets up the hardware and prepares the project for firmware development, so we only need to add our application logic in the user code sections

 

Code

/*Paste your code here*/
#include<string.h>
#include<stdio.h>
#define ADC_SAMPLES 100       // Number of samples for averaging
#define ADC_RESOLUTION 4096   // 12-bit ADC resolution
#define REFERENCE_VOLTAGE 3.28f //Measured Reference voltage

uint32_t adcValues[2];    // Buffer for two channels
char uartBuffer[64];   // Buffer for UART message
hile (1) {
  uint32_t sumCh0 = 0, sumCh1 = 0;
  uint8_t validSamplesCh0 = 0, validSamplesCh1 = 0;
  float voltageDiff = 0;
  int16_t tempValue = 0;
  int16_t tempDecimalValue = 0;

  // Take multiple samples for averaging
  for (int i = 0; i < ADC_SAMPLES; i++) {
    // Read channel 0
    HAL_ADC_Start(&hadc1);
    if (HAL_ADC_PollForConversion(&hadc1, 20) == HAL_OK) {
      sumCh0 += HAL_ADC_GetValue(&hadc1);
      validSamplesCh0++;
    }

    // Read channel 1
    HAL_ADC_Start(&hadc2);
    if (HAL_ADC_PollForConversion(&hadc2, 20) == HAL_OK) {
      sumCh1 += HAL_ADC_GetValue(&hadc2);
      validSamplesCh1++;
    }
  }

  // Calculate average values only if we have valid samples
  if (validSamplesCh0 > 0 && validSamplesCh1 > 0) {
    adcValues[0] = sumCh0 / validSamplesCh0;
    adcValues[1] = sumCh1 / validSamplesCh1;

    // Calculate absolute difference once
    uint32_t adcDiff =
      (adcValues[0] >= adcValues[1]) ? (adcValues[0] - adcValues[1]) : (adcValues[1] - adcValues[0]);

    if (adcDiff != 0) {
      voltageDiff = (REFERENCE_VOLTAGE * adcDiff) / ADC_RESOLUTION;
    }

    if (voltageDiff != 0) {
      tempValue = voltageDiff * 100;
      tempDecimalValue = (int16_t)(voltageDiff * 10000) % 100;
    }


    // Format message based on which channel is higher
    if (adcValues[0] >= adcValues[1]) {
      sprintf(uartBuffer, "Temperature: %u.%u Degree Celsius \r\n",
              tempValue, tempDecimalValue);
    } else {
      sprintf(uartBuffer, "Temperature: -%u.%u Degree Celsius \r\n",
              tempValue, tempDecimalValue);
    }

    // Send Temperature value on UART
    HAL_UART_Transmit(&huart2, (uint8_t*)uartBuffer,
                      strlen(uartBuffer), HAL_MAX_DELAY);
  } else {
    // Handle error case if needed
    sprintf(uartBuffer, "ADC read error\r\n");
    HAL_UART_Transmit(&huart2, (uint8_t*)uartBuffer,
                      strlen(uartBuffer), HAL_MAX_DELAY);
  }

  HAL_Delay(1000);
}
 

Output

Video

Add video of output (know more)

 

 

 

 

 

Photo of Output

Add a photo of your hardware showing the output.

 

 

 

 

Upvote
Downvote

Submit Your Solution

Note: Once submitted, your solution goes public, helping others learn from your approach!