Skip to content

Navigation Menu

Sign in
Appearance settings

Search code, repositories, users, issues, pull requests...

Provide feedback

We read every piece of feedback, and take your input very seriously.

Saved searches

Use saved searches to filter your results more quickly

Sign up
Appearance settings

ESP32-S3 RMT-based PWM sweep causes glitches; not as seamless as Timer1 on Arduino Uno #11529

Murugesh-Hobbyist started this conversation in General
Discussion options

Board

ESP32-S3

Device Description

ESP32-S3 module on custom board. Only one GPIO (GPIO10) is used for PWM output via RMT.

Hardware Configuration

Only GPIO10 is used as output to measure PWM via oscilloscope. No other components attached.

Version

latest stable Release (if not listed below)

IDE Name

Arduino IDE

Operating System

Windows 11

Flash frequency

80 MHz

PSRAM enabled

no

Upload speed

921600

Description

When sweeping PWM frequency and Ton dynamically using RMT on ESP32-S3, the output is not smooth. There's a noticeable glitch or "bang" at each frequency step. The same logic works perfectly and seamlessly on Arduino Uno using Timer1 hardware PWM with Phase Correct mode.

Expected: clean frequency and Ton sweep with no break in output
Observed: visible discontinuity or glitch at each step due to teardown/reinit of RMT channel

Sketch

Below code i used in Arduino UNO worked flawlessly.
const int pwmPin = 9; // OC1A = Pin 9 on Arduino Uno
const float freqStart = 28000.0; // Hz
const float freqEnd = 24000.0; // Hz
const float freqStep = -10.0; // Hz
const float tonStart = 8.0; // μs
const float tonEnd = 21.0; // μs
const int delayMs = 5; // Delay per step
const int offDelayMs = 3000; // 5 sec OFF after sweep
void setup() {
 pinMode(pwmPin, OUTPUT);
 delay(2000);
 // Timer1: Phase Correct PWM, TOP = ICR1
 TCCR1A = _BV(COM1A1); // Non-inverting PWM on OC1A
 TCCR1B = _BV(WGM13) | _BV(CS10); // Mode 8: Phase-correct, no prescaler
 Serial.begin(115200);
}
void loop() {
 float freq = freqStart;
 float ton = tonStart;
 float freqRange = freqStart - freqEnd;
 float tonRange = tonEnd - tonStart;
 int steps = freqRange / -freqStep;
 for (int i = 0; i <= steps; i++) {
 freq = freqStart + i * freqStep;
 ton = tonStart + (tonRange * i / steps);
 float period_us = 1000000.0 / freq;
 uint16_t top = (16000000UL / (2 * freq)); // ICR1 value
 uint16_t duty = (ton / period_us) * top; // OCR1A value
 ICR1 = top;
 OCR1A = duty;
 Serial.print("Freq: ");
 Serial.print(freq, 1);
 Serial.print(" Hz | Ton: ");
 Serial.print(ton, 1);
 Serial.print(" us | TOP: ");
 Serial.print(top);
 Serial.print(" | OCR1A: ");
 Serial.println(duty);
 delay(delayMs);
 }
 // Turn off PWM
 OCR1A = 0;
 Serial.println("PWM OFF for 5 seconds");
 delay(offDelayMs);
}
Below code i used in ESP32-S3 but the wave is banging.
#include <Arduino.h>
#include <driver/rmt_tx.h>
#include <Ticker.h>
// --- Pin Setup ---
#define PWM_PIN 10 // Pick a reliable RMT-capable GPIO
// --- Sweep Parameters ---
const float freqStart = 28000.0;
const float freqEnd = 24000.0;
const float freqStep = -10.0;
const float tonStart = 8.0;
const float tonEnd = 21.0;
const int delayMs = 5;
const int offDelayMs = 5000;
rmt_channel_handle_t rmt_chan = nullptr;
rmt_encoder_handle_t rmt_encoder = nullptr;
void setupRMT(float freq, float ton_us) {
 if (rmt_chan) {
 rmt_disable(rmt_chan);
 rmt_del_channel(rmt_chan);
 rmt_chan = nullptr;
 }
 uint32_t period_us = 1000000.0 / freq;
 uint32_t toff_us = period_us - ton_us;
 rmt_tx_channel_config_t tx_config = {};
 tx_config.clk_src = RMT_CLK_SRC_DEFAULT;
 tx_config.gpio_num = (gpio_num_t)PWM_PIN;
 tx_config.mem_block_symbols = 64;
 tx_config.resolution_hz = 1000000; // 1 μs resolution
 tx_config.trans_queue_depth = 1;
 tx_config.flags.invert_out = false;
 tx_config.flags.with_dma = false;
 ESP_ERROR_CHECK(rmt_new_tx_channel(&tx_config, &rmt_chan));
 rmt_copy_encoder_config_t enc_config = {};
 ESP_ERROR_CHECK(rmt_new_copy_encoder(&enc_config, &rmt_encoder));
 ESP_ERROR_CHECK(rmt_enable(rmt_chan));
 rmt_symbol_word_t item;
 item.level0 = 1;
 item.duration0 = (uint16_t)ton_us;
 item.level1 = 0;
 item.duration1 = (uint16_t)toff_us;
 rmt_transmit_config_t config = {};
 config.loop_count = 1000;
 ESP_ERROR_CHECK(rmt_transmit(rmt_chan, rmt_encoder, &item, sizeof(item), &config));
}
void stopPWM() {
 if (rmt_chan) {
 rmt_disable(rmt_chan);
 gpio_reset_pin((gpio_num_t)PWM_PIN);
 gpio_set_direction((gpio_num_t)PWM_PIN, GPIO_MODE_OUTPUT);
 gpio_set_level((gpio_num_t)PWM_PIN, 0);
 rmt_del_channel(rmt_chan);
 rmt_chan = nullptr;
 }
}
void setup() {
 Serial.begin(115200);
 delay(2000);
 Serial.println("Starting PWM Sweep...");
}
void loop() {
 float freq = freqStart;
 float ton = tonStart;
 float freqRange = freqStart - freqEnd;
 float tonRange = tonEnd - tonStart;
 int steps = freqRange / -freqStep;
 for (int i = 0; i <= steps; i++) {
 freq = freqStart + i * freqStep;
 ton = tonStart + (tonRange * i / steps);
 setupRMT(freq, ton);
 float period_us = 1000000.0 / freq;
 Serial.printf("Freq: %.1f Hz | Ton: %.1f us | Period: %.1f us\n", freq, ton, period_us);
 delay(delayMs);
 }
 stopPWM();
 Serial.println("PWM OFF for 5 seconds");
 delay(offDelayMs);
}

