#include <stdio.h>
#include "freertos/FreeRTOS.h"
#include "freertos/task.h"
#include "esp_log.h"
#include "esp_adc/adc_oneshot.h"
#include "driver/ledc.h"
#define CONFIG_LOG_MAXIMUM_LEVEL 5
static const char *TAG = "ADC_PWM";
// 硬體配置
#define ADC_CHAN ADC_CHANNEL_6 // GPIO 7
#define LED_PIN GPIO_NUM_41 // GPIO 41
// LEDC (PWM) 配置
#define LEDC_TIMER LEDC_TIMER_0
#define LEDC_MODE LEDC_LOW_SPEED_MODE
#define LEDC_CHANNEL LEDC_CHANNEL_0
#define LEDC_DUTY_RES LEDC_TIMER_12_BIT // 12位元解析度(0-4095)
#define LEDC_FREQUENCY 5000 // 5kHz
void ledc_init() {
// 設置時脈
ledc_timer_config_t ledc_timer = {
.speed_mode = LEDC_MODE,
.timer_num = LEDC_TIMER,
.duty_resolution = LEDC_DUTY_RES,
.freq_hz = LEDC_FREQUENCY,
.clk_cfg = LEDC_AUTO_CLK
};
ledc_timer_config(&ledc_timer);
// 設置輸出通道
ledc_channel_config_t ledc_channel = {
.speed_mode = LEDC_MODE,
.channel = LEDC_CHANNEL,
.timer_sel = LEDC_TIMER,
// .intr_type = LEDC_INTR_DISABLE,
.gpio_num = LED_PIN,
.duty = 0,
.hpoint = 0
};
ledc_channel_config(&ledc_channel);
}
// ADC 讀取任務
void adc_pwm_task(void *arg) {
// 初始化ADC、建立ADC控制物件
adc_oneshot_unit_handle_t adc_handle;
adc_oneshot_unit_init_cfg_t init_cfg = { .unit_id = ADC_UNIT_1 };
ESP_ERROR_CHECK(adc_oneshot_new_unit(&init_cfg, &adc_handle));
adc_oneshot_chan_cfg_t chan_cfg = {
.bitwidth = ADC_BITWIDTH_DEFAULT,
.atten = ADC_ATTEN_DB_12,
};
ESP_ERROR_CHECK(adc_oneshot_config_channel(adc_handle, ADC_CHAN, &chan_cfg));
int raw_val = 0;
int last_val = -1;
while (1) {
if (adc_oneshot_read(adc_handle, ADC_CHAN, &raw_val) == ESP_OK) {
// 避免頻繁更新輸出
if(abs(raw_val - last_val) >= 10) {
// 直接將12位元ADC值設給12位元PWM
ledc_set_duty(LEDC_MODE, LEDC_CHANNEL, raw_val);
ledc_update_duty(LEDC_MODE, LEDC_CHANNEL);
ESP_LOGI(TAG, "ADC值:%d", raw_val);
last_val = raw_val;
}
}
vTaskDelay(pdMS_TO_TICKS(20)); // 短暫延遲
}
}
void app_main(void) {
esp_log_level_set(TAG, ESP_LOG_VERBOSE);
ledc_init(); // 初始化 PWM
// 啟動任務
xTaskCreate(adc_pwm_task, "adc_to_pwm", 3000, NULL, 4, NULL);
}