Non Blocking LED Blink Function

Amorphous
Posts: 7
Joined: Mon Nov 21, 2022 3:09 pm

Non Blocking LED Blink Function

Postby Amorphous » Wed Dec 07, 2022 6:28 pm

Hi All,

I am trying to build LED blinking functions at different speeds, to denote the connection status of the wifi. A simple while(1) like this :

Code: Select all

void led_fast(){
	ESP_LOGI(TAG, "LED FAST INITIATED");
	while (1) {
	        gpio_set_level(LED,0);
	        vTaskDelay(500/portTICK_RATE_MS);
	        gpio_set_level(LED,1);
	        vTaskDelay(500/portTICK_RATE_MS);
	    }

}
however blocks the rest of the code, so I am unable to use that.

Is it possible to use the LEDC peripheral to make the LED blink at variable speeds and switch it on/off? Is there any example code for the same?

Thanks in advance!

User avatar
mbratch
Posts: 303
Joined: Fri Jun 11, 2021 1:51 pm

Re: Non Blocking LED Blink Function

Postby mbratch » Thu Dec 08, 2022 3:42 am

Probably many ways to do this.

One way would be to set up a FreeRTOS message queue which your while loop can scan. Send it a message from another task to change the delay time.

You could also unit the task with a pointer to a static variable that defines the delay time and use that instead of hard coding it. I like this option the least although it's probably the simplest.

You could flash your LED using a software timer instead of a task. The timer API has a function for changing the timers period.

Amorphous
Posts: 7
Joined: Mon Nov 21, 2022 3:09 pm

Re: Non Blocking LED Blink Function

Postby Amorphous » Thu Dec 08, 2022 9:15 am

Thanks for your response.

I was trying to do something similar to the first option. I created a Task like this :

Code: Select all

void create_led_blink_tasks(){
		BaseType_t xReturned;

		xReturned = xTaskCreate(&led_blink,"LED_BLINK",2048,NULL,5,&led_task_handle);

	    if(xReturned == pdPASS )
	       {
	           /* The task was created.  Use the task's handle to delete the task. */
	           ESP_LOGI(TAG, "LED BLINK TASK CREATED");
	       }

}
LED Blink Function as below :

Code: Select all

void led_blink(){
	ESP_LOGI(TAG, "LED SLOW INITIATED");
	while (1) {
	
		g_led_duration = get_duration();
		ESP_LOGI(TAG, "LED SLOW BLINKING");
	        gpio_set_level(LED,0);
	        vTaskDelay(g_led_duration/portTICK_RATE_MS);
	        gpio_set_level(LED,1);
	        vTaskDelay(g_led_duration/portTICK_RATE_MS);
	        
	    }
}
Where g_led_duration is a variable that can be set by other functions depending on the requirement.

Now when I need to stop the LED Blinking (at this time, I need the LED to be either ON or OFF, not blinking), I am doing the following :

Code: Select all

void delete_led_blink_task()
{
ESP_LOGI(TAG, "LED TASK DELETED");
vTaskDelete(led_task_handle);

}
But doesn't seem to be working. What am I doing wrong?

User avatar
mbratch
Posts: 303
Joined: Fri Jun 11, 2021 1:51 pm

Re: Non Blocking LED Blink Function

Postby mbratch » Thu Dec 08, 2022 3:40 pm

Can you explain further about it not working? What you're showing is part of the solution and it seems ok depending upon what your other code is doing. Although rather than delete the task you could just stop/pause it.

Alternatively, you could define duration of 0 to mean steady off and some other (probably very large) value to mean always on and you just add logic to handle it. Then you don't have to stop and start the task. It would just run all the time.

Amorphous
Posts: 7
Joined: Mon Nov 21, 2022 3:09 pm

Re: Non Blocking LED Blink Function

Postby Amorphous » Fri Dec 09, 2022 6:13 am

I have implemented another method to try to do it, but seems to be a problem again.

In the files I have uploaded here :

https://github.com/Abhesheksh/led-message-code

In gpio.c (https://github.com/Abhesheksh/led-messa ... ain/gpio.c) I have the following functions :

Code: Select all

BaseType_t led_send_message(led_messages_e led_msgID)
{

		led_queue_message_t led_msg;
		led_msg.led_message = led_msgID;

		return xQueueSend(led_queue_handle, &led_msg, portMAX_DELAY);

}

void led_task(void){

	led_queue_message_t msg;
	uint32_t blink_duration = 1000;

//	led_send_message(LED_BLINK_FAST_START);

	while(1){

		if (xQueueReceive(led_queue_handle, &msg, portMAX_DELAY))
			{
				switch(msg.led_message)
				{
				case LED_BLINK_SLOW_START:

					ESP_LOGI(TAG, "LED_BLINK_SLOW_START");
					led_blink_function(1000);
					xQueueReset(led_queue_handle);
					break;

				case LED_BLINK_SLOW_STOP:
					ESP_LOGI(TAG, "LED_BLINK_SLOW_STOP");
					suspend_led_task();


					break;

				case LED_BLINK_FAST_START:

					ESP_LOGI(TAG, "LED_BLINK_FAST_START");
					led_blink_function(1000);

					break;

				case LED_BLINK_FAST_STOP:
					ESP_LOGI(TAG, "LED_BLINK_FAST_STOP");
					led_blink_function(2000);
					suspend_led_task();

					break;

				case LED_BLINK_STOP:
					ESP_LOGI(TAG, "LED_BLINK_STOP");
					suspend_led_task();

					break;

				default:
					break;
				}
			}
	}
}

Initialization here :

Code: Select all

void gpio_main(void)
{

    gpio_config_t io_conf;
    //disable interrupt
    io_conf.intr_type = GPIO_INTR_DISABLE;
    //set as output mode
    io_conf.mode = GPIO_MODE_OUTPUT;
    //bit mask of the pins that you want to set,e.g.GPIO15/16
    io_conf.pin_bit_mask = GPIO_OUTPUT_PIN_SEL;
    //disable pull-down mode
    io_conf.pull_down_en = 0;
    //disable pull-up mode
    io_conf.pull_up_en = 0;
    //configure GPIO with the given settings
    gpio_config(&io_conf);

    gpio_set_level(RELAY, 0);
    gpio_set_level(LED, 0);

    led_queue_handle = xQueueCreate(5,sizeof(led_queue_message_t));

    xTaskCreate(&led_task, "led_task", 4096, NULL, 5, &led_task_handle);


}
I am calling this function "led_send_message" in my other file wifi_app.c (https://github.com/Abhesheksh/led-messa ... wifi_app.c) but only first message is received (line 47) and the second message sent on line 193 is not received even though the function returns pdTrue. So the LED keeps blinking as per the first message and no further messages are received by the xQueueReceive function. What am I doing wrong?

Amorphous
Posts: 7
Joined: Mon Nov 21, 2022 3:09 pm

Re: Non Blocking LED Blink Function

Postby Amorphous » Fri Dec 09, 2022 11:26 am

mbratch wrote:
Thu Dec 08, 2022 3:42 am
Probably many ways to do this.

One way would be to set up a FreeRTOS message queue which your while loop can scan. Send it a message from another task to change the delay time.

You could also unit the task with a pointer to a static variable that defines the delay time and use that instead of hard coding it. I like this option the least although it's probably the simplest.

You could flash your LED using a software timer instead of a task. The timer API has a function for changing the timers period.
It goes into a infinite loop even after I try to suspend or delete the task.

Amorphous
Posts: 7
Joined: Mon Nov 21, 2022 3:09 pm

Re: Non Blocking LED Blink Function

Postby Amorphous » Fri Dec 09, 2022 11:32 am

Ok now it seems I did not include the following line in my code which did not allow me to suspend or delete my tasks :


#define INCLUDE_vTaskSuspend 1

Now it works okay. ;)

Who is online

Users browsing this forum: Bing [Bot] and 79 guests