Precision generator

RickRac
Posts: 7
Joined: Thu Apr 29, 2021 8:10 pm

Precision generator

Postby RickRac » Tue Sep 30, 2025 7:50 pm

I am keen about generating a square wave with a floating point frequency say 1 or 2 decimal points from the range of 1-20000 Hz.
Is there an easy way to do this say with a S3? 7.83 Hz for example.
Thanks

Sprite
Espressif staff
Espressif staff
Posts: 10596
Joined: Thu Nov 26, 2015 4:08 am

Re: Precision generator

Postby Sprite » Wed Oct 01, 2025 1:27 am

The -S3 can run its PWM stuff (LEDC etc) on 80MHz. It has an 18bit divider and 14-bit counter after that, for a minimum frequency of 0.1Hz. At 200000Hz, the divider would be something like 4000, meaning if you change your divider by 1, the frequency would shift by 5Hz. However, if you're okay with some jitter in the output frequency, the divider has a fractional part, meaning you can change the divider by 1/256th, leading to a frequency shift of 0.2Hz. The LEDC does this by e.g. using a divider of 4000 for 255 cycles and then a divider of 4001 for one cycle (averaging to exactly the frequency you set), so that's the jitter you will get.

RickRac
Posts: 7
Joined: Thu Apr 29, 2021 8:10 pm

Re: Precision generator

Postby RickRac » Wed Oct 01, 2025 2:12 pm

Thanks for the prompt reply. A little jitter etc is all ok.
Can you offer any sample code to get started please?

Sprite
Espressif staff
Espressif staff
Posts: 10596
Joined: Thu Nov 26, 2015 4:08 am

Re: Precision generator

Postby Sprite » Sat Oct 04, 2025 12:28 am

I think you should be able to use the LEDC examples as a starting point. Just set the duty cycle to 50%.

RickRac
Posts: 7
Joined: Thu Apr 29, 2021 8:10 pm

Re: Precision generator

Postby RickRac » Sun Oct 05, 2025 5:13 pm

Well the issue is freq must be an integer so no dice on 7.83. I need a version that allows floats or divide the master clock by 10.

ledcAttachChannel(7, freq, resolution, 3); //freq is an integer.

Thanks for the reply though

Sprite
Espressif staff
Espressif staff
Posts: 10596
Joined: Thu Nov 26, 2015 4:08 am

Re: Precision generator

Postby Sprite » Tue Oct 07, 2025 1:22 am

Ah, you're right there. esp-idf also doesn't support fractional rates, I'm afraid... hm, you could use the HAL to poke into the registers directly, or file an issue on esp-idf or the esp32-arduino repos to allow for float frequencies, I guess.

samlevy0515
Posts: 1
Joined: Mon Oct 20, 2025 7:49 am

Re: Precision generator

Postby samlevy0515 » Fri Oct 24, 2025 2:20 am

Sure, the ESP32-S3 can handle that. You'll want to use the LEDC (PWM) peripheral and set it to a high-resolution mode (like 20-bit) to get the fine decimal control you need for frequencies like 7.83 Hz.
Last edited by samlevy0515 on Fri Oct 31, 2025 2:06 am, edited 3 times in total.

RickRac
Posts: 7
Joined: Thu Apr 29, 2021 8:10 pm

Re: Precision generator

Postby RickRac » Tue Oct 28, 2025 8:39 pm

While 20 bit PW resolution is super nice, the issue remains that the freq must be an integer so no dice on 7.83

ESP32_kid
Posts: 16
Joined: Tue Oct 28, 2025 10:02 pm

Re: Precision generator

Postby ESP32_kid » Tue Oct 28, 2025 10:23 pm

PWM functions need integer? Ok, so don't use PWM

1/7.83 = 0.1277139208173 sec

We can delay() to 1msec
The closest you'll get to 7.83Hz is 127 or 128msec period. 128 is the better number.
127ms period is off by -5.69ms, 128ms period is off by +2.24ms

It was never stated what % PWM @ 7.83Hz, so I assume here 50%

(esp32-c3-zero, flash the led at 7.83Hz))
neopixelWrite(RGB_BUILTIN,0,0,RGB_BRIGHTNESS); // Blue
delay(64);
neopixelWrite(RGB_BUILTIN,0,0,0); // Off / black
delay(64);

You want to change % PWM, just change on off times, as long as they add up to 127 or 128.
eg; fast pulse 1ms on, 127ms off.

It's not accurate, yet should be fairly precise, not sure how much drift there is in esp32 clock.
If it's for PPL or the like, probably won't work if 7.83 is needed within nsec accuracy.

ESP32_kid
Posts: 16
Joined: Tue Oct 28, 2025 10:02 pm

Re: Precision generator

Postby ESP32_kid » Tue Oct 28, 2025 11:10 pm

And then look into time.sleep_us()
With usec sleep you can get to 7.83Hz.

Who is online

Users browsing this forum: Applebot, Qwantbot and 8 guests