Debug Message

No crash or backtrace. The issue is in waveform stability and timing.

Other Steps to Reproduce

Output is connected to oscilloscope

Observe the waveform during frequency sweep

Clear gaps and interruptions are visible in ESP32-S3 output

Arduino Uno waveform is smooth and uninterrupted

I have checked existing issues, online documentation and the Troubleshooting Guide

  • I confirm I have checked existing issues, online documentation and Troubleshooting guide.
You must be logged in to vote

Replies: 1 comment 2 replies

Comment options

first to point out that you are using ESP-IDF APIs and not Arduino. Also you destroy the RMT channel on each change, instead of just modifying it. Last but not least, we have LEDC for PWM generation. While it's possible with RMT, LEDC is geared more towards PWM

You must be logged in to vote
2 replies
Comment options

Thanks for the idea of Ledc, with help of GPT, I tried below code but got error, can you please guide where I'm missing?

Code:

#include <Arduino.h>
// --- Pin Setup ---
#define PWM_PIN 1
#define LEDC_CHANNEL LEDC_CHANNEL_0
// --- Sweep Parameters ---
const float freqStart = 28000.0;
const float freqEnd = 24000.0;
const float freqStep = -10.0;
const float tonStart = 8.0;
const float tonEnd = 21.0;
const int delayMs = 5;
const int offDelayMs = 5000;
void setup() {
 Serial.begin(115200);
 delay(2000);
 Serial.println("Starting LEDC PWM Sweep...");
 ledcSetup(LEDC_CHANNEL, freqStart, 16);
 ledcAttachPin(PWM_PIN, LEDC_CHANNEL);
}
void loop() {
 float freq = freqStart;
 float ton = tonStart;
 float freqRange = freqStart - freqEnd;
 float tonRange = tonEnd - tonStart;
 int steps = freqRange / -freqStep;
 for (int i = 0; i <= steps; i++) {
 freq = freqStart + i * freqStep;
 ton = tonStart + (tonRange * i / steps);
 float period_us = 1000000.0 / freq;
 float duty_ratio = ton / period_us;
 uint32_t duty = duty_ratio * 65535;
 ledcSetup(LEDC_CHANNEL, freq, 16);
 ledcWrite(LEDC_CHANNEL, duty);
 Serial.printf("Freq: %.1f Hz | Ton: %.1f us | Duty: %.1f%%\n", freq, ton, duty_ratio * 100.0);
 delay(delayMs);
 }
 ledcWrite(LEDC_CHANNEL, 0);
 Serial.println("PWM OFF for 5 seconds");
 delay(offDelayMs);
}

Error:

...\sketch_jul2d.ino: In function 'void setup()':
...\sketch_jul2d.ino:23:3: error: 'ledcSetup' was not declared in this scope
 23 | ledcSetup(LEDC_CHANNEL, freqStart, 16);
 | ^~~~~~~~~
...\sketch_jul2d.ino:24:3: error: 'ledcAttachPin' was not declared in this scope; did you mean 'ledcAttach'?
 24 | ledcAttachPin(PWM_PIN, LEDC_CHANNEL);
 | ^~~~~~~~~~~~~
 | ledcAttach
...\sketch_jul2d.ino: In function 'void loop()':
...\sketch_jul2d.ino:42:5: error: 'ledcSetup' was not declared in this scope
 42 | ledcSetup(LEDC_CHANNEL, freq, 16);
 | ^~~~~~~~~
exit status 1
Compilation error: 'ledcSetup' was not declared in this scope
Comment options

Use the examples in our repository as a reference or documentation.
Your code is using old API from 2.x versions.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Converted from issue

This discussion was converted from issue #11526 on June 30, 2025 07:54.

AltStyle によって変換されたページ (->オリジナル) /