《ESP32 学习笔记》 之Arduino环境下 如何优雅的输出 频率占空比可调 的PWM波

  • Arduino环境下,我们如何优雅的输出频率可变的PWM波?

  • 支持ADC功能的引脚请查看:引脚定义

这里我们就要借助 esp32-hal-ledc.c 和 esp32-hal-ledc.h 两个文件来完成 esp32-hal库 内置的 PWM 功能

1.在esp32-hal-ledc.c这个文件中,我们可以看到每个通道的和组、定时器的关系,共0~15个通道:

        ** LEDC Chan to Group/Channel/Timer Mapping
        ** ledc: 0  => Group: 0,  Channel: 0, Timer: 0
        ** ledc: 1  => Group: 0,  Channel: 1, Timer: 0
        ** ledc: 2  => Group: 0,  Channel: 2, Timer: 1
        ** ledc: 3  => Group: 0,  Channel: 3, Timer: 1
        ** ledc: 4  => Group: 0,  Channel: 4, Timer: 2
        ** ledc: 5  => Group: 0,  Channel: 5, Timer: 2
        ** ledc: 6  => Group: 0,  Channel: 6, Timer: 3
        ** ledc: 7  => Group: 0,  Channel: 7, Timer: 3
        ** ledc: 8  => Group: 1,  Channel: 0, Timer: 0
        ** ledc: 9  => Group: 1,  Channel: 1, Timer: 0
        ** ledc: 10 => Group: 1, Channel: 2, Timer: 1
        ** ledc: 11 => Group: 1, Channel: 3, Timer: 1
        ** ledc: 12 => Group: 1, Channel: 4, Timer: 2
        ** ledc: 13 => Group: 1, Channel: 5, Timer: 2
        ** ledc: 14 => Group: 1, Channel: 6, Timer: 3
        ** ledc: 15 => Group: 1, Channel: 7, Timer: 3

2. 在esp32-hal-ledc.h中,我们可以看到PWM相关的一些函数:

#ifndef _ESP32_HAL_LEDC_H_
#define _ESP32_HAL_LEDC_H_

#ifdef __cplusplus
extern "C" {
#endif

#include <stdint.h>
#include <stdbool.h>

typedef enum {
    NOTE_C, NOTE_Cs, NOTE_D, NOTE_Eb, NOTE_E, NOTE_F, NOTE_Fs, NOTE_G, NOTE_Gs, NOTE_A, NOTE_Bb, NOTE_B, NOTE_MAX
} note_t;

//channel 0-15 resolution 1-16bits freq limits depend on resolution
double      ledcSetup(uint8_t channel, double freq, uint8_t resolution_bits);//设置通道频率和分辨率
void        ledcWrite(uint8_t channel, uint32_t duty);//设置通道占空比
double      ledcWriteTone(uint8_t channel, double freq);//设置通道频率
double      ledcWriteNote(uint8_t channel, note_t note, uint8_t octave);//输出需要的音阶
uint32_t    ledcRead(uint8_t channel);//读取某个通道的占空比
double      ledcReadFreq(uint8_t channel);//读取通道频率
void        ledcAttachPin(uint8_t pin, uint8_t channel);//将通道与引脚绑定
void        ledcDetachPin(uint8_t pin);//解绑引脚与通道的关系


#ifdef __cplusplus
}
#endif

#endif /* _ESP32_HAL_LEDC_H_ */

3.其中ledcWriteNote函数为输出一些音阶,可以接上蜂鸣器发出一些简单的音频, 函数如下:

double ledcWriteNote(uint8_t chan, note_t note, uint8_t octave){
    const uint16_t noteFrequencyBase[12] = {
    //   C        C#       D        Eb       E        F       F#        G       G#        A       Bb        B
        4186,    4435,    4699,    4978,    5274,    5588,    5920,    6272,    6645,    7040,    7459,    7902
    };

    if(octave > 8 || note >= NOTE_MAX){
        return 0;
    }
    double noteFreq =  (double)noteFrequencyBase[note] / (double)(1 << (8-octave));
    return ledcWriteTone(chan, noteFreq);
}
  • 例子代码功能:在Arduino环境下输出频率可变的PWM波

/*
@功能:输出两路PWM,可调占空比
@时间:2020/3/5
@作者:刘泽文
@QQ:2822604962
*/
#include <WiFi.h>
 
#define LED1 19
#define LED2 22
#define LED1_OFF   digitalWrite(LED1, HIGH)//关灯1
#define LED1_ON    digitalWrite(LED1, LOW)//开灯1
#define LED1_PWM   digitalWrite(LED1, !digitalRead(LED1))//灯1闪烁
#define LED2_OFF   digitalWrite(LED2, HIGH)//关灯2
#define LED2_ON    digitalWrite(LED2, LOW)//开灯2
#define LED2_PWM   digitalWrite(LED2, !digitalRead(LED2))//灯2闪烁

int freq1 = 2000;    // 频率
int channel1 = 0;    // 通道0,共16个通道,0~15
int resolution1 = 10;   // 分辨率,取值0~20,duty最大取值为2^resolution-1

int freq2 = 2000;    // 频率
int channel2 = 1;    // 通道1,共16个通道,0~15
int resolution2 = 10;   // 分辨率,取值0~20,duty最大取值为2^resolution-1

void setup()
{
  ledcSetup(channel1, freq1, resolution1); // 设置通道0
  ledcSetup(channel2, freq2, resolution2); // 设置通道1
  ledcAttachPin(LED1, channel1);  // 将通道0与引脚19连接
  ledcAttachPin(LED2, channel2);  // 将通道1与引脚22连接
}

void loop()
{
  // 逐渐变亮
  for (int dutyCycle = 0; dutyCycle <= 1023; dutyCycle = dutyCycle + 5)
  {
    ledcWrite(channel1, dutyCycle);  // 输出PWM
    ledcWrite(channel2, 1023 - dutyCycle);  // 输出PWM
    delay(5);
  }

  // 逐渐变暗
  for (int dutyCycle = 1023; dutyCycle >= 0; dutyCycle = dutyCycle - 5)
  {
    ledcWrite(channel1, dutyCycle);  // 输出PWM
    ledcWrite(channel2, 1023 - dutyCycle);  // 输出PWM
    delay(5);
  }
}
  • 将代码上传到你的ESP32板卡上

实验效果:LED1 与 LED2 为呼吸灯状态,且亮度互补~

  • 14
    点赞
  • 54
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
ESP32上接收蓝牙音频并使用PWM输出音频,你需要使用适配蓝牙的库,如`ESP32-A2DP`库,并配置PWM输出来生成音频信号。以下是一个示例代码: 首先,确保你已经安装了`ESP32-A2DP`库。在Arduino IDE中,选择 "工具" -> "管理库",然后搜索并安装 "ESP32-A2DP" 库。 然后,使用以下示例代码: ```cpp #include <Arduino.h> #include <driver/adc.h> #include <esp_adc_cal.h> #include <A2DP_Sink.h> const int I2S_BCK_PIN = 26; // I2S Bit Clock pin const int I2S_WS_PIN = 25; // I2S Word Select pin const int I2S_SD_PIN = 22; // I2S Serial Data pin const int PWM_PIN = 4; // PWM output pin for audio A2DP_Sink a2dp_sink; void i2s_init() { i2s_begin(I2S_MODE_MASTER | I2S_MODE_TX); i2s_set_pin(I2S_BCK_PIN, I2S_WS_PIN, I2S_SD_PIN); } void iram_function audio_data_callback(const uint8_t *data, uint32_t len) { for (uint32_t i = 0; i < len; i += 4) { int16_t sample = (data[i + 1] << 8) | data[i]; ledcWrite(PWM_CHANNEL_0, sample >> 4); // Adjust the shift amount as per your requirement } } void setup() { Serial.begin(115200); a2dp_sink.setAudioDataCallback(audio_data_callback); ledcSetup(PWM_CHANNEL_0, 5000, 8); // Adjust the frequency and resolution as per your requirement ledcAttachPin(PWM_PIN, PWM_CHANNEL_0); i2s_init(); a2dp_sink.setSinkPinMode(); a2dp_sink.start("ESP32 Audio Sink"); } void loop() { // Do other tasks if needed } ``` 在此代码中,我们使用了`ESP32-A2DP`库来接收蓝牙音频数据。我们通过I2S接口将音频数据传输到ESP32,并使用PWM输出来生成音频信号。 你需要根据硬件连接情况修改`I2S_BCK_PIN`、`I2S_WS_PIN`和`I2S_SD_PIN`的引脚定义,确保与ESP32的I2S接口连接正确。同时,你还需要修改`PWM_PIN`的引脚定义,以确保与你的设备连接正确。 在`audio_data_callback`函数中,我们将音频数据转换为16位采样,并使用PWM输出来生成音频信号。你可以根据需要调整采样数据的处理方式和PWM输出的配置。 运行代码后,ESP32将接收蓝牙音频并通过PWM输出音频信号。请注意,这只是一个基本示例,实际应用可能需要更多的配置和处理。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值