How to LOG Sensors data into SD card using FreeRTOS

We have already covered how to use ADC, DHT11, SD CARD, and FreeRTOS. Today in this tutorial, we will combine them all. We will read the data from Potentiometre, which is connected via ADC, also read from DHT11 temperature sensor, and we will write this data to the SD card. This entire process will take place in different tasks of FreeRTOS.

CubeMX Setup

basic setup
basic setup

Above is the setup for ADC, where we will use channel 1. TIM7 is used for microseconds delay, which will be needed for the DHT11 sensor to operate. TIM1 is used as a periodic delay, where an interrupt will be triggered every 2 seconds. We will use this interrupt to release a semaphore for DHT11 task to operate.

Other than the above setup, we also need to turn on the FATFS, FreeRTOS, and SPI. You can download the code and check the *.ioc file for more setup related information, or watch the video linked below for explanation of this setup used.

Some more Setup is required with the libraries, so i would advise you watch the video below.

Some insight into the CODE

uint16_t ADC_VAL;
int Temperature, Humidity;

xTaskHandle ADC_Task_Hnadler;
xTaskHandle DHT_Task_Hnadler;
xTaskHandle SDCARD_Task_Hnadler;

xSemaphoreHandle DHT_SEM;

Above, i have created variables to store ADC and Temperature Data. Also, three task handlers have been defined along with 1 semaphore handler.


Inside the main function, I am creating the files, where the data will be updated later by the tasks.

DHT_SEM = xSemaphoreCreateBinary();

xTaskCreate(DHT_Task, "DHT", 128, NULL, 1, &DHT_Task_Hnadler);
xTaskCreate(ADC_Task, "ADC", 128, NULL, 2, &ADC_Task_Hnadler);
xTaskCreate(SDCARD_Task, "SD", 128, NULL, 3, &SDCARD_Task_Hnadler);

HAL_TIM_Base_Start(&htim7);  // us delay timer
HAL_TIM_Base_Start_IT(&htim1); // periodic delay timer


Now we will create the semaphore, and the three tasks. Here, SDCARD_Task is given highest priority, because we don’t want any other task to preempt it, while the task is accessing the SD CARD. In that case, a failure of drive might occur.
Start the TIM7 normally, and TIM1 in interrupt mode. This is because the TIM1 will generate the periodic interrupt in every 2 seconds.

And finally we will start the scheduler.

void ADC_Task (void *argument)
	while (1)
		HAL_ADC_PollForConversion(&hadc1, 10);
		ADC_VAL = HAL_ADC_GetValue(&hadc1);


ADC_Task will run every 500 ms. Where it will store the ADC value in the variable (ADC_VAL) using PollForConversion method.

void DHT_Task (void *argument)
	while (1)
		if (xSemaphoreTake(DHT_SEM, 2500) != pdTRUE)
			HAL_UART_Transmit(&huart2, (uint8_t *) "Unable to acquire semaphore\n", 28, 100);

			DHT11_Get_Data(&Temperature, &Humidity);

DHT_Task will run only after acquiring the semaphore. The semaphore will be released by the TIM1 periodically every 2 seconds. After acquiring the semaphore, DHT11_Get_Data function will store the Temp and Rh values in the Temperature and Humidity variables.
The semaphore part is just to bring variation in this program. Ofcourse you can just use the vTaskDelay to run this task every 2 seconds.

void SDCARD_Task (void *argument)
	int indx=1;
	while (1)
		char *buffer = pvPortMalloc(50*sizeof(char));
		sprintf (buffer, "%d. %u\n", indx,ADC_VAL);
		Update_File("ADC_DATA.TXT", buffer);
		sprintf (buffer, "%d. Temp = %d C\t RH = %d \n",indx, Temperature, Humidity);
		Update_File("TEMP.TXT", buffer);



SDCARD_Task will run every 1 second, and update the data in the files. indx variable is used for indexing.



You can see above that two files were created in the SD CRAD, and the recorded data is written to the files. For more details, watch the video below

Check out the VIDEO Below


You can buy me a coffee Sensor by clicking DONATE OR Just click DOWNLOAD to download the code

Notify of
Oldest Most Voted
Inline Feedbacks
View all comments