Voltage Tracking, UART Control and Temperature-Based PWM Regulation Implementation for STM32

Periodic Voltage Sampling

ADC voltage sampling is triggered every 100ms via timer interrutp:

void HAL_TIM_PeriodElapsedCallback(TIM_HandleTypeDef *htim)
{
	if(htim->Instance == TIM1)
	{
		read_adc_voltage();
	}
}

ADC configuration is omitted here, the sampling function witth averaging filtering is implemented as follows:

uint32_t adc_samples[10];
int init_counter = 0;
float current_voltage;
float max_voltage;
float min_voltage;
float prev_voltage;
uint8_t voltage_trend;

void read_adc_voltage()
{
	HAL_ADC_Start_DMA(&hadc2, (uint32_t *)adc_samples, 10);

	uint32_t raw_sum = 0;
	for(int i = 0; i < 10; i++)
	{
		raw_sum += adc_samples[i];
	}
	
	float avg_raw = raw_sum / 10.0f;
	current_voltage = 3.3f * avg_raw / 4096.0f;
	
	// Initialize min/max values, run twice to avoid zero error from first sample
	if(init_counter < 2)
	{
		max_voltage = current_voltage;
		min_voltage = current_voltage;
		prev_voltage = current_voltage;
		init_counter++;
		voltage_trend = 1; // 1 = rising by default
	}
}

Update maximum and minimum voltage records:

void update_voltage_extremes()
{
	if (current_voltage > max_voltage) max_voltage = current_voltage;
	if (current_voltage < min_voltage) min_voltage = current_voltage;
}

Update voltage change trend:

// Trend codes: 1 = rising, 2 = falling
void update_voltage_trend()
{
	if((uint8_t)current_voltage > (uint8_t)prev_voltage)
	{
		voltage_trend = 1;
	}
	else if((uint8_t)current_voltage < (uint8_t)prev_voltage)
	{
		voltage_trend = 2;
	}
	prev_voltage = current_voltage;
}

Main loop execusion flow:

while (1)
{
	update_voltage_extremes();
	update_voltage_trend();
	update_lcd_display();
	adjust_pwm_from_temp();
}

LCD Display Implementation

char lcd_buffer[32];
void update_lcd_display()
{
	memset(lcd_buffer, 0, sizeof(lcd_buffer));
	sprintf(lcd_buffer,

Tags: STM32 ADC Sampling UART Communication PWM Control Temperature Sensing

Posted on Sat, 09 May 2026 08:16:01 +0000 by j.smith1981