一、项目介绍
本项目以"感知——机械臂"为创意方向,旨在开发一款低成本的智能控制板,实现通过电脑对三自由度机械臂的智能控制。传统淘宝上20元左右的舵机机械臂套件通常仅支持物理摇杆控制,缺乏智能化和交互性,无法满足现代用户对智能硬件的需求。针对这一痛点,我设计并实现了一套基于微控制器(MCU)的控制方案,通过电脑与机械臂的交互,实现了对机械臂的智能控制,为低成本具身智能硬件开发提供了可行路径。
本项目的亮点在于将本地部署的Qwen3:4b大语言模型与低成本硬件结合,使机械臂能够通过自然语言指令进行控制,突破了传统机械臂仅能通过预设指令或物理摇杆控制的局限,大大提升了交互体验和智能化水平。通过这一项目,不仅实现了机械臂的智能控制,还为后续的智能硬件开发积累了宝贵经验。
二、硬件介绍
硬件名称 | 型号/规格 | 功能说明 |
MCU芯片 | GD32F310K8U6 | 接收指令、处理控制逻辑、生成PWM信号控制舵机 |
USB转串口芯片 | CH340B | 实现USB接口与串口通信的转换,便于与电脑连接 |
机械臂套件 | 淘宝购买,包含4个SG90舵机 | 三自由度机械臂,包括基座、左臂、右臂和夹爪 |
交互设备 | 笔记本电脑 | 作为用户交互界面,运行Python终端程序,向MCU发送控制指令 |
特别的,本项目使用活动指定厂家TE Connectivity的3Pin 2.54mm绿色排针用于在控制板和4个舵机之间提供稳定可靠的电气连接(https://www.digikey.cn/zh/products/detail/te-connectivity-amp-connectors/826926-3/2135839)。
三、项目设计思路介绍
本项目的整体设计采用"电脑-控制板-机械臂"的交互架构,系统框图如下:

设计思路基于以下核心考虑:
- 低成本:选择GD32F310K8U6(约4.9元)和CH340N(约3.4元)等性价比高的元器件,确保芯片成本控制在10元以内,使项目具有广泛的推广价值。
- 易用性:通过电脑进行交互,避免了额外的物理控制设备,用户只需通过简单的指令即可控制机械臂,大大降低了使用门槛。
- 智能化:引入本地部署的Qwen3:4b大模型,实现自然语言指令识别,使控制更加直观和智能,无需用户记忆预设指令。
- 扩展性:系统设计采用模块化思路,便于后续增加更多功能。
四、原理图和PCB介绍
我使用KiCad 7.0进行了一版PCB设计。PCB采用低成本的双层板设计,外形为L形。串口通信及PWM波形输出在实际测试中表现稳定,满足了项目需求。
控制板PCB提供4个SG90舵机接口、一个USB通信兼供电接口、MCU调试接口和复位按键。对于感兴趣的使用者,控制板预留了2个用户按键并引出多个MCU引脚,方便外接其他模块实现自定义功能。
控制板的USB2为通信兼供电接口,必须焊接,USB1仅限供电,可以空置。


我设计了一套PETG外壳安装控制板。安装时根据Type-C数据线的实际接口厚度,可适当打磨USB2处的外壳。

五、关键代码介绍
1. 电脑端软件
本项目基于Python开发,基于大语言模型(qwen3:4b)实现机械臂的自然语言控制系统。它创建两个独立线程,分别用于串口指令的异步发送与接收,确保通信的实时性和可靠性。系统支持两种指令模式:自然语言指令通过LLM解析为电机控制命令,直接控制指令(/direct_ctrl)直接映射到对应的电机通道。串口指令的格式为:pwm_cmd <电机编号> <PWM增量值>,用于控制4通道机械臂电机的运动方向和幅度。

LLM客户端核心代码:
class OllamaClient:
"""Client for interacting with Ollama text-based language models."""
def generate(self, prompt: str, model: str = "qwen3:4b",
stream: bool = False, timeout: int = 90) -> tuple:
"""Generate text response from the language model."""
payload = {
"model": model,
"prompt": prompt,
"stream": stream,
}
resp = requests.post(self.api_url, json=payload, timeout=timeout)
data = resp.json()
text = self._extract_text(data)
return data, text
class OllamaClientWrapper:
def generate_with_rules(self, user_input: str, rules: str,
model: str = "qwen3:4b") -> str:
"""Generate text response by combining rules with user input."""
combined_prompt = f"{rules}\n\n用户指令: {user_input}\n\n请根据上述规则解析用户指令并输出对应的控制命令。"
return self.generate(combined_prompt, model=model)
串口通信核心代码:
class SerialArmController:
"""Controller for robotic arm serial communication."""
def __init__(self, port: str, baudrate: int = 115200,
timeout: float = 1.0, verbose: bool = False):
self.serial_conn = None
self.command_queue = queue.Queue()
self.running = False
self.sender_thread = None
self.receiver_thread = None
self.lock = threading.Lock()
def send_motor_command(self, channel: MotorChannel,
delta_timer_cnt: int) -> bool:
"""Send motor control command to the queue."""
# Build command string: "pwm_cmd <channel> <delta_timer_cnt>"
command = f"pwm_cmd {int(channel)} {delta_timer_cnt}"
self.command_queue.put(command, timeout=1.0)
return True
2.MCU端软件
本项目基于RT-Thread 4.1操作系统设计GD32F310K8U6的嵌入式程序。它创建两个线程。一个用于解析上位机下达的串口指令,另一个控制LED按周期闪烁,展示操作系统正常工作状态。串口指令的格式为:pwm_cmd <pwm通道编号> <定时器输出比较值的增量>。

串口通信线程的代码:
struct rt_device_pwm *pwm1_dev;
struct rt_device_pwm *pwm2_dev;
struct rt_device_pwm *pwm3_dev;
struct rt_device_pwm *pwm4_dev;
typedef struct{
int idx;
int cnt;
int high;
int low;
} pwmx_cnt;
static pwmx_cnt pwm1_cnt ={.idx=1, .cnt=1750000, .high=2200000, .low=1200000};
static pwmx_cnt pwm2_cnt ={.idx=2, .cnt=1850000, .high=2200000, .low=1550000 };
static pwmx_cnt pwm3_cnt ={.idx=3, .cnt=1780000, .high=2280000, .low=1530000 };
static pwmx_cnt pwm4_cnt ={.idx=4, .cnt=1660000, .high=1760000, .low=1610000 }; //gripper
static struct rt_semaphore pwm_sem;
typedef struct {
char message[64];
int count;
} thread_pwm_param_t;
static thread_pwm_param_t thread_pwm_param = {
.message = "Custom message from thread parameter",
.count = 0
};
static void pwm_thread_entry(void *parameter)
{
thread_pwm_param_t *param = (thread_pwm_param_t *)parameter;
while (1) {
rt_sem_take(&pwm_sem, RT_WAITING_FOREVER);
++param->count;
}
}
static int eval_pwm_cmd(pwmx_cnt* ch, struct rt_device_pwm* pwmx, int val){
int new_cnt = ch->cnt + val;
if(new_cnt<ch->low) new_cnt=ch->low;
else if(new_cnt>ch->high) new_cnt=ch->high;
ch->cnt=new_cnt;
rt_pwm_set(pwmx, 4-ch->idx, 20000000, new_cnt);
rt_kprintf("{\"CH\":%d,\"val\":%d}\n",ch->idx,ch->cnt);
return 0;
}
static int pwm_cmd(int argc, char **argv)
{
int CH=-1, val=99;
pwmx_cnt* ch_select;
struct rt_device_pwm* pwmx_select;
rt_sem_release(&pwm_sem);
if (argc ==3) {
CH = atoi(argv[1]);
val = atoi(argv[2]);
switch(CH){
case 1:
ch_select = &pwm1_cnt; pwmx_select=pwm1_dev; break;
case 2:
ch_select = &pwm2_cnt; pwmx_select=pwm2_dev; break;
case 3:
ch_select = &pwm3_cnt; pwmx_select=pwm3_dev; break;
case 4:
ch_select = &pwm4_cnt; pwmx_select=pwm4_dev; break;
default:
rt_kprintf("{\"CH\":-1,\"val\":-1}\n");
return 0;
}
eval_pwm_cmd(ch_select, pwmx_select ,val);
}
else{
rt_kprintf("{\"CH\":-1,\"val\":-1}\n");
}
return 0;
}
int pwm_thread_init(void)
{
rt_sem_init(&pwm_sem, "pwm_sem", 0, RT_IPC_FLAG_FIFO);
rt_thread_t thread = rt_thread_create("pwm_thread",pwm_thread_entry,&thread_pwm_param,512, 10, 10);
if (thread != RT_NULL) {
rt_thread_startup(thread);
//rt_kprintf("PWM thread created and started!\n");
} else {
rt_kprintf("Failed to create PWM thread!\n");
return -1;
}
return 0;
}
MSH_CMD_EXPORT(pwm_cmd, "pwm_cmd - advanced pwm configurations");
INIT_APP_EXPORT(pwm_thread_init);
六、实物图片

控制板的预留引脚和按键为感兴趣的用户提供在本项目开源代码基础上进一步开发的空间。

大模型智能解析用户输入的自然语言指令“向右边的反方向移动”。
七、设计中遇到的难题和解决方法
1. 大模型模型部署效率低
- 问题描述:本地部署的Qwen3:14b模型在笔记本电脑CPU上运行很慢,影响了用户体验。
- 解决方法:一方面,优化部署方式。将Ollama服务部署于局域网内有Nvidia RTX GPU的Ubuntu服务器。通过SSH指令
ssh -N -L 11434:localhost:11434 -p <SSH_PORT> <USERNAME>@xxx.xxx.xxx.xxx(请按实际情况更改Ollama端口、SSH端口、用户名及IP地址)完成转发服务器的Ollama服务端口至本地,随后按照原先方式使用Ollama服务。另一方面,更换参数量较小的Qwen3:4b模型降低推理延迟。
2. 移植RT-Thread
- 问题描述:RT-Thread未提供GD32F3x0的支持包。
- 解决方法:参考教程https://blog.csdn.net/weixin_47569031/article/details/124014203。此外,编译Keil 5工程前需手动添加
gd32f3x0_syscfg.c。
八、心得体会
通过本次项目,我深刻体会到低成本智能硬件开发的挑战与乐趣。将Qwen3:4b大模型部署到本地并用于控制机械臂,让我亲身体验了AI与硬件结合的可行性,为未来智能硬件开发提供了宝贵经验。
总的来说,本项目不仅实现了预期的功能,还为未来的智能硬件开发积累了宝贵经验。通过将低成本硬件与AI技术结合,成功地打造了一个具有初步智能的机械臂控制系统,为具身智能硬件的普及提供了一个可行的方案。未来,我计划在此基础上增加视觉识别功能,使机械臂能够实现更复杂的任务,进一步提升其智能化水平。
备注:
1.MCU代码使用说明
将zip文件解压,放到rt-thread-lts-v4.1.x\bsp\gd32\arm后,在rt-thread-lts-v4.1.x\bsp\gd32\arm\gd32310k-start,打开工程project.uvprojx。该目录下的build\rtthread.hex是编译后的hex文件。