回到首页 返回首页
回到顶部 回到顶部
返回上一页 返回上一页
best-icon

【创意智造组】基于AI识别的电子元件学习和分类系统 简单

头像 江志灏 2026.04.08 9 0

项目背景

本项目围绕电子元件智能识别、学习辅助与自动分类展开,构建一套基于 AI 模型的轻量化实用系统,旨在解决电子入门学习、创客制作、硬件教学与元件整理中常见的元件辨识难、分类繁琐、知识记忆不直观等问题。

系统以计算机视觉与深度学习模型为核心,通过摄像头或图片输入,可识别LED灯、舵机、超声波模块、蓝牙模块、语音播放模块、温湿度模块等常见电子元器件,AI系统识别到电子元件后,系统自动输出元件名称、引脚定义、工作电压、典型参数与基础应用原理,实现 “拍摄即识别、识别即学习”。同时结合分类管理功能,支持对元件库进行自动归类、方便使用者快速查阅、收纳与教学演示。
在使用场景上,既可面向青少年创客、电子初学者提供轻量化学习工具,降低硬件入门门槛;也可用于工作室、实验室、课堂教学,实现元件快速盘点与知识可视化展示。系统兼顾实用性与易用性,模型轻量化、部署简单,可运行在电脑、开发板等常见设备上,为电子技术学习与实践提供智能化辅助。

二、下面对制作步骤进行讲解。

步骤1 对作品进行整体建模,作品三维模型三视图如下

作品立体视图

image.png

俯视图

image.png

正视图

image.png

右视图

image.png

行空板K10支架三维模型建模

image.png

行空板支架切片3D打印

image.png

步骤2 绘制模型激光切割图纸,激光切割图纸如下。

模型激光切割图纸1

image.png

模型激光切割图纸2

image.png

模型组装好的实际效果图

image.png

步骤3 下面对本次作品使用的编程软件和编程环境搭建进行讲解。

编程软件使用Mind+2以上版本,和所使用的硬件如图所示

image.png

步骤4 打开Mind+用里面的图像分类模块进行训练AI模型。

image.png

用摄像头直接获取图像的数据如图所示,每组图片获取100张,训练次数位50轮。

d078bc231f57b5aa84186e76a9a3d59b.png

训练过程中可以查看训练模型的进度和状态。

bab974a7ae8496dba668d15a0efc5049.png

模型训练完成后用对训练的模型进行校验,如效果不满意重新进行采集模型进行训练。AI模型经过反复训练,经过多次训练模型的识别率达到95%以上。训练效果如图所示。

9a98a71f889321ea6f0649b9f4dceaf7.png

62ce60e78bf96406276ebd69a6ff7c8d.png

770b881a63af878ce7383385bfe3300b.png

步骤5 将训练好的模型导出保存好模型。

image.png

将保存好的模型导入行空板M10.

image.png

步骤6 编写行空板AI识别程序,程序如图所示。

image.png
image.png
image.png

步骤7 编写行空板K10接收程序。

image.png
image.png
image.png
image.png

步骤8 用Arduino ide编写控制步进电机程序,如下图所示。

image.png
image.png
image.png
image.png
image.png
image.png
image.png

代码
/********************************************************************
 *  ESP32 + MQTT + 步进电机 + 舵机  (带串口打印消息)
 *  指令:chaoshengbo / LED / lanya / wenshidu / kongblank
 *  步进:DIR 17  STEP 5  EN 18    舵机:D19
 *  按键:D2/D4(内部上拉)        空闲自动断电,任务完再断电
 *******************************************************************/
#include <WiFi.h>          // ESP32 官方 Wi-Fi 库
#include <PubSubClient.h>  // MQTT 客户端库(IDE 库管理安装)
#include <ESP32Servo.h>    // 硬件 PWM 驱动舵机,不抢定时器

/* ==================== 用户配置 ==================== */
const char *ssid     = "WR793084";       // 路由器账号
const char *password = "81570750";       // 路由器密码
const char *mqtt_server = "10.1.2.3";    // SIoT 服务器 IP
const uint16_t mqtt_port = 1883;         // MQTT 默认端口
const char *mqtt_user     = "siot";      // SIoT 分配的用户名
const char *mqtt_pass     = "dfrobot";   // SIoT 分配的密码
const char *mqtt_clientID = "6268744424515"; // 客户端 ID,与 Python 端保持一致
const char *topic_sub     = "siot/shujujieshou"; // 订阅主题(接收指令)

