Audio Signal via PWM with ESP32-C3
Posted: Sat Nov 02, 2024 2:04 pm
Hi guys,
I'm trying to control a passive buzzer with a GPIO output pin. This is on an ESP32-C3-Super-Mini-Board, and I'm using the IDF Framework for bare metal programming (i.e. no Arduino).
I was successful with generating audio in general, but only for the first call to tone_play(). When stopping audio and trying to re-start (with same or different frequency), it fails: I tried lots of variants, but I either get an error message
The code I have based on https://github.com/pcbreflux/espressif/ ... pio_task.c, and it looks as follows;
I have also experimented with adding
in the tone_stop() functuion, but it did not change much.
Also, in the log I'm getting a warning message
Any ideas?
I'm trying to control a passive buzzer with a GPIO output pin. This is on an ESP32-C3-Super-Mini-Board, and I'm using the IDF Framework for bare metal programming (i.e. no Arduino).
I was successful with generating audio in general, but only for the first call to tone_play(). When stopping audio and trying to re-start (with same or different frequency), it fails: I tried lots of variants, but I either get an error message
, or audio continues playing with the first chosen frequency (not with the new one). It seems the timer continues to run somehow, but I have not found any way to stop it properly so IDF would not complain anymore (and ledc_timer_del() does not seem to be available (anymore?)).E (1199) ledc: ledc_timer_del(767): timer hasn't been configured, or it is still running, please stop it with ledc_timer_pause first
The code I have based on https://github.com/pcbreflux/espressif/ ... pio_task.c, and it looks as follows;
Code: Select all
#define GPIO_SPEAKER GPIO_NUM_0
#define GPIO_OUTPUT_SPEED LEDC_LOW_SPEED_MODE // no LEDC_HIGH_SPEED_MODE for ESP32-C3
void tone_play(uint32_t freq) {
ledc_timer_config_t timer_conf;
timer_conf.speed_mode = GPIO_OUTPUT_SPEED;
timer_conf.duty_resolution = LEDC_TIMER_8_BIT;
timer_conf.timer_num = LEDC_TIMER_0;
timer_conf.freq_hz = freq;
timer_conf.clk_cfg = LEDC_AUTO_CLK; // Auto select the source clock
ledc_timer_config(&timer_conf);
ledc_channel_config_t ledc_conf;
ledc_conf.gpio_num = GPIO_SPEAKER;
ledc_conf.speed_mode = GPIO_OUTPUT_SPEED;
ledc_conf.channel = LEDC_CHANNEL_0;
ledc_conf.intr_type = LEDC_INTR_DISABLE;
ledc_conf.timer_sel = LEDC_TIMER_0;
ledc_conf.duty = 0x0; // 8 bit: 50%=0x7F, 100%=0xFF
ledc_conf.hpoint = 0;
ledc_channel_config(&ledc_conf);
ledc_set_duty(GPIO_OUTPUT_SPEED, LEDC_CHANNEL_0, 0x7F); // 50% duty cycle
ledc_update_duty(GPIO_OUTPUT_SPEED, LEDC_CHANNEL_0);
}
void tone_stop(void) {
ledc_set_duty(GPIO_OUTPUT_SPEED, LEDC_CHANNEL_0, 0);
ledc_update_duty(GPIO_OUTPUT_SPEED, LEDC_CHANNEL_0);
}
void _delay_ms(uint32_t ms) {
vTaskDelay(ms / portTICK_PERIOD_MS);
}
/* ... and this code in main() */
gpio_set_direction(GPIO_SPEAKER, GPIO_MODE_OUTPUT);
gpio_set_level(GPIO_SPEAKER, 0);
tone_play(n_o6_Dis); _delay_ms(500);
tone_stop();
_delay_ms(500);
tone_play(n_o4_C); _delay_ms(500);
tone_stop();
Code: Select all
ledc_timer_pause(GPIO_OUTPUT_SPEED, LEDC_TIMER_0);
ledc_stop(GPIO_OUTPUT_SPEED, LEDC_CHANNEL_0, 0);
Also, in the log I'm getting a warning message
which is not sure if it's related or meaning anything. I do not use GPIO0 for anything else.W (1199) ledc: GPIO 0 is not usable, maybe conflict with others
Any ideas?