Generate signal with timer

espmajds
Posts: 5
Joined: Fri Apr 12, 2024 7:52 am

Generate signal with timer

Postby espmajds » Fri Apr 12, 2024 8:12 am

I'm trying to generate a 100 kHz signal with ESP32 timers.
I tried to do this with the gptimer but the ESP32 keeps resetting!
Which timer can I use for this? How?

MicroController
Posts: 1706
Joined: Mon Oct 17, 2022 7:38 pm
Location: Europe, Germany

Re: Generate signal with timer

Postby MicroController » Fri Apr 12, 2024 10:13 am

saeidi_majid wrote:
Fri Apr 12, 2024 8:12 am
I'm trying to generate a 100 kHz signal with ESP32 timers.
That's not going to happen.
Which timer can I use for this? How?
Look into generating PWM in hardware, e.g. via the LEDC peripheral.

espmajds
Posts: 5
Joined: Fri Apr 12, 2024 7:52 am

Re: Generate signal with timer

Postby espmajds » Fri Apr 12, 2024 10:42 am

I tested it with LEDC and it works properly, but I want to know how to do it with GPTimer functions.
I've set the timer resolution to 1MHz, so each tick equals 1 microsecond. Therefore, if I set the alarm count value to 10, an interrupt occurs every 10 microseconds, during which I can toggle a port get my frequency
Now, when I do this, the ESP32 resets.
  1. #include <stdio.h>
  2. #include "freertos/FreeRTOS.h"
  3. #include "freertos/task.h"
  4. #include "freertos/queue.h"
  5. #include "driver/gptimer.h"
  6. #include "driver/gpio.h"
  7.  
  8. #define FREQ_OUT_PIN     GPIO_NUM_5
  9.  
  10. static QueueHandle_t timer_alarm_queue = NULL;
  11.  
  12. gptimer_handle_t gptimer = NULL;
  13.  
  14. typedef struct {
  15.     uint64_t event_count;
  16.     uint64_t event_alarm;
  17. }queue_element_t;
  18.  
  19. //************************************************************************************************************
  20. static bool IRAM_ATTR timrt_alarm_callback(gptimer_handle_t timer, const gptimer_alarm_event_data_t *edata, void *user_data)
  21. {
  22.     BaseType_t high_task_awoken = pdFALSE;
  23.  
  24.     queue_element_t queue_data = {
  25.             .event_count = edata->count_value,
  26.             .event_alarm = edata->alarm_value,
  27.     };
  28.  
  29.     xQueueSendFromISR(timer_alarm_queue, &queue_data, &high_task_awoken);
  30.    
  31.     return (high_task_awoken == pdTRUE);
  32. }
  33.  
  34. //************************************************************************************************************
  35. static void timer_alarm_task(void* arg)
  36. {
  37.     int isOn = 0;
  38.     queue_element_t data;
  39.  
  40.     while (true)
  41.     {
  42.         if(xQueueReceive(timer_alarm_queue, &data, portMAX_DELAY))
  43.         {
  44.             isOn =! isOn;
  45.             gpio_set_level(LED_GPIO, isOn);
  46.         }
  47.     }
  48. }
  49.  
  50. //************************************************************************************************************
  51. void app_main(void)
  52. {
  53.     gpio_set_direction(LED_GPIO, GPIO_MODE_OUTPUT);
  54.  
  55.     gptimer_config_t timer_config = {
  56.             .clk_src = GPTIMER_CLK_SRC_APB,
  57.             .direction = GPTIMER_COUNT_UP,
  58.             .resolution_hz = 1000000,
  59.             .intr_priority = 0,
  60.             .flags.intr_shared = false,
  61.     };
  62.  
  63.     gptimer_new_timer(&timer_config, &gptimer);
  64.  
  65.     gptimer_event_callbacks_t timerCallback = {
  66.             .on_alarm = timrt_alarm_callback,
  67.     };
  68.  
  69.     gptimer_register_event_callbacks(gptimer, &timerCallback, NULL);
  70.  
  71.     gptimer_alarm_config_t alarm_config = {
  72.             .alarm_count = 5000,
  73.             .reload_count = 0,
  74.             .flags.auto_reload_on_alarm = true,
  75.     };
  76.  
  77.     gptimer_set_alarm_action(gptimer, &alarm_config);
  78.  
  79.     timer_alarm_queue = xQueueCreate(1, sizeof(uint32_t));
  80.  
  81.     xTaskCreate(timer_alarm_task, "timer_alarm_task", 2048, NULL, 5, NULL);
  82.  
  83.     gptimer_enable(gptimer);
  84.  
  85.     gptimer_start(gptimer);
  86.  
  87.  
  88.     while(1)
  89.     {
  90.         vTaskDelay(1000 / portTICK_PERIOD_MS);
  91.     }
  92. }

