# STM32 - Sampling ADC value at known regular time intervals

I am working on a simple microcontroller based proportional controller to regulate the temperature of a heater cartridge using a feedback thermistor. I'm using the 'black pill' STM32F103C8T6 and have the controller working however I would like to send out time stamp and temperature readings over UART so that I can plot a graph of the temperature output vs time and use the Ziegler-Nichols method to obtain integral and derivative values (by obtaining the ultimate period of oscillation and ultimate gain).

I played around with DMA mode and ADC but had a lot of troubles so ended up using the simple polling method mentioned in the answer here:

The controller works in the main loop:

 /* USER CODE BEGIN 2 */
/* USER CODE END 2 */

/* Infinite loop */
/* USER CODE BEGIN WHILE */
while (1)
{

temperatureInDegrees = read_temp(waxThermistor); //Calculates the value in degrees using a look up table
}

if(heater==1){
HAL_TIM_PWM_Start(&htim3, TIM_CHANNEL_1); //PWM for heater element
heater = 0;
}

int currentTemperature = temperatureInDegrees;
int pi = PI(30,currentTemperature,50,0); //returns the controller value P + I
int actuate = limitActuation(pi,0,500); //Limits the actuation range between 0% and 50% duty cycle
htim3.Instance->CCR1 = actuate; //Sets the duty cycle
sendTemperature(currentTemperature); //transmits the temperature over UART
/* USER CODE END WHILE */


I would like to be able to send out a time value along with the temperature. I tried removing the polling and placing waxThermistor = HAL_ADC_GetValue(&hadc1);in the interrupt routine for a 20ms timer (using OC mode) however I no longer get any PWM output as the ADC value is just returning 0 all the time. Could anyone recommend a better method for ADC sampling at a regular known interval rather than polling like this?

One possible solution I thought of would be to setup the ADC to trigger conversion on a timer and then read the sample in the conversion complete callback function. The time elapsed would then be the time between triggers + time taken for conversion to complete which can be calculated through the formulas given here. Would this be a viable solution?

For example if sampling every 20ms, the data sent out over UART would look like:

0ms;25c\n
20ms;27c\n
40ms;35c\n

• You should configure the Timer & ADC such that the Timer directly triggers the ADC to perform a conversion, and then use the ADC's Conversion-Complete interrupt to read the result. You shouldn't need to use the TImer's interrupt and write code to start the ADC there. – brhans Sep 27 '20 at 19:17