ESP32-WROOM - Problems getting high frequency GPIO working

SparkyNZ
Posts: 48
Joined: Thu Jan 04, 2024 9:01 pm

ESP32-WROOM - Problems getting high frequency GPIO working

Postby SparkyNZ » Tue Aug 20, 2024 4:29 am

I took this code as a base: https://github.com/espressif/esp-idf/bl ... ple_main.c

When I first compiled and downloaded the code, I saw triangle wave on my scope at 2MHz. I tried dropping the frequency to 10000000 and I've put it back to 20000000 but I have absolutely nothing coming out of GPIO 18 now.

For a sanity check, I can see GPIO 16 flashing an LED every 2 seconds.

Why am I not seeing a 2MHz signal? I don't know if it makes any difference but I'm using IDF 4.3 (I needed that for FabGl compatibility).

Here's my code:

Code: Select all

#include <stdio.h>
#include "freertos/FreeRTOS.h"
#include "freertos/task.h"
#include "driver/gpio.h"
#include "driver/ledc.h"
#include "sdkconfig.h"

#include "esp_task.h"
#include "esp_task_wdt.h"
#include <Time.h>

ledc_timer_config_t ledc_timer;
ledc_channel_config_t ledc_channel;

int64_t tCpuStep  = esp_timer_get_time();
int64_t tPoll     = esp_timer_get_time();

extern void serialEventRun(void) __attribute__((weak));

TaskHandle_t loopTaskHandle = NULL;
bool loopTaskWDTEnabled = false;

//-----------------------------------------------------------------------------------------------------------
void enableLoopWDT(){
//-----------------------------------------------------------------------------------------------------------
    if(loopTaskHandle != NULL){
        if(esp_task_wdt_add(loopTaskHandle) != ESP_OK){
            printf("ERROR: Failed to add loop task to WDT");
        } else {
            loopTaskWDTEnabled = true;
        }
    }
}

#define ARDUINO_ISR_ATTR
//-----------------------------------------------------------------------------------------------------------
unsigned long ARDUINO_ISR_ATTR millis()
//-----------------------------------------------------------------------------------------------------------
{
    return (unsigned long) (esp_timer_get_time() / 1000ULL);
}

#define YIELD_TIME_MS 2000
#define YIELD_TIME_US 2000000
uint64_t tCurrentTime = 0;

//-----------------------------------------------------------------------------------------------------------
void yieldIfNecessary(void){
//-----------------------------------------------------------------------------------------------------------
    static uint64_t lastYield = 0;
    //uint64_t now = millis();
    //if((now - lastYield) > YIELD_TIME_MS) {    // Avoid division
      if((tCurrentTime - lastYield) > YIELD_TIME_US) {
        lastYield = tCurrentTime;
        vTaskDelay(5); //delay 1 RTOS tick
    }
}


//-----------------------------------------------------------------------------------------------------------
void loopTask(void *pvParameters) {
//-----------------------------------------------------------------------------------------------------------
    int64_t tStart = esp_timer_get_time();

    /* Configure the IOMUX register for pad BLINK_GPIO (some pads are
       muxed to GPIO on reset already, but some default to other
       functions and need to be switched to GPIO. Consult the
       Technical Reference for a list of pads and their default
       functions.)
    */
    gpio_pad_select_gpio(GPIO_NUM_16);
    /* Set the GPIO as a push/pull output */
    gpio_set_direction(GPIO_NUM_16, GPIO_MODE_OUTPUT);

    for(;;)
    {
      tCurrentTime = esp_timer_get_time();

      yieldIfNecessary();

      if(loopTaskWDTEnabled){
          esp_task_wdt_reset();
      }

      static int direction = 0;
      if (tCurrentTime - tPoll > 2000000) {
        tPoll = tCurrentTime;
        
        if( direction == 1) {
          gpio_set_level(GPIO_NUM_16, 1);
          direction = 0;
        } else {
          gpio_set_level(GPIO_NUM_16, 0);
          direction = 1;
        }
      }
    }
}

#define LEDC_CHANNEL LEDC_CHANNEL_0
#define LEDC_MODE    LEDC_HIGH_SPEED_MODE