MicroController
Posts: 1706
Joined: Mon Oct 17, 2022 7:38 pm
Location: Europe, Germany

Re: Generate signal with timer

Postby MicroController » Fri Apr 12, 2024 1:18 pm

an interrupt occurs every 10 microseconds
This is the actual problem. When accounting for the overhead of entering and exiting an ISR plus the xQueueSendFromISR(...), plus the context switch to the timer_alarm_task, 10us won't leave much time, if any, for anything else on that CPU core. I don't know if that's actually what causes the resets in your case (e.g. by angering the watchdog timer), but 100kHz is still likely too much for an ISR; and if it doesn't crash the system, the jitter in signal timing you'd get is probably inacceptable.
However, you can try to do the GPIO toggling directly from the ISR instead of communicating to a task to significantly reduce the overhead.

espmajds
Posts: 5
Joined: Fri Apr 12, 2024 7:52 am

Re: Generate signal with timer

Postby espmajds » Fri Apr 12, 2024 1:50 pm

I directly changed the GPIO from the ISR, but it resets again.
The ESP32 has a high operating frequency, which is why it surprises me why this is happening!
What is your suggestion for generating 100 kilohertz frequency other than LEDC?
Do you have any sample code
Thanks

ESP_Sprite
Posts: 9730
Joined: Thu Nov 26, 2015 4:08 am

Re: Generate signal with timer

Postby ESP_Sprite » Fri Apr 12, 2024 2:41 pm

Do you have an issue specific with the LEDC? If so, you can also use the MCPWM or the RMT, or even hack stuff up using e.g. I2s, to generate such a signal. If you specifically want to generate a signal using a software interrupt, it would really help if you would tell us why exactly. (And the answer might be: 'you can't'. The features that make the ESP32 core very fast, also make it a bit sluggish when it comes to interrupt handling and context switching. That is why they have so many flexible peripherals on board, like the LEDC.)

espmajds
Posts: 5
Joined: Fri Apr 12, 2024 7:52 am

Re: Generate signal with timer

Postby espmajds » Fri Apr 12, 2024 3:35 pm

I don't have any issues with LEDC. in fact, I wanted to set up an ultrasonic SR-04 module, which actually worked fine with LEDC. However, as I'm currently learning ESP-IDF and reading the GPTimer documentation, I tried to generate 100 kHz frequency for the SR-04 using GPTimer to get familiar with different methods and applications of GPTimer.

I have another question about GPTimer.
Since the ESP32 has two Timer groups, each containing 2 timers, how can I configure a different setup and a separate ISR for each?

Thanks.

espmajds
Posts: 5
Joined: Fri Apr 12, 2024 7:52 am

Re: Generate signal with timer

Postby espmajds » Sat Apr 13, 2024 7:57 am

I don't understand! What's the relationship between GPTimer and Timer Group?
If a timer group includes 4 timers, then which one does GPTimer work with?
And do I need to use multiple gptimer_handle_t with different configurations to create multiple timers with GPTimer?

ESP_Sprite
Posts: 9730
Joined: Thu Nov 26, 2015 4:08 am

Re: Generate signal with timer

Postby ESP_Sprite » Sun Apr 14, 2024 1:16 am

Not sure where you get that a timer group contains 4 timers. From the TRM: 'The ESP32 contains two timer modules, each containing two timers. '. In general, the gptimer driver abstracts away over this: if you ask it for a timer, it'll give you the first one that is free.

Who is online

Users browsing this forum: Google [Bot] and 127 guests