
机甲小师
简介
参考RoboMaster英雄机器人设计的丐版,可视化操作界面、可支持人脸识别解锁与自动锁头,配合二维云台发射激光武器等功能,配合全向麦轮底盘,打造一个预算有限成本极低的“机甲小师”!
简介:参考RoboMaster英雄机器人设计的丐版,可视化操作界面、可支持人脸识别解锁与自动锁头,配合二维云台发射激光武器等功能,配合全向麦轮底盘,打造一个预算有限成本极低的“机甲小师”!开源协议
:GPL 3.0
描述
题目要求
机甲小师
题目分析
参考RoboMaster英雄机器人设计的丐版,可视化操作界面、模式切换、可支持人脸识别解锁与自动锁头、纯视觉测距,配合二维云台发射激光武器等功能,配合全向麦轮底盘,打造一个预算有限成本极低的“机甲小师”!另外,在经济条件允许的情况下,还可以拓展更多控制机构(比如上下位机加装六自由度的旋转电位器控制机械臂、水弹枪...)、增加实时图传,设计基本可以涵盖STM32F103c8t6常用的片上外设、基础的机器视觉算法、基础的运动控制算法、滤波算法、还涉及多端代码联调、模块选型等。可以作为一个基础的练手项目!!!
后期计划打造一个完整的满血“机甲小师”:不依赖模块的高度集成化、更精准的控制机构、全3D打印炫酷外壳、多种武器选择、无线图传+屏幕直控等,敬请期待
总体设计方案框图

原理图设计说明
发送与接收端均通过STM32引脚特性进行了简单的引脚分配,配合拓展接口直接与各模块连接,大大降低了开发难度


PCB设计说明
遥控器PCB部分

主控PCB

第一代版本基本都是使用的电路模块,设计简单制作较为方便而且容错较高,发送端的板框按实际的串口屏尺寸做的,不同方案需要自行设计相应的尺寸。
软件说明
摄像头端:使用嘉楠科技的CanMV IDE K230开发,示例程序在立创官方的网站https://wiki.lckfb.com/zh-hans/lushan-pi-k230/ 可以找到(有好多好玩的例程,稍加改造就有很不错的效果!!!),本次开发借鉴了其中人脸识别和人体关键点检测,如果有其他识别需求也可以在这里面找找;

发送端&接收端:基于keil标准库进行开发
串口屏:使用陶晶驰官方开发软件USART HMI进行相关开发

