Skip to main content
Associate III
February 19, 2024
Question

Grouping sensors connected to the same ADC and schedule them at different rate in FreeRTOS.

  • February 19, 2024
  • 1 reply
  • 2196 views

Say that I have the following set of sensors: s1,s2,s3, s4, s5 and s6.

I want the set (s1,s2,s3) to be scheduled at 100ms, s4 every 200ms and the set (s5,s6) every second. 

My gut feeling suggests me to create three periodic tasks task1, task2 and task3 that calls `sensor_set1()`, `sensor_set2()` and `sensor_set3()`, respectively.

The problem here is that all the sensors are connected in the same ADC, and therefore, at the beginning of each function call I should re-configure the ADC.

My idea is to do something like the following but I don't know if it is correct or not. Any help? :)

sensor_set1(){
 hadc1.Init.ScanConvMode = ENABLE;
 hadc1.Init.NbrOfConversion = 3;

 sConfig.Channel = ADC_CHANNEL_1;
 sConfig.Rank = 1;
 sConfig.SamplingTime = ADC_SAMPLETIME_3CYCLES;
 HAL_ADC_ConfigChannel(&hadc1, &sConfig);

 sConfig.Channel = ADC_CHANNEL_2;
 sConfig.Rank = 2;
 sConfig.SamplingTime = ADC_SAMPLETIME_3CYCLES;
 HAL_ADC_ConfigChannel(&hadc1, &sConfig);

 sConfig.Channel = ADC_CHANNEL_3;
 sConfig.Rank = 3;
 sConfig.SamplingTime = ADC_SAMPLETIME_3CYCLES;
 HAL_ADC_ConfigChannel(&hadc1, &sConfig);

 HAL_ADC_Start_DMA(&hadc1, &analog_readSet1, 3);
 xSemaphoreTake(xSemaphoreADC_PV, portMAX_DELAY); // Wait for ADC EOC
 HAL_ADC_Stop_DMA(&hadc1);
}

sensor_set2(){
 hadc1.Init.ScanConvMode = DISABLE;
 hadc1.Init.NbrOfConversion = 1;

 sConfig.Channel = ADC_CHANNEL_4;
 sConfig.Rank = 1;
 sConfig.SamplingTime = ADC_SAMPLETIME_3CYCLES;
 HAL_ADC_ConfigChannel(&hadc1, &sConfig);

 HAL_ADC_Start_DMA(&hadc1, &analog_readSet2, 1);
 xSemaphoreTake(xSemaphoreADC_PV, portMAX_DELAY); // Wait for ADC EOC
 HAL_ADC_Stop_DMA(&hadc1);
}

sensor_set3(){
 hadc1.Init.ScanConvMode = ENABLE;
 hadc1.Init.NbrOfConversion = 2;

 sConfig.Channel = ADC_CHANNEL_5;
 sConfig.Rank = 1;
 sConfig.SamplingTime = ADC_SAMPLETIME_3CYCLES;
 HAL_ADC_ConfigChannel(&hadc1, &sConfig

 sConfig.Channel = ADC_CHANNEL_6;
 sConfig.Rank = 2;
 sConfig.SamplingTime = ADC_SAMPLETIME_3CYCLES;
 HAL_ADC_ConfigChannel(&hadc1, &sConfig);

 HAL_ADC_Start_DMA(&hadc1, &analog_readSet3, 2);
 xSemaphoreTake(xSemaphoreADC_PV, portMAX_DELAY); // Wait for ADC EOC
 HAL_ADC_Stop_DMA(&hadc1);
}

 

1 reply

TDK
February 19, 2024

Convert all 6 channels every 100ms and ignore the result of channels that don't need captured that quickly. Read every other result on s4 and every 10th result on s5, s6.

(Changing hadc1.Init without re-initializing the peripheral will not have any effect.)

> ADC_SAMPLETIME_3CYCLES

For the sake of accuracy, this could be much higher.

"If you feel a post has answered your question, please click ""Accept as Solution""."
Andrew Neil
Super User
February 19, 2024

Or, a slight variation on that, have a single task that's called every 100ms

The Task always does s1,s2,s3, and maintains a count so that it knows when to also do the others ...

A complex system that works is invariably found to have evolved from a simple system that worked.A complex system designed from scratch never works and cannot be patched up to make it work.