| 本帖最后由 创客编程张 于 2025-5-4 19:35 编辑 
 在城市化进程加速的今天,全球每年产生超过20亿吨生活垃圾,而错误分类导致的资源浪费和环境污染正成为严峻挑战。如何让垃圾桶"学会思考",让科技为环保赋能?这就是我们探索的答案。 
 接下来,就让我们一起完成这个独一无二的项目吧! 
 
 一、准备 
 二、编写程序 1.初始硬件配置 
			
			
			定义RGB LED的GPIO引脚(12/13/14)复制代码// RGB LED引脚配置
typedef enum {
    LED_R = 12,
    LED_G = 13,
    LED_B = 14
} led_pins_t;
// PWM配置
#define LEDC_CHANNEL_R   LEDC_CHANNEL_0
#define LEDC_CHANNEL_G   LEDC_CHANNEL_1
#define LEDC_CHANNEL_B   LEDC_CHANNEL_2
#define LEDC_RESOLUTION  LEDC_TIMER_8_BIT</font>
 配置PWM通道参数(8位分辨率)
 
 2.PWM初始化 初始化PWM定时器复制代码void ledc_init() {
    ledc_timer_config_t timer_conf = {
        .speed_mode = LEDC_LOW_SPEED_MODE,
        .duty_resolution = LEDC_RESOLUTION,
        .timer_num = LEDC_TIMER_0,
        .freq_hz = 5000,
        .clk_cfg = LEDC_AUTO_CLK
    };
    ledc_timer_config(&timer_conf);
    ledc_channel_config_t channel_conf = {
        .gpio_num = LED_R,
        .speed_mode = LEDC_LOW_SPEED_MODE,
        .channel = LEDC_CHANNEL_R,
        .timer_sel = LEDC_TIMER_0,
        .duty = 0,
        .hpoint = 0
    };
    ledc_channel_config(&channel_conf);
    
    // 类似配置G/B通道...
}</font>
 配置各颜色通道参数
作用:1.5kHz频率可避免LED闪烁 2. 需要为每个颜色通道重复配置(示例中只展示了红色通道) 
 3.灯光反馈系统 根据垃圾类型显示不同颜色复制代码void set_led_feedback(garbage_type_t type) {
    switch(type) {
        case RECYCLABLE:  // 蓝灯
            ledc_set_duty(LEDC_LOW_SPEED_MODE, LEDC_CHANNEL_B, 255);
            break;
        case HAZARDOUS:   // 红灯
            ledc_set_duty(...);
            break;
        // 其他case...
    }
    ledc_update_duty(...);
}</font>
 使用PWM混合颜色
 4.图像处理 复制代码static void preprocess_image(camera_fb_t *fb) {
    // 实现步骤:
    // 1. YUV422转RGB(摄像头原始格式转换)
    // 2. 缩放到模型输入尺寸
// 3. 归一化到[-1,1]或[0,1]范围
}</font>
 
5.AI推理(这里需要自己添加训练好的模型,由于我不会训练AI所以我花钱找人训练了一个,这里就不分享了哈,还请见谅) 要求:1.模型需量化为INT8格式(减小尺寸)复制代码static classification_result_t tflite_inference(const uint8_t *processed_img) {
    // 伪代码流程:
    // 1. 从文件系统加载model.tflite
    // 2. 创建解释器:tflite::MicroInterpreter
    // 3. 分配输入/输出张量
    // 4. 执行推理
    // 5. 解析概率分布
    return classification_result_t{...};
}
</font>
 2.输入数据对齐模型要求(尺寸/格式)
 3.使用TFLite Micro库进行部署
 6.主任务逻辑程序 复制代码void classification_task(void *arg) {
    while(1) {
        // 获取摄像头帧
        camera_fb_t *fb = esp_camera_fb_get();
        
        // 预处理→推理→反馈
        preprocess_image(fb);
        classification_result_t result = tflite_inference(fb->buf);
        set_led_feedback(result.type);
        
        // 释放资源
        esp_camera_fb_return(fb);
        vTaskDelay(500);
    }
}</font>
 
