Continue to Site

Welcome to EDAboard.com

Welcome to our site! EDAboard.com is an international Electronics Discussion Forum focused on EDA software, circuits, schematics, books, theory, papers, asic, pld, 8051, DSP, Network, RF, Analog Design, PCB, Service Manuals... and a whole lot more! To participate you need to register. Registration is free. Click here to register now.

[SOLVED] Issues with generating 11 MHz square wave on ESP32 (ESP32-Wrover board)

Status
Not open for further replies.

FlyingDutch

Advanced Member level 1
Advanced Member level 1
Joined
Dec 16, 2017
Messages
458
Helped
45
Reputation
92
Reaction score
55
Trophy points
28
Location
Bydgoszcz - Poland
Activity points
5,029
Hello,
I am trying to generate square wave of frequency 11.2896 MHz (this is external clock for IC PCM1608 (256*44.1KHz) on ESP32 board. I haven't big experience with using ESP32 MCU (I have bigger experience with ARM-CortexMx MCUs). I am trying to program ESP32-Wrover board in "Arduino-IDE". I wouldn't like to install "ESP-IDF" because of many dependences in my Windows OS (for example installed Python version) and this is "command-line" environment (quite complex). I was studying Expressif documentation, and found that "LEDC" module API can be used for generating square wave up to 40 MHz (using internal timers) - see link:
https://docs.espressif.com/projects/esp-idf/en/latest/esp32/api-reference/peripherals/ledc.html
https://www.esp32.com/viewtopic.php?t=1037
I altered this code a bit in order to compile it in "Arduino IDE" (with boards package for ESP32). I had to add few headers files (from Github with ESP32 drivers). Here is code of main program "Arduino sketch":


Code:
#include "ledc.h"
void setup() { //---------------------------------------------------------------------------------------
  Serial.begin(115200); // use the serial port
  ledc_timer_config_t ledc_timer;
  ledc_channel_config_t ledc_channel;
  //params ledc_timer
  ledc_timer.speed_mode = LEDC_HIGH_SPEED_MODE;//LEDC_HIGH_SPEED_MODE;
  ledc_timer.timer_num  = LEDC_TIMER_0;
  ledc_timer.bit_num    = (ledc_timer_bit_t) LEDC_TIMER_1_BIT; //LEDC_TIMER_2_BIT;
  ledc_timer.freq_hz    = 1000000;
  ledc_timer.clk_cfg    = LEDC_USE_APB_CLK;
 
  //params ledc_channel
  ledc_channel.channel    = LEDC_CHANNEL_0;
  ledc_channel.gpio_num   = 18;  //WAS 18
  ledc_channel.speed_mode = LEDC_HIGH_SPEED_MODE;
  ledc_channel.timer_sel  = LEDC_TIMER_0;
  ledc_channel.duty       = 1;
  //Generacja zegara dla PCM1808
  ledc_timer_config(&ledc_timer);
  ledc_channel_config(&ledc_channel);

  Serial.println("Program Started");
}//---------------------------------------------------------------------------------------
void loop() {
}
This code is compiling without any errors in "Arduino IDE" and runs on ESP32 board without runtime errors.
--- Updated ---

First, I tried to generate 11 MHz square wave, but such frequency is very close to frequency limit for my cheap digital scope and I saw series of impulses of low amplitude (below 0.5 Volt). When I change the generated signal waveform to 1 MHz (see in given code above) I was observing 1 MHz sinusoidal wave of amplitude lower then 1 Volt. I tried to see generated waveform on logic analyzer (which has much bigger bandwith - 200 Mhz), but from the cause amplitude had to low to trigger sampling on it. I also made further experiments - lower the generated signal frequency to 4 Khz (in program code) and had seen it on scope. In this case I saw 4 KHz square waveform, but amplitude was only 1 Volt. In tis case timer resolution was 13-bit, and when I was changing the waveform duty, I was able to see it on scope properly. I also tried to find different example of code in C language, but all be very similar to code in link I attached.

As I told I haven't big experience with ESP32 MCU. Could somebody help me with this problem and give me any clue what I am doing wrong? In zip package is full program for "Arduino IDE" (with needed header files).

BTW: when I tried to generate lower frequencies the resolution of timer wasn't 1-bit, it was 13-bit: LEDC_TIMER_13_BIT

Thanks in advance and Regards
 

Attachments

  • FFT_on_ESP32_PCM1808_02.zip
    10.9 KB · Views: 281
Last edited:

The timer is clocked by 80 MHz APB clock and not suited to generate 11.29 MHz. ESP32 has however a fractional audio clock for the I2S interface which is supporting 44.1 kS/s audio with usual frame formats. Review the I2S paragraphs in hardware and API reference.
 

The timer is clocked by 80 MHz APB clock and not suited to generate 11.29 MHz. ESP32 has however a fractional audio clock for the I2S interface which is supporting 44.1 kS/s audio with usual frame formats. Review the I2S paragraphs in hardware and API reference.
Hello @FvM,

so what clock I have to use: REF_TICK has only 1MHz frequency and RTC8M_CLK has f=8 MHz. See screenshot:
ESP32_ClockSource.png

with documentation (Expressif). And here is citation from documentation:

The LEDC can be used for generating signals at much higher frequencies that are sufficient enough to clock other devices, e.g., a digital camera module. In this case, the maximum available frequency is 40 MHz with duty resolution of 1 bit. This means that the duty cycle is fixed at 50% and cannot be adjusted.
I want to use external I2S ADC (the main reason is resolution of ADC) based on PCM1808 IC - see datasheet:

https://www.ti.com/lit/ds/symlink/p...tps%3A%2F%2Fwww.ti.com%2Fproduct%2FPCM1808-Q1

and this IC requires this external clock waveform on it's SCKI input (256*Fs) - where Fs is sampling audio signal frequency

Do you have any suspicions what can to cause such low amplitude (Below 1V) of generated waveform on I/O pin of ESP32 (even for low frequencies about few KHz)?

In worst case I am able to generate such frequency on small FPGA, but it result in unnecessary complexity of hardware for this project.

Thanks for your answer and regards
--- Updated ---

Hello @FvM,

so what clock I have to use: REF_TICK has only 1MHz frequency and RTC8M_CLK has f=8 MHz. See screenshot:
ESP32_ClockSource.png

with documentation (Expressif). And here is citation from documentation:


I want to use external I2S ADC (the main reason is resolution of ADC) based on PCM1808 IC - see datasheet:

https://www.ti.com/lit/ds/symlink/pcm1808-q1.pdf?ts=1647175592223&ref_url=https%3A%2F%2Fwww.ti.com%2Fproduct%2FPCM1808-Q1

and this IC requires this external clock waveform on it's SCKI input (256*Fs) - where Fs is sampling audio signal frequency

Do you have any suspicions what can to cause such low amplitude (Below 1V) of generated waveform on I/O pin of ESP32 (even for low frequencies about few KHz)?

In worst case I am able to generate such frequency on small FPGA, but it result in unnecessary complexity of hardware for this project.

Thanks for your answer and regards
Lets assume that on this step I want to generate exactly 11 MHz square waveform (duty 50%).

Best Regards
--- Updated ---

I had generated this I2S CLOCK 11.2896 MHz square waveform with Elbert v.2 FPGA (Spartan3A), and it works fine.

Berst Regards
 
Last edited:

Just guessing but the low amplitude is probably because the slew rate on the output driver devices is too low. I *think* the ESP32 devices can adjust the slew rate - check the data sheet and see if that helps.
Susan
 

    FlyingDutch

    Points: 2
    Helpful Answer Positive Rating
They can, but I'm not sure the Arduino IDE supports it. If the IDE calls the ESP-IDF compiler directly it should be possible to set the slew rate with the "GPIO_DRIVE_CAP_x" function.

Brian.
 

    FlyingDutch

    Points: 2
    Helpful Answer Positive Rating
Hello,

thanks @Aussie Susan and @betwixt for clue. I found such code related to function: gpio_set_drive_capability:

https://github.com/espressif/esp-idf/issues/6944


I tried it in my Arduino code for ESP32 and it seems that it is compiling without errors. I check it with hardware today afternoon. Then I will write how results are.

Best Regards
 

Hello,
today I changed the main program - see actual code:
Code:
#include "ledc.h"

#define CLK_PIN (18)

void setup() { //---------------------------------------------------------------------------------------
  Serial.begin(115200); // use the serial port
  Serial.println("Starting ...");

  gpio_reset_pin((gpio_num_t)CLK_PIN);
  /* Set the GPIO as a push/pull output */
  //gpio_set_direction((gpio_num_t)CLK_PIN, GPIO_MODE_OUTPUT);
  gpio_set_drive_capability((gpio_num_t)CLK_PIN, GPIO_DRIVE_CAP_3);

  ledc_timer_config_t ledc_timer;
  ledc_channel_config_t ledc_channel;
 
  //params ledc_timer
  ledc_timer.speed_mode = LEDC_HIGH_SPEED_MODE;//LEDC_HIGH_SPEED_MODE;
  ledc_timer.timer_num  = LEDC_TIMER_0;
  ledc_timer.bit_num    = (ledc_timer_bit_t) LEDC_TIMER_14_BIT; //LEDC_TIMER_2_BIT;
  ledc_timer.freq_hz    = 4000;
  ledc_timer.clk_cfg    = LEDC_USE_APB_CLK;
 
  //params ledc_channel
  ledc_channel.channel    = LEDC_CHANNEL_0;
  ledc_channel.gpio_num   = 18;  //WAS 18
  ledc_channel.speed_mode = LEDC_HIGH_SPEED_MODE;
  ledc_channel.timer_sel  = LEDC_TIMER_0;
  ledc_channel.duty       = 6000;

  //Generacja zegara dla PCM1808
  ledc_timer_config(&ledc_timer);
  ledc_channel_config(&ledc_channel);

  Serial.println("Program Started");
 
}//---------------------------------------------------------------------------------------

void loop() {
 
}

But it didn't help, even in slower frequency 4 Khz - see screnshot from scope:
SlewRate3_.png

Tis is signal for 4 Khz, timer resolution 14-bit and duty = 6000.

Besst Regards
 

That looks very like the AC component only. Are you certain that you are looking at the pin directly (and not via some capacitor) and have the scope set up for DC?
What if you simply drive a GPIO pin up and down directly, perhaps with a bit of delay in the 'while' loop (without a delay you can certainly run into slew limitations)?
Personally I would not try to use the Arduino framework for the ESP32's - it takes a while to get used to it but the ESP-IDF framework does let you get closer to the hardware. (I use VS Code as the IDE with the PlatformIO framework that automatically brings in the ESP-IDF if you ask it to.)
Susan
 

    FlyingDutch

    Points: 2
    Helpful Answer Positive Rating
Hi,

The scope picture does not look right.
Maybe bad scope probe, bad connections at probe_signal or probe_GND..

Klaus
 

    FlyingDutch

    Points: 2
    Helpful Answer Positive Rating
That looks very like the AC component only. Are you certain that you are looking at the pin directly (and not via some capacitor) and have the scope set up for DC?
What if you simply drive a GPIO pin up and down directly, perhaps with a bit of delay in the 'while' loop (without a delay you can certainly run into slew limitations)?
Personally I would not try to use the Arduino framework for the ESP32's - it takes a while to get used to it but the ESP-IDF framework does let you get closer to the hardware. (I use VS Code as the IDE with the PlatformIO framework that automatically brings in the ESP-IDF if you ask it to.)
Susan
Hello,

@Aussie Susan and @KlausST you two have right, I made big mistake. I connect scope one pin too far (not pin 18 but next). I am ashamed, because I should first check if i am connected to proper pin. On this 4KHz waveform now is ideal square. For square wave of frequency 11 289 600 Hz also everything is OK. I put the final version of program (working OK on Arduino IDE) for square wave f=11289600 Hz. Maybe someone esle would like to generate square wave of big frequency on ESP32:
C++:
#include "ledc.h"

#define CLK_PIN (18)

void setup() { //---------------------------------------------------------------------------------------
  Serial.begin(115200); // use the serial port
  Serial.println("Starting ...");

  gpio_reset_pin((gpio_num_t)CLK_PIN);
  /* Set the GPIO as a push/pull output */
  gpio_set_direction((gpio_num_t)CLK_PIN, GPIO_MODE_OUTPUT);
  gpio_set_drive_capability((gpio_num_t)CLK_PIN, GPIO_DRIVE_CAP_3);

  ledc_timer_config_t ledc_timer;
  ledc_channel_config_t ledc_channel;
 
  //params ledc_timer
  ledc_timer.speed_mode = LEDC_HIGH_SPEED_MODE;//LEDC_HIGH_SPEED_MODE;
  ledc_timer.timer_num  = LEDC_TIMER_0;
  ledc_timer.bit_num    = (ledc_timer_bit_t) LEDC_TIMER_1_BIT; //LEDC_TIMER_2_BIT;
  ledc_timer.freq_hz    = 11289600;
  ledc_timer.clk_cfg    = LEDC_USE_APB_CLK;
 
  //params ledc_channel
  ledc_channel.channel    = LEDC_CHANNEL_0;
  ledc_channel.gpio_num   = 18;  //WAS 18
  ledc_channel.speed_mode = LEDC_HIGH_SPEED_MODE;
  ledc_channel.timer_sel  = LEDC_TIMER_0;
  ledc_channel.duty       = 1;

  //Generacja zegara dla PCM1808
  ledc_timer_config(&ledc_timer);
  ledc_channel_config(&ledc_channel);

  Serial.println("Program Started");
 
}//---------------------------------------------------------------------------------------

void loop() {
 
}

In zip archive is full project for "Arduino IDE" with needed header files.

Best Regards
--- Updated ---

Hello,

@Aussie Susan and @KlausST you two have right, I made big mistake. I connect scope one pin too far (not pin 18 but next). I am ashamed, because I should first check if i am connected to proper pin. On this 4KHz waveform now is ideal square. For square wave of frequency 11 289 600 Hz also everything is OK. I put the final version of program (working OK on Arduino IDE) for square wave f=11289600 Hz. Maybe someone esle would like to generate square wave of big frequency on ESP32:
C++:
#include "ledc.h"

#define CLK_PIN (18)

void setup() { //---------------------------------------------------------------------------------------
  Serial.begin(115200); // use the serial port
  Serial.println("Starting ...");

  gpio_reset_pin((gpio_num_t)CLK_PIN);
  /* Set the GPIO as a push/pull output */
  gpio_set_direction((gpio_num_t)CLK_PIN, GPIO_MODE_OUTPUT);
  gpio_set_drive_capability((gpio_num_t)CLK_PIN, GPIO_DRIVE_CAP_3);

  ledc_timer_config_t ledc_timer;
  ledc_channel_config_t ledc_channel;
 
  //params ledc_timer
  ledc_timer.speed_mode = LEDC_HIGH_SPEED_MODE;//LEDC_HIGH_SPEED_MODE;
  ledc_timer.timer_num  = LEDC_TIMER_0;
  ledc_timer.bit_num    = (ledc_timer_bit_t) LEDC_TIMER_1_BIT; //LEDC_TIMER_2_BIT;
  ledc_timer.freq_hz    = 11289600;
  ledc_timer.clk_cfg    = LEDC_USE_APB_CLK;
 
  //params ledc_channel
  ledc_channel.channel    = LEDC_CHANNEL_0;
  ledc_channel.gpio_num   = 18;  //WAS 18
  ledc_channel.speed_mode = LEDC_HIGH_SPEED_MODE;
  ledc_channel.timer_sel  = LEDC_TIMER_0;
  ledc_channel.duty       = 1;

  //Generacja zegara dla PCM1808
  ledc_timer_config(&ledc_timer);
  ledc_channel_config(&ledc_channel);

  Serial.println("Program Started");
 
}//---------------------------------------------------------------------------------------

void loop() {
 
}

In zip archive is full project for "Arduino IDE" with needed header files.

Best Regards
BTW: how to mark thread as "Solved"?

Reagards
 

Attachments

  • FFT_on_ESP32_PCM1808_03.zip
    11 KB · Views: 296
Last edited:

Status
Not open for further replies.

Similar threads

Part and Inventory Search

Welcome to EDABoard.com

Sponsor

Back
Top