//-----------------------------------------------------------------------------------------------------------
extern "C" void app_main(void)
//-----------------------------------------------------------------------------------------------------------
{
  ledc_timer.speed_mode = LEDC_MODE;
  ledc_timer.duty_resolution = LEDC_TIMER_13_BIT; // 2 ^ 13 = 4096
  ledc_timer.timer_num  = LEDC_TIMER_0;
  //ledc_timer.bit_num    = LEDC_TIMER_2_BIT;
  ledc_timer.freq_hz    = 20000000;
  ledc_timer.clk_cfg    = LEDC_AUTO_CLK;

// Attempt to create a clock on pin 18..
  ledc_channel.speed_mode = LEDC_MODE;  
  ledc_channel.channel    = LEDC_CHANNEL;
  ledc_channel.intr_type  = LEDC_INTR_DISABLE;
  ledc_channel.gpio_num   = 18;  
  ledc_channel.timer_sel  = LEDC_TIMER_0;
  ledc_channel.duty       = 0; 
  ledc_channel.hpoint     = 0; 

  ledc_timer_config(&ledc_timer);
  ledc_channel_config(&ledc_channel);

  ledc_set_duty(LEDC_MODE, LEDC_CHANNEL, 4096); // 50%
  ledc_update_duty(LEDC_MODE, LEDC_CHANNEL);

  enableLoopWDT();

  xTaskCreatePinnedToCore(
    loopTask
    ,  "loopTask"
    ,  2048  // Stack size
    ,  NULL  // When no parameter is used, simply pass NULL
    ,  1  // Priority
    ,  &loopTaskHandle // With task handle we will be able to manipulate with this task.
    ,  tskNO_AFFINITY  // Core on which the task will run
    );
}

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

Re: ESP32-WROOM - Problems getting high frequency GPIO working

Postby MicroController » Tue Aug 20, 2024 9:05 pm

SparkyNZ wrote:
Tue Aug 20, 2024 4:29 am
I tried dropping the frequency to 10_000_000 and I've put it back to 20_000_000...
;-)
You may want to check that IDF functions like ledc_timer_config(...) return ESP_OK.

SparkyNZ
Posts: 48
Joined: Thu Jan 04, 2024 9:01 pm

Re: ESP32-WROOM - Problems getting high frequency GPIO working

Postby SparkyNZ » Thu Aug 22, 2024 7:21 am

MicroController wrote:
Tue Aug 20, 2024 9:05 pm
You may want to check that IDF functions like ledc_timer_config(...) return ESP_OK.
I did try lower frequencies. Just had the sense to print out the return of ledc_timer_config() and yeah.. it's returning -1. I'll have a look when I get a chance. Wish I had more time :-) Thanks.

SparkyNZ
Posts: 48
Joined: Thu Jan 04, 2024 9:01 pm

Re: ESP32-WROOM - Problems getting high frequency GPIO working

Postby SparkyNZ » Thu Aug 22, 2024 9:29 am

You may want to check that IDF functions like ledc_timer_config(...) return ESP_OK.
[/quote]

I found that when I set bit_num to LEDC_TIMER_2_BIT, I got ESP_OK for ledc_timer_config(). Unfortunately I just had a constant high output on GP18.

Looking at the definition of bit_num, it says that its deprecated and is part of a union with duty_resolution.. So I wonder why it won't initialise with LEDC_TIMER_13_BIT.. unless this is a limitation of my device?

Update: I changed it to LEDC_TIMER_4_BIT, and:

Code: Select all

rc = ledc_set_duty(LEDC_MODE, LEDC_CHANNEL, 8); // 50% for 4 bit
This is now giving me 2MHz output :-)

SparkyNZ
Posts: 48
Joined: Thu Jan 04, 2024 9:01 pm

Re: ESP32-WROOM - Problems getting high frequency GPIO working

Postby SparkyNZ » Thu Aug 22, 2024 9:38 am

Question now is.. how can I get a 14MHz output? ledc_timer_config() fails when I try 14000000.

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

Re: ESP32-WROOM - Problems getting high frequency GPIO working

Postby MicroController » Thu Aug 22, 2024 12:59 pm

See https://docs.espressif.com/projects/esp ... resolution

The maximum frequency you can get is 80MHz/(1 << ResolutionBits); i.e. ResolutionBits[max] = floor(log2(80000000/desiredFrequency)).
LEDC_TIMER_2_BIT works for up to 20MHz, LEDC_TIMER_3_BIT only for up to 10MHz &c.

SparkyNZ
Posts: 48
Joined: Thu Jan 04, 2024 9:01 pm

Re: ESP32-WROOM - Problems getting high frequency GPIO working

Postby SparkyNZ » Thu Aug 22, 2024 6:49 pm

MicroController wrote:
Thu Aug 22, 2024 12:59 pm
See https://docs.espressif.com/projects/esp ... resolution

The maximum frequency you can get is 80MHz/(1 << ResolutionBits); i.e. ResolutionBits[max] = floor(log2(80000000/desiredFrequency)).
LEDC_TIMER_2_BIT works for up to 20MHz, LEDC_TIMER_3_BIT only for up to 10MHz &c.
Thank you. I'll give that a try this evening.

Who is online

Users browsing this forum: atx823, brushlow18 and 243 guests