7.完整代码 复制代码#include "esp_camera.h"
#include "esp_timer.h"
#include "driver/ledc.h"
#define TAG "SMART_BIN"
// RGB LED引脚配置
typedef enum {
    LED_R = 12,
    LED_G = 13,
    LED_B = 14
} led_pins_t;
// PWM配置
#define LEDC_CHANNEL_R   LEDC_CHANNEL_0
#define LEDC_CHANNEL_G   LEDC_CHANNEL_1
#define LEDC_CHANNEL_B   LEDC_CHANNEL_2
#define LEDC_RESOLUTION  LEDC_TIMER_8_BIT
// 初始化PWM
void ledc_init() {
    ledc_timer_config_t timer_conf = {
        .speed_mode = LEDC_LOW_SPEED_MODE,
        .duty_resolution = LEDC_RESOLUTION,
        .timer_num = LEDC_TIMER_0,
        .freq_hz = 5000,
        .clk_cfg = LEDC_AUTO_CLK
    };
    ledc_timer_config(&timer_conf);
    ledc_channel_config_t channel_conf = {
        .gpio_num = LED_R,
        .speed_mode = LEDC_LOW_SPEED_MODE,
        .channel = LEDC_CHANNEL_R,
        .timer_sel = LEDC_TIMER_0,
        .duty = 0,
        .hpoint = 0
    };
    ledc_channel_config(&channel_conf);
    
    // 类似配置G/B通道...
}
// 智能灯光反馈
void set_led_feedback(garbage_type_t type) {
    switch(type) {
        case RECYCLABLE:
            ledc_set_duty(LEDC_LOW_SPEED_MODE, LEDC_CHANNEL_B, 255);
            break;
        case HAZARDOUS:
            ledc_set_duty(LEDC_LOW_SPEED_MODE, LEDC_CHANNEL_R, 255);
            break;
        case KITCHEN:
            ledc_set_duty(LEDC_LOW_SPEED_MODE, LEDC_CHANNEL_G, 255);
            break;
        case OTHER:
            ledc_set_duty(LEDC_LOW_SPEED_MODE, LEDC_CHANNEL_R, 150);
            ledc_set_duty(LEDC_LOW_SPEED_MODE, LEDC_CHANNEL_G, 255);
            break;
    }
    ledc_update_duty(LEDC_LOW_SPEED_MODE, LEDC_CHANNEL_R);
    // 更新其他通道...
}
// 图像预处理
static void preprocess_image(camera_fb_t *fb) {
    // 添加实际预处理逻辑:
    // 1. 色彩空间转换 (YUV422->RGB)
    // 2. 图像缩放 (根据模型输入尺寸)
    // 3. 直方图均衡化
    // 4. 归一化处理
}
// 基于TensorFlow Lite的推理函数
static classification_result_t tflite_inference(const uint8_t *processed_img) {
    // 伪代码示例:
    // 1. 加载TFLite模型
    // 2. 分配张量
    // 3. 执行推理
    // 4. 解析输出
    return (classification_result_t){
        .type = RECYCLABLE,
        .confidence = 0.92f
    };
}
void classification_task(void *arg) {
    while(1) {
        camera_fb_t *fb = esp_camera_fb_get();
        if (!fb) {
            ESP_LOGW(TAG, "Frame buffer acquisition failed");
            continue;
        }
        // 图像预处理流水线
        preprocess_image(fb);
        
        // 执行模型推理
        classification_result_t result = tflite_inference(fb->buf);
        
        // 显示结果
        ESP_LOGI(TAG, "Detected: %s (Confidence: %.2f%%)", 
            garbage_type_to_str(result.type), 
            result.confidence*100);
        // 灯光反馈
        set_led_feedback(result.type);
        
        // 释放资源
        esp_camera_fb_return(fb);
        
        // 非阻塞延迟
        vTaskDelay(pdMS_TO_TICKS(500));
    }
}</font>
 
三、最后我们可以在程序中加入自己训练的智能体(我不会训练AI所以我花钱找人训练了一个,这里就不分享了哈,还请见谅)。由于我也是初学者,程序中可能会有少许问题,大家可以检查修改。 
 最后连接esp32 s3 ai模块,上传程序。
 
 四、附件 
 就此,完!欢迎交流学习。 
 |