My first code ever in C, how do you rate it?
Posted: Tue Jul 07, 2026 6:31 pm
I know I've used some overkill features like interrupts, but I wanted to experiment.
Initially I hoped that the glitch filter would help me against the bounce of my button, but in the end I had to find an additional workaround, otherwise it often happened that the trigger would fire twice.
The purpose of this project is to explore different features of the ESP32 combined with Espressif's IDE to have two LEDs blink alternatively each second.
So far it works good, except for some occasional double triggers even the DEBOUNCE_MS value set to 50, 70 or 150ms.
I'll probably have to set it even higher, but one day I'd like to find a better solution for this issue, maybe by dropping any attempt to tie interrupts to physical input and just use a while() cycle.
Here is the main code:
and the header:
Initially I hoped that the glitch filter would help me against the bounce of my button, but in the end I had to find an additional workaround, otherwise it often happened that the trigger would fire twice.
The purpose of this project is to explore different features of the ESP32 combined with Espressif's IDE to have two LEDs blink alternatively each second.
So far it works good, except for some occasional double triggers even the DEBOUNCE_MS value set to 50, 70 or 150ms.
I'll probably have to set it even higher, but one day I'd like to find a better solution for this issue, maybe by dropping any attempt to tie interrupts to physical input and just use a while() cycle.
Here is the main code:
Code: Select all
#include <stdio.h>
#include "driver/gpio_filter.h"
#include "freertos/FreeRTOS.h"
#include "freertos/idf_additions.h"
#include "freertos/task.h"
#include "driver/gpio.h"
#include "hal/gpio_types.h"
#include "BlinkCycleFunctions.h"
extern bool is_cycle_running;
void app_main(void)
{
//create the binary semaphore then check success status
printf("Generating semaphore..\n");
BUTTON_semaphore_handle = xSemaphoreCreateBinary();
if(BUTTON_semaphore_handle == NULL){
printf("Failed to create the semaphore, the program is closed.\n");
return;
}
else{
printf("Success.\n");
}
//reset the GPIOs before a fresh session
printf("Resetting GPIOs for the new session...\n");
gpio_reset_pin(LED1);
gpio_reset_pin(LED2);
gpio_reset_pin(BUTTON);
//set the LED pins with a "compound literal" struct
printf("Setting GPIOs...\n");
gpio_config(&(gpio_config_t){
.pin_bit_mask = ((1ULL << (int)LED1) | (1ULL << (int)LED2)),
.mode = GPIO_MODE_OUTPUT,
.pull_up_en = GPIO_PULLUP_DISABLE,
.pull_down_en = GPIO_PULLDOWN_DISABLE,
.intr_type = GPIO_INTR_DISABLE
});
//set the button interrupt pin with a "compound literal" struct
gpio_config(&(gpio_config_t){
.pin_bit_mask = (1ULL << (int)BUTTON),
.mode = GPIO_MODE_INPUT,
.pull_up_en = GPIO_PULLUP_ENABLE,
.pull_down_en = GPIO_PULLDOWN_DISABLE,
.intr_type = GPIO_INTR_NEGEDGE
});
//set pin BUTTON to have glitch filter
gpio_glitch_filter_handle_t BUTTON_glitch_filter_handle;
gpio_new_pin_glitch_filter(&(gpio_pin_glitch_filter_config_t){
.clk_src = GLITCH_FILTER_CLK_SRC_DEFAULT,
.gpio_num = BUTTON
}, &BUTTON_glitch_filter_handle);
//enable the interrupt
printf("Enabling the interrupt...\n");
gpio_intr_enable(BUTTON);
//install ISR (interrupt handler service) with default flag "0"
printf("Installing the ISR service...\n");
gpio_install_isr_service(0);
//add my GPIO to the ISR attaching it to the function it triggers
printf("Attaching the interrupt to the function...\n");
gpio_isr_handler_add(BUTTON, BUTTON_interrupt_function, NULL);
//declare task, attached to previously declared handler
printf("Preparing the start-stop function task...\n");
xTaskCreate(
blink_manager_task,
"blink_manager",
2048,
NULL,
1,
&blink_manager_handle
);
printf("Preparing the blinking cycle task...\n");
xTaskCreate(
blink_cycle_task,
"blink_cycle",
2048,
NULL,
1,
&blink_cycle_handle
);
}
Code: Select all
#ifndef BLINKCYCLEFUNCTIONS_H_
#define BLINKCYCLEFUNCTIONS_H_
#include <stdio.h>
#include "freertos/FreeRTOS.h"
#include "freertos/projdefs.h"
#include "freertos/task.h"
#include "driver/gpio.h"
#include "soc/gpio_num.h"
#include "freertos/semphr.h"
#define LED1 GPIO_NUM_20
#define LED2 GPIO_NUM_21
#define BUTTON GPIO_NUM_10
//milliseconds to wait while the input bounces
#define DEBOUNCE_MS 70
TaskHandle_t blink_cycle_handle = NULL; //declare handle for blink cycle task
TaskHandle_t blink_manager_handle = NULL; //declare handle for blink manager task
SemaphoreHandle_t BUTTON_semaphore_handle; //declare the handle for the semaphore between the interrupt and blink manager task
bool is_cycle_running = 0; //flag to keep track if the cycle is running or not
//function to blink LEDs
void blink_cycle_task(void * pvParameters){
printf("Task ready to launch\n");
vTaskSuspend(NULL); //start task in suspended mode, won't start until the button is pushed for the first time
while (true) { //blink cycle
gpio_set_level(LED1, 1); //pin 20 on
vTaskDelay(pdMS_TO_TICKS(1000)); //delay 1sec
gpio_set_level(LED1,0); //pin 20 off
gpio_set_level(LED2, 1); //pin 21 on
vTaskDelay(pdMS_TO_TICKS(1000)); //delay 1sec
gpio_set_level(LED2,0); //pin 21 off
}
};
//function that's called when the button interrupt is pressed, resumes or suspends the task based on the flag's status
void BUTTON_interrupt_function(void *arg){
xSemaphoreGiveFromISR(BUTTON_semaphore_handle, NULL);
};
//this task takes in the semaphore from the button interrupt and manages the blinking cycle
void blink_manager_task(void * pvParameters){
while(1){
xSemaphoreTake(BUTTON_semaphore_handle, portMAX_DELAY); //xSemaphoreTake suspends the task indefinitely until the semaphore is given
if (is_cycle_running == 0){
vTaskResume(blink_cycle_handle);
is_cycle_running = 1;
printf("Start\n");
xSemaphoreTake(BUTTON_semaphore_handle, pdMS_TO_TICKS(DEBOUNCE_MS)); //if the bounce of the button raised the semaphore again, it is absorbed
}
else{
vTaskSuspend(blink_cycle_handle);
is_cycle_running = 0;
printf("Stop\n");
xSemaphoreTake(BUTTON_semaphore_handle, pdMS_TO_TICKS(DEBOUNCE_MS)); //if the bounce of the button raised the semaphore again, it is absorbed
}
}
};
#endif /* BLINKCYCLEFUNCTIONS_H_ */