#include <stdio.h>
#include "freertos/FreeRTOS.h"
#include "freertos/task.h"
#include "freertos/queue.h"
#include "esp_log.h"
#include "esp_adc/adc_oneshot.h"
#include "driver/ledc.h"
#define CONFIG_LOG_DEFAULT_LEVEL_VERBOSE (1)
#define CONFIG_LOG_MAXIMUM_LEVEL_VERBOSE (1)
#define CONFIG_LOG_MAXIMUM_LEVEL (5)
static const char *TAG = "ADC_LED_APP";
// 硬體配置
#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
// 宣告隊列控制物件
static QueueHandle_t adc_queue = NULL;
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_task(void *arg) {
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) {
ESP_ERROR_CHECK(adc_oneshot_read(adc_handle, ADC_CHAN, &raw_val));
if (abs(raw_val - last_val) >= 10) {
// 將百分比發送到隊列 (不等待)
xQueueSend(adc_queue, &raw_val, 0);
last_val = raw_val;
ESP_LOGD(TAG, "ADC值:%d%%", raw_val);
}
vTaskDelay(pdMS_TO_TICKS(20));
}
}
// LED 控制任務
void led_task(void *arg) {
int data = 0;
while (1) {
// 等待隊列訊息 (portMAX_DELAY 代表一直等到有資料為止)
if (xQueueReceive(adc_queue, &data, portMAX_DELAY)) {
ledc_set_duty(LEDC_MODE, LEDC_CHANNEL, data);
ledc_update_duty(LEDC_MODE, LEDC_CHANNEL);
ESP_LOGI(TAG, "LED亮度值:%d%%", data);
}
}
}
void app_main(void) {
esp_log_level_set(TAG, ESP_LOG_VERBOSE);
// 建立隊列 (長度為 1,我們只需要最新的數值)
adc_queue = xQueueCreate(1, sizeof(int));
ledc_init(); // 初始化 PWM
// 啟動任務
// adc_task 優先級稍高,確保讀取穩定
xTaskCreate(adc_task, "adc_task", 2048, NULL, 5, NULL);
xTaskCreate(led_task, "led_task", 2048, NULL, 4, NULL);
}