/* ==================== 引脚定义 ==================== */
const uint8_t PIN_BTN_A = 2;   // 备用硬件按键(本例未用,可扩展)
const uint8_t PIN_BTN_B = 4;   // 备用硬件按键(本例未用,可扩展)
const uint8_t PIN_DIR   = 17;  // 步进方向信号:HIGH=正转,LOW=反转
const uint8_t PIN_STEP  = 5;   // 步进脉冲:上升沿走一步(DRV8825 最小 1 µs)
const uint8_t PIN_EN    = 18;  // 步进使能:LOW=工作,HIGH=断电(空闲关键)
const uint8_t PIN_SERVO = 19;  // 舵机信号脚,ESP32Servo 库自动分配 LEDC 通道

/* ==================== 机械参数 ==================== */
const uint16_t STEPS_PER_REV = 200;   // 42 步进电机 1.8°/步,整圈 200 步(全步)
const uint16_t MICROSTEP     = 1;     // 1=全步;若驱动板 MS1/2/3 接高可改 2/4/8/16/32
const uint16_t TOTAL_STEPS   = STEPS_PER_REV * MICROSTEP; // 实际一圈要发的步数
const uint32_t STEP_DELAY_US = 2000;  // 每步 2000 µs → 约 500 步/秒,想再慢就加大

const int SERVO_MID  = 90;     // 舵机中立位
const int SERVO_A_END = 120;   // ButtonA/chaoshengbo/lanya 要转到的角度
const int SERVO_B_END = 60;    // ButtonB/LED/wenshidu 要转到的角度
const uint16_t SERVO_DWELL = 500; // 到位后停留 500 ms,可改

/* ==================== MQTT ==================== */
WiFiClient   espClient;           // TCP 客户端
PubSubClient mqtt(espClient);     // MQTT 客户端,绑定 TCP

/* ==================== 舵机 ==================== */
Servo myServo;                      // ESP32Servo 对象,占用硬件 LEDC

/* ==================== 状态 ==================== */
volatile bool  msgReady   = false;  // 收到一条新消息(10 次相同后置位)
String         lastMsg    = "";     // 上一次消息内容,用于比对
uint8_t        sameCnt    = 0;      // 相同消息连续计数
bool           running    = false;  // 机械动作正在跑(软件锁)
long           currentPos = 0;      // 步进绝对位置(步),0 就是原点

/* ==================== 工具函数 ==================== */
void stepOnce(bool dir) {
  digitalWrite(PIN_DIR, dir ? HIGH : LOW); // 先给方向,再发脉冲(DRV8825 要求)
  digitalWrite(PIN_STEP, HIGH);            // 上升沿触发走一步
  delayMicroseconds(2);                    // 脉宽 > 1 µs 即可
  digitalWrite(PIN_STEP, LOW);             // 拉低准备下次上升沿
  delayMicroseconds(STEP_DELAY_US);        // 速度控制:延时决定每秒步数
}

void moveSteps(long target) {
  long steps = target - currentPos; // 可正可负,算出剩余步数
  int  dir   = steps > 0 ? 1 : -1;  // 1=正转,-1=反转
  steps = abs(steps);
  for (long i = 0; i < steps; i++) {
    stepOnce(dir > 0);              // 走一步
    currentPos += dir;              // 实时更新绝对位置,方便“回零”
  }
}

void servoMove(int angle) {
  myServo.write(angle);         // ESP32Servo 库底层用 LEDC,精度 16 位
  delay(SERVO_DWELL);           // 简单阻塞等待,可改成非阻塞
}

