Skip to main content
Graduate II
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);
}

 

    This topic has been closed for replies.

    1 reply

    Super User
    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.

    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 ...