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

俯视图

正视图

右视图

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

行空板支架切片3D打印

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

模型激光切割图纸2

模型组装好的实际效果图

步骤3 下面对本次作品使用的编程软件和编程环境搭建进行讲解。
编程软件使用Mind+2以上版本,和所使用的硬件如图所示

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

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

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

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



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

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

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



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




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







/********************************************************************
* 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软件制作电子元件知识卡片,如图所示。

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

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

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

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

返回首页
回到顶部


评论