本帖最后由 创客编程张 于 2025-5-4 19:35 编辑
在城市化进程加速的今天,全球每年产生超过20亿吨生活垃圾,而错误分类导致的资源浪费和环境污染正成为严峻挑战。如何让垃圾桶"学会思考",让科技为环保赋能?这就是我们探索的答案。
接下来,就让我们一起完成这个独一无二的项目吧!
一、准备
二、编写程序 1.初始硬件配置
- // 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>
复制代码
定义RGB LED的GPIO引脚(12/13/14)
配置PWM通道参数(8位分辨率)
2.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>
复制代码
初始化PWM定时器
配置各颜色通道参数作用: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所以我花钱找人训练了一个,这里就不分享了哈,还请见谅) - 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>
复制代码
要求:1.模型需量化为INT8格式(减小尺寸)
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模块,上传程序。
四、附件
就此,完!欢迎交流学习。
|