/* ==================== 机械动作 ==================== */
void execCmd(const String &cmd) {
  digitalWrite(PIN_EN, LOW); // 上电(使能驱动器)
  running = true;            // 上锁,防止重入
  if (cmd == "chaoshengbo" ) 
  {
    moveSteps(6L * TOTAL_STEPS);   // 6圈
    servoMove(SERVO_A_END);        // 90→120
    servoMove(SERVO_MID);          // 120→90
  } 
  else if ( cmd == "lanya")
  {
    moveSteps(16L * TOTAL_STEPS);   // 16圈
    servoMove(SERVO_A_END);        // 90→120
    servoMove(SERVO_MID);          // 120→90
    }
  else if(cmd == "wenshidu")
  {
    moveSteps(28L * TOTAL_STEPS);   // 28 圈
    servoMove(SERVO_A_END);        // 90→120
    servoMove(SERVO_MID);          // 120→90
    }
  else if (cmd == "LED" ) {
    moveSteps(6L * TOTAL_STEPS);  // 6 圈
    servoMove(SERVO_B_END);        // 90→60
    servoMove(SERVO_MID);          // 60→90
  } 
  else if (cmd == "duoji" ) {
    moveSteps(16L * TOTAL_STEPS);  // 16 圈
    servoMove(SERVO_B_END);        // 90→60
    servoMove(SERVO_MID);          // 60→90
  } 
  else if (cmd == "yuyingbofang" ) {
    moveSteps(28L * TOTAL_STEPS);  // 28 圈
    servoMove(SERVO_B_END);        // 90→60
    servoMove(SERVO_MID);          // 60→90
  } 
  
  else if (cmd == "kongblank") {
    ; // 空指令,什么都不做
  }
  moveSteps(0);               // 回到原点(currentPos=0)
  running = false;            // 解锁
  digitalWrite(PIN_EN, HIGH); // 立即断电,电机自由、不发热、不锁轴
}

/* ==================== MQTT 回调 ==================== */
void mqttCallback(char *topic, byte *payload, unsigned int len) {
  String msg;
  for (int i = 0; i < len; i++) msg += (char)payload[i];

  // 1. 立即打印收到的消息
  Serial.print("MQTT recv: ");
  Serial.println(msg);

  if (msg == lastMsg) {
    sameCnt++;
  } else {
    sameCnt = 1;
    lastMsg = msg;
  }

  if (sameCnt >= 2 && !msgReady && !running) {
    Serial.print("2次相同消息触发 → ");
    Serial.println(msg);
    msgReady = true;
    mqtt.unsubscribe(topic_sub); // 暂停接收,避免干扰
  }
}

/* ==================== 连接 WiFi ==================== */
void setupWiFi() {
  WiFi.begin(ssid, password);
  while (WiFi.status() != WL_CONNECTED) {
    delay(500);
    Serial.print(".");
  }
  Serial.println("\nWiFi OK, IP=");
  Serial.println(WiFi.localIP());
}

/* ==================== 连接 MQTT ==================== */
void reconnectMQTT() {
  while (!mqtt.connected()) {
    Serial.print("MQTT connecting ...");
    if (mqtt.connect(mqtt_clientID, mqtt_user, mqtt_pass)) {
      mqtt.subscribe(topic_sub);
      Serial.println("connected & subscribed");
    } else {
      Serial.print("failed, state=");
      Serial.println(mqtt.state());
      delay(5000);
    }
  }
}

/* ==================== setup ==================== */
void setup() {
  Serial.begin(115200);

  /* 引脚初始化 */
  pinMode(PIN_EN, OUTPUT);
  pinMode(PIN_DIR, OUTPUT);
  pinMode(PIN_STEP, OUTPUT);
  digitalWrite(PIN_EN, HIGH); // 上电即断电

  /* 舵机初始化 */
  ESP32PWM::allocateTimer(0);
  myServo.setPeriodHertz(50);
  myServo.attach(PIN_SERVO, 500, 2500);
  myServo.write(SERVO_MID);

  /* 网络 & MQTT */
  setupWiFi();
  mqtt.setServer(mqtt_server, mqtt_port);
  mqtt.setCallback(mqttCallback);
}

/* ==================== loop ==================== */
void loop() {
  if (!mqtt.connected()) reconnectMQTT();
  mqtt.loop();

  if (msgReady) {               // 10 次相同消息已凑齐
    msgReady = false;
    sameCnt = 0;
    execCmd(lastMsg);           // 执行机械动作
    lastMsg = "";               // 清空上次消息
    mqtt.subscribe(topic_sub);  // 重新订阅,继续接收
  }
}

步骤9 用PS软件制作电子元件知识卡片,如图所示。

image.png

在行空板K10上面展示效果如图所示。

image.png

步骤10 搭建SIOT物联网服务器。

image.png

步骤11 拼装完成作品整体图片,如下图所示。

image.png

步骤12 作品视频实现效果,有不足的地方欢迎或建议欢迎批评指正留言。

评论

user-avatar