当前位置:网站首页>Arduino框架下I2S控制ADC采样以及PWM输出示例解析
Arduino框架下I2S控制ADC采样以及PWM输出示例解析
2022-08-04 12:34:00 【perseverance52】
Arduino框架下I2S控制ADC采样以及PWM输出示例
ESP32 LED PWM 控制器介绍
LED PWM 控制器主要用于控制 LED,也可产生 PWM 信号用于其他设备的控制。该控制器有 8 路高速通道和 8 路低速通道。
LED PWM 控制器的高速通道和低速通道均支持硬件渐变功能,可在无需 CPU 干预的情况下自动改变 PWM 信号的占空比,也可由软件改变 PWM 信号的占空比,实现亮度和颜色渐变。此外,低速通道在 Sleep 模式下仍可运行。
LED PWM 控制器 高速模式或低速模式 通道运行的配置选项:
- 配置定时器:指定 PWM 信号的频率和占空比分辨率。
- 配置通道:绑定定时器和输出 PWM 信号的 GPIO引脚。
- 改变 PWM 信号:输出 PWM 信号来驱动 LED。可通过软件控制或使用硬件渐变功能来改变 LED 的亮度。
- 信息参考来源;
https://docs.espressif.com/projects/esp-idf/zh_CN/v4.3.1/esp32/api-reference/peripherals/ledc.html#ledc-api-supported-range-frequency-duty-resolution
频率和占空比分辨率支持范围
ledcSetup(channel, freq, resolution);
// 设置通道,频率,占空比分辨率
channel
:通道0 -7 为高速通道,7-15 为低速通道freq
:频率,最大设置5000
resolution
:占空比分辨率
LED PWM 控制器主要用于驱动 LED。该控制器 PWM 占空比设置的分辨率范围较广。比如,PWM 频率为 5 kHz 时,占空比分辨率最大可为 13 位。这意味着占空比可为 0 至 100% 之间的任意值,分辨率为 ~0.012%(2 ** 13 = 8192 LED 亮度的离散电平)。
LED PWM 控制器可用于生成频率较高的信号,足以为数码相机模组等其他设备计时。此时,最大频率可为 40 MHz,占空比分辨率为 1 位。也就是说,占空比固定为 50%,无法调整。
LED PWM 控制器 API 可在设定的频率和占空比分辨率超过 LED PWM 控制器硬件范围时报错。例如,试图将频率设置为 20 MHz、占空比分辨率设置为 3 位时,串行端口监视器上会报告如下错误:
E (196) ledc: requested frequency and duty resolution cannot be achieved, try reducing freq_hz or duty_resolution. div_param=128
此时,占空比分辨率或频率必须降低。比如,将占空比分辨率设置为 2 会解决这一问题,让占空比设置为 25% 的倍数,即 25%、50% 或 75%。
- 如设置的频率和占空比分辨率低于所支持的最低值,LED PWM 驱动器也会反映并报告,如:
E (196) ledc: requested frequency and duty resolution cannot be achieved, try increasing freq_hz or duty_resolution. div_param=128000000
占空比分辨率通常用 ledc_timer_bit_t 设置,范围是 10 至 15位。如需较低的占空比分辨率(上至 10,下至 1),可直接输入相应数值。
I2S ADC
- I2S ADC的采样频率最大值为5MHz(值为5000000)
- 初始化配置函数
void i2sInit(){
i2s_config_t i2s_config = {
.mode = (i2s_mode_t)(I2S_MODE_MASTER | I2S_MODE_RX | I2S_MODE_ADC_BUILT_IN),
.sample_rate = I2S_SAMPLE_RATE, // The format of the signal using ADC_BUILT_IN
.bits_per_sample = I2S_BITS_PER_SAMPLE_16BIT, // is fixed at 12bit, stereo, MSB
.channel_format = I2S_CHANNEL_FMT_RIGHT_LEFT,
.communication_format = I2S_COMM_FORMAT_STAND_I2S,
.intr_alloc_flags = ESP_INTR_FLAG_LEVEL1,
.dma_buf_count = 8,
.dma_buf_len = I2S_DMA_BUF_LEN,
.use_apll = false,
.tx_desc_auto_clear = false,
.fixed_mclk = 0
};
示例代码
/* This example demonstrates I2S ADC capability to sample high frequency analog signals. The PWM signal generated with ledc is only for ease of use when first trying out. To sample the generated signal connect default pins 22(PWM) and 32(Sampling) together. If you do not wish to generate PWM simply comment out the definition of constant GENERATE_PWM 如果不希望生成PWM,只需注释掉常量GENERATE_PWM的定义 Try to change the PWM_DUTY_PERCENT and see how to averaged value changes. The maximum for I2S ADC sampling frequency is 5MHz (value 5000000), however there will be many values repeated because the real I2S ADC的采样频率最大值为5MHz(值为5000000),但是由于真实的采样频率,会有很多值重复。 sampling frequency is much lower - By default this example will print values compatible with Arduino plotter 1. signal - all values 2. signal - averaged value You can change the number of sample over which is the signal averaged by changing value of AVERAGE_EVERY_N_SAMPLES If you comment the definition altogether the averaging will not be performed nor printed. If you do not wish to print every value, simply comment definition of constant PRINT_ALL_VALUES Note: ESP prints messages at startup which will pollute Arduino IDE Serial plotter legend. To avoid this pollution, start the plotter after startup (op restart) */
#include <driver/i2s.h>
// I2S(ADC输入GPIO 32)
#define I2S_SAMPLE_RATE (20000) // Max sampling frequency(最大采样频率) = 277.777 kHz
#define ADC_INPUT (ADC1_CHANNEL_4) //pin 32
#define I2S_DMA_BUF_LEN (1024)
// PWM输出
#define GENERATE_PWM
#define OUTPUT_PIN (22) //Pin 22
#define PWM_FREQUENCY ((I2S_SAMPLE_RATE)/4) //PWM 频率为 I2S采样率的1/4
#define PWM_DUTY_PERCENT (50)//占空比
//PWM 频率越高,占空比分辨率越低,反之则越高
#define PWM_RESOLUTION_BITS (2) //较低的比特分辨率可以获得更高的频率,占空比分辨率设置为 25% 的倍数,即 25%、50% 或 75%。
#define PWM_DUTY_VALUE ((((1<<(PWM_RESOLUTION_BITS)))*(PWM_DUTY_PERCENT))/100) // Duty value used for setup function based on resolution占空值用于根据分辨率设置功能
// Sample post processing
#define PRINT_ALL_VALUES
#define AVERAGE_EVERY_N_SAMPLES (20)
void i2sInit(){
i2s_config_t i2s_config = {
.mode = (i2s_mode_t)(I2S_MODE_MASTER | I2S_MODE_RX | I2S_MODE_ADC_BUILT_IN),
.sample_rate = I2S_SAMPLE_RATE, // The format of the signal using ADC_BUILT_IN
.bits_per_sample = I2S_BITS_PER_SAMPLE_16BIT, // is fixed at 12bit, stereo, MSB
.channel_format = I2S_CHANNEL_FMT_RIGHT_LEFT,
.communication_format = I2S_COMM_FORMAT_STAND_I2S,
.intr_alloc_flags = ESP_INTR_FLAG_LEVEL1,
.dma_buf_count = 8,
.dma_buf_len = I2S_DMA_BUF_LEN,
.use_apll = false,
.tx_desc_auto_clear = false,
.fixed_mclk = 0
};
Serial.printf("Attempting to setup I2S ADC with sampling frequency %d Hz\n", I2S_SAMPLE_RATE);//69444
if(ESP_OK != i2s_driver_install(I2S_NUM_0, &i2s_config, 0, NULL)){
Serial.printf("Error installing I2S. Halt!");
while(1);
}
if(ESP_OK != i2s_set_adc_mode(ADC_UNIT_1, ADC_INPUT)){
Serial.printf("Error setting up ADC. Halt!");
while(1);
}
if(ESP_OK != adc1_config_channel_atten(ADC_INPUT, ADC_ATTEN_DB_11)){
Serial.printf("Error setting up ADC attenuation. Halt!");
while(1);
}
if(ESP_OK != i2s_adc_enable(I2S_NUM_0)){
Serial.printf("Error enabling ADC. Halt!");
while(1);
}
Serial.printf("I2S ADC setup ok\n");
}
void setup() {
Serial.begin(115200);
while(!Serial);
#ifdef GENERATE_PWM
// PWM setup
Serial.printf("Setting up PWM: frequency = %d; resolution bits %d; Duty cycle = %d; duty value = %d, Output pin = %d\n", PWM_FREQUENCY, PWM_RESOLUTION_BITS, PWM_DUTY_PERCENT, PWM_DUTY_VALUE, OUTPUT_PIN);
uint32_t freq = ledcSetup(0, PWM_FREQUENCY , 12);//通道 频率 分辨率
if(freq != PWM_FREQUENCY){
Serial.printf("Error setting up PWM. Halt!");
while(1);
}
ledcAttachPin(OUTPUT_PIN, 0);
ledcWrite(0, PWM_DUTY_VALUE);
Serial.printf("PWM setup ok\n");
#endif
// Initialize the I2S peripheral
i2sInit();
}
void loop(){
// The 4 high bits are the channel, and the data is inverted
size_t bytes_read;
uint16_t buffer[I2S_DMA_BUF_LEN] = {
0};
#ifdef AVERAGE_EVERY_N_SAMPLES
uint32_t read_counter = 0;
uint32_t averaged_reading = 0;
uint64_t read_sum = 0;
#endif
while(1){
i2s_read(I2S_NUM_0, &buffer, sizeof(buffer), &bytes_read, 15);
//Serial.printf("read %d Bytes\n", bytes_read);
for(int i = 0; i < bytes_read/2; ++i){
#ifdef PRINT_ALL_VALUES
//Serial.printf("[%d] = %d\n", i, buffer[i] & 0x0FFF); // Print with indexes
Serial.printf("Signal:%d ", buffer[i] & 0x0FFF); // Print compatible with Arduino Plotter
#endif
#ifdef AVERAGE_EVERY_N_SAMPLES
read_sum += buffer[i] & 0x0FFF;
++read_counter;
if(read_counter == AVERAGE_EVERY_N_SAMPLES){
averaged_reading = read_sum / AVERAGE_EVERY_N_SAMPLES;
//Serial.printf("averaged_reading = %d over %d samples\n", averaged_reading, read_counter); // Print with additional info
Serial.printf("Averaged_signal:%d", averaged_reading); // Print compatible with Arduino Plotter
read_counter = 0;
read_sum = 0;
}
#endif
#if defined(PRINT_ALL_VALUES) || defined (AVERAGE_EVERY_N_SAMPLES)
Serial.printf("\n");
#endif
} // for
} // while
}
串口监视器输出信息
串口绘图器波形
- 相关文章:基于ESP-IDF《ESP32使用I2S控制ADC和DAC》
- 官方文档《LED PWM 控制器》
边栏推荐
猜你喜欢
随机推荐
七夕疯狂搞钱的年轻人,一周赚14万
广告电商系统开发
Oracle 19c 单实例 19.3.0 升级到19.11.0 详细教程
两个数组中用第二个数组的Value对比换第一个数组中的Key
Flutter教程大全合集(2022年版)
动规(16)-并查集基础题——格子游戏
5 cloud security management strategies enterprises should implement
TensorFlow学习记录(三):高阶操作 & 神经网络与全连接层
情人节浪漫3D照片墙【附源码】
ES 节点2G内存分析
【VSCode】一文详解vscode下安装vim后无法使用Ctrl+CV复制粘贴 使用Vim插件的配置记录
数据中台建设(九):数据中台资产运营机制
DC/DC电感底部要不要覆铜?
企业应当实施的5个云安全管理策略
接入华为游戏防沉迷,点击防沉迷弹窗后游戏闪退
Motion Rule (16)-Union Check Basic Questions-Grid Game
正则表达式
聚焦数据来源、数据质量和模型性能构建小微企业信用画像
“蔚来杯“2022牛客暑期多校训练营2 G、J、K
DateTimeFormatter api