代码块:
舵机控制方面,接收到摄像头采集的目标坐标信息后,通过多级步长调节控制舵机在不同位置采用不同的速度,相较于PID来说,大大降低了部署难度,有很不错的鲁棒性
*舵机参数自定义
// 三级速度分区阈值,XY独立配置
#define LOOP_DELAY_MS 5
#define IMPROVE_THRESHOLD 0.3f
#define DATA_WINDOW_SIZE 3
#define DEAD_ZONE 0.5f
// X轴速度分区阈值(独立):±5外=步长3,±2~±5=步长2,±2内=步长1
#define X_FAR_THRESHOLD 5.0f // X轴远距阈值
#define X_NEAR_THRESHOLD 2.0f // X轴近距阈值
// Y轴速度分区阈值(独立):±5外=步长3,±2~±5=步长2,±2内=步长1
#define Y_FAR_THRESHOLD 5.0f // Y轴远距阈值
#define Y_NEAR_THRESHOLD 2.0f // Y轴近距阈值
// 三级步长定义
#define STEP_FAST 4 // 快速步长(远距)
#define STEP_MID 2 // 中速步长(中距)
#define STEP_SLOW 1 // 慢速步长(近距)
// -------------------------- X轴动态调整(三级速度,独立控制)--------------------------
if (fabs(filt_x) > DEAD_ZONE) {
float delta_x = fabs(filt_x) - fabs(last_filtered_x);
int current_step = STEP_SLOW; // 默认慢速
// 根据X轴距离选择步长
if (fabs(filt_x) > X_FAR_THRESHOLD) {
current_step = STEP_FAST;
} else if (fabs(filt_x) > X_NEAR_THRESHOLD) {
current_step = STEP_MID;
}
if (filt_x > 0) {
// 目标在中心右侧(X正):右转(角度减小)
if (delta_x < -IMPROVE_THRESHOLD) {
servo_x_angle = limit_angle(servo_x_angle - current_step, 1, 179);
} else if (delta_x > IMPROVE_THRESHOLD) {
servo_x_angle = limit_angle(servo_x_angle - current_step, 1, 179);
} else {
// 坐标稳定:步长减半,避免过冲
servo_x_angle = limit_angle(servo_x_angle - (current_step / 2), 1, 179);
}
} else {
// 目标在中心左侧(X负):左转(角度增大)
if (delta_x < -IMPROVE_THRESHOLD) {
servo_x_angle = limit_angle(servo_x_angle + current_step, 1, 179);
} else if (delta_x > IMPROVE_THRESHOLD) {
servo_x_angle = limit_angle(servo_x_angle + current_step, 1, 179);
} else {
servo_x_angle = limit_angle(servo_x_angle + (current_step / 2), 30, 179);
}
}
}
// -------------------------- Y轴动态调整(三级速度,独立控制)--------------------------
if (fabs(filt_y) > DEAD_ZONE) {
float delta_y = fabs(filt_y) - fabs(last_filtered_y);
int current_step = STEP_SLOW; // 默认慢速
// 根据Y轴距离选择步长
if (fabs(filt_y) > Y_FAR_THRESHOLD) {
current_step = STEP_FAST;
} else if (fabs(filt_y) > Y_NEAR_THRESHOLD) {
current_step = STEP_MID;
}
if (filt_y > 0) {
// 目标在中心下方(Y正):上转(角度增大)
if (delta_y < -IMPROVE_THRESHOLD) {
servo_y_angle = limit_angle(servo_y_angle + current_step, 30, 179);
} else if (delta_y > IMPROVE_THRESHOLD) {
servo_y_angle = limit_angle(servo_y_angle + current_step, 30, 179);
} else {
servo_y_angle = limit_angle(servo_y_angle + (current_step / 2), 30, 179);
}
} else {
// 目标在中心上方(Y负):下转(角度减小)
if (delta_y < -IMPROVE_THRESHOLD) {
servo_y_angle = limit_angle(servo_y_angle - current_step, 30, 179);
} else if (delta_y > IMPROVE_THRESHOLD) {
servo_y_angle = limit_angle(servo_y_angle - current_step, 30, 179);
} else {
servo_y_angle = limit_angle(servo_y_angle - (current_step / 2),30, 179);
}
}
}
视觉处理部分代码
视觉方面,距离检测是基于立创·庐山派K230官方文档里的“人体关键点检测”改造而成的:通过计算肩部关键点与耳朵关键点的像素距离,与正常人类的平均长度推导出当前距离;由于时间问题,代码这里仅做一个大致的推算演示,精度不是很高,如果想更精进,可以多加几组(比如肩宽、臂长等)
```
import math
EAR_TO_SHOULDER_CM = 20 # 耳到肩实际物理距离(cm)
FOCAL_LENGTH = 900 # 摄像头焦距(像素)
KEYPOINT_CONF_THRESH = 0.3 # 关键点置信度阈值
def calc_person_distance(kpses):
"""
单目测距逻辑
:param kpses: 模型输出关键点 [person_idx][kp_idx][x, y, confidence]
:return: 实际距离(cm),无效返回None
"""
# 关键点索引
left_ear = kpses[0][3] # 左耳(索引3)
left_shoulder = kpses[0][5]# 左肩(索引5)
right_ear = kpses[0][4] # 右耳(索引4)
right_shoulder = kpses[0][6]# 右肩(索引6)
# 过滤低置信度关键点
valid_pairs = []
if left_ear[2] > KEYPOINT_CONF_THRESH and left_shoulder[2] > KEYPOINT_CONF_THRESH:
valid_pairs.append((left_ear, left_shoulder))
if right_ear[2] > KEYPOINT_CONF_THRESH and right_shoulder[2] > KEYPOINT_CONF_THRESH:
valid_pairs.append((right_ear, right_shoulder))
if not valid_pairs:
return None
# 计算平均像素距离
total_pixel_dist = 0
for (kp1, kp2) in valid_pairs:
# 像素
pixel_dist = math.hypot(kp2[0]-kp1[0], kp2[1]-kp1[1])
total_pixel_dist += pixel_dist
avg_pixel_dist = total_pixel_dist / len(valid_pairs)
# 实际距离 = (物理尺寸 × 焦距) / 像素距离
return (EAR_TO_SHOULDER_CM * FOCAL_LENGTH) / avg_pixel_dist
这里有个比较有意思的代码,时摇杆的一个初始化校准,因为它默认状态下电位偏的特别离谱,因此加了一个校准功能:上电后读取此时的XY轴的电位,将此时的电位作为中间值重新计算两侧的电位值
static void Joystick_AutoCalibrate(void)
{
Delay_Ms(200);
uint32_t x_sum = 0, y_sum = 0;
for (uint8_t i = 0; i < 5; i++)
{
x_sum += ADC_ReadChannel(ADC_Channel_1); // X=A1
y_sum += ADC_ReadChannel(ADC_Channel_0); // Y=A0
Delay_Ms(10);
}
uint16_t x_center = x_sum / 5;
uint16_t y_center = y_sum / 5;
x_offset = x_center - JOY_CALIB_MID;
y_offset = y_center - JOY_CALIB_MID;
}
// 摇杆数据(读取+校准+处理)
void Joystick_Update(JoystickData *data) {
// 读取原始ADC值
uint16_t x_raw = ADC_ReadChannel(ADC_Channel_1);
uint16_t y_raw = ADC_ReadChannel(ADC_Channel_0);
// 应用校准并限制范围
int32_t x_calibrated = (int32_t)x_raw - x_offset;
data->x_raw = (x_calibrated < 0) ? 0 : (x_calibrated > ADC_MAX) ? ADC_MAX : (uint16_t)x_calibrated;
int32_t y_calibrated = (int32_t)y_raw - y_offset;
data->y_raw = (y_calibrated < 0) ? 0 : (y_calibrated > ADC_MAX) ? ADC_MAX : (uint16_t)y_calibrated;
// 计算角度
data->x_angle = (uint8_t)((data->x_raw * 180.0f) / ADC_MAX);
data->y_angle = (uint8_t)((data->y_raw * 180.0f) / ADC_MAX);
}
实物展示说明

发送端串口屏部分UI

后面又做了简单的外壳,,,就是它的头怎么大大的

注意事项
发送端的STM32是焊在反面的,注意不要搞错了
舵机安装前要确保初始角度均在90°的位置
串口通信注意配置合适的波特率、TR不要接错
##硬件选型

演示视频
【立创开源活动-哔哩哔哩】 https://b23.tv/IaBH3O6
其它附件上传
通过网盘分享的文件:机甲小师开源资料.zip
链接: https://pan.baidu.com/s/1gqt7Km1rPFPJojcqwo31qw 提取码: 0717
设计图
未生成预览图,请在编辑器重新保存一次BOM
暂无BOM
克隆工程知识产权声明&复刻说明
本项目为开源硬件项目,其相关的知识产权归创作者所有。创作者在本平台上传该硬件项目仅供平台用户用于学习交流及研究,不包括任何商业性使用,请勿用于商业售卖或其他盈利性的用途;如您认为本项目涉嫌侵犯了您的相关权益,请点击上方“侵权投诉”按钮,我们将按照嘉立创《侵权投诉与申诉规则》进行处理。
请在进行项目复刻时自行验证电路的可行性,并自行辨别该项目是否对您适用。您对复刻项目的任何后果负责,无论何种情况,本平台将不对您在复刻项目时,遇到的任何因开源项目电路设计问题所导致的直接、间接等损害负责。










