news 2026/6/11 2:59:51

用STM32F103C8T6和摇杆做个桌面小监控云台(SG90舵机+完整代码)

作者头像

张小明

前端开发工程师

1.2k 24
文章封面图
用STM32F103C8T6和摇杆做个桌面小监控云台(SG90舵机+完整代码)

用STM32F103C8T6打造智能桌面监控云台:从硬件搭建到控制逻辑优化

周末整理工作室时,发现抽屉里闲置的STM32开发板和几个SG90舵机,突然萌生一个想法——何不制作一个桌面监控云台?这个看似简单的小装置,不仅能观察盆栽生长状态,还能作为远程会议的第二视角,甚至监控宠物在家的活动情况。与市面上动辄上千元的专业云台相比,自制方案成本不到百元,却能获得完全定制化的控制体验。

1. 项目规划与硬件选型

1.1 核心组件功能解析

选择STM32F103C8T6作为主控并非偶然。这款被称为"蓝色药丸"的开发板,虽然只有64KB Flash和20KB RAM,但其72MHz的Cortex-M3内核完全能满足实时控制需求。更重要的是,它具备:

  • 12位ADC:精确读取摇杆模拟量
  • 4个通用定时器:其中TIM4可直接生成两路PWM信号
  • 丰富的GPIO:方便扩展其他传感器

SG90舵机的选择也经过深思熟虑。对比常见舵机参数:

型号扭矩(kg·cm)工作电压(V)重量(g)价格(元)
SG901.54.8-6.0915-20
MG90S2.54.8-7.21430-40
DS3218206.0-7.45580-100

对于桌面级应用,SG90在价格和性能间取得了完美平衡。虽然扭矩较小,但配合轻量化结构完全够用。

1.2 机械结构设计要点

云台的稳定性很大程度上取决于机械结构。经过多次迭代,我发现这些设计细节至关重要:

  • 重心平衡:摄像头安装位置应尽量靠近旋转中心
  • 减震处理:在舵机与支架间添加橡胶垫减少振动
  • 走线管理:使用螺旋套管整理线材,避免缠绕

一个实用的支架方案是3D打印L型转接件,将两个舵机正交安装。具体尺寸建议:

  • 水平旋转底座:80×80mm平台
  • 垂直旋转支架:高度60mm
  • 摄像头夹持部:适配常见网络摄像头

提示:没有3D打印机?可以用亚克力板激光切割,甚至改造旧玩具的齿轮结构。

2. 电路连接与信号处理

2.1 硬件接口定义

确保所有组件正确连接是项目成功的第一步。具体接线方式:

  1. 摇杆模块

    • VRx → PA2 (ADC1_IN2)
    • VRy → PA3 (ADC1_IN3)
    • +5V → 开发板5V输出
    • GND → 共地
  2. 舵机控制

    • 舵机1信号线 → PB8 (TIM4_CH3)
    • 舵机2信号线 → PB9 (TIM4_CH4)
    • 电源建议外接5V/2A适配器
// 引脚功能宏定义 #define JOYSTICK_X_ADC_CHANNEL ADC_Channel_2 #define JOYSTICK_Y_ADC_CHANNEL ADC_Channel_3 #define SERVO_HORIZONTAL_PIN GPIO_Pin_8 #define SERVO_VERTICAL_PIN GPIO_Pin_9

2.2 ADC采样优化技巧

原始代码中ADC采样存在可改进空间。通过以下措施提升响应速度:

  • 启用连续转换模式
  • 增加软件滤波
  • 动态调整采样时间

改进后的ADC初始化代码:

void ADC_Config(void) { ADC_InitTypeDef ADC_InitStructure; ADC_InitStructure.ADC_Mode = ADC_Mode_Independent; ADC_InitStructure.ADC_ScanConvMode = ENABLE; // 启用扫描模式 ADC_InitStructure.ADC_ContinuousConvMode = ENABLE; // 连续转换 ADC_InitStructure.ADC_ExternalTrigConv = ADC_ExternalTrigConv_None; ADC_InitStructure.ADC_DataAlign = ADC_DataAlign_Right; ADC_InitStructure.ADC_NbrOfChannel = 2; ADC_Init(ADC1, &ADC_InitStructure); // 配置采样时间 ADC_RegularChannelConfig(ADC1, JOYSTICK_X_ADC_CHANNEL, 1, ADC_SampleTime_28Cycles5); ADC_RegularChannelConfig(ADC1, JOYSTICK_Y_ADC_CHANNEL, 2, ADC_SampleTime_28Cycles5); ADC_DMACmd(ADC1, ENABLE); // 启用DMA可进一步提升效率 ADC_Cmd(ADC1, ENABLE); ADC_ResetCalibration(ADC1); while(ADC_GetResetCalibrationStatus(ADC1)); ADC_StartCalibration(ADC1); while(ADC_GetCalibrationStatus(ADC1)); ADC_SoftwareStartConvCmd(ADC1, ENABLE); // 启动连续转换 }

3. 控制算法进阶实现

3.1 摇杆死区处理

原始代码直接使用ADC原始值判断方向,实际操作中会发现舵机容易产生抖动。这是因为:

  • 摇杆中立点存在物理偏差
  • ADC采样存在噪声
  • 人手微小颤动会被放大

引入死区控制后,代码更健壮:

#define DEAD_ZONE 100 // 死区范围 void ProcessJoystick(int16_t x, int16_t y) { static uint8_t lastAngle1 = 90, lastAngle2 = 90; // X轴处理(水平方向) if(x < (2048 - DEAD_ZONE)) { if(lastAngle1 < 180) lastAngle1 += 2; } else if(x > (2048 + DEAD_ZONE)) { if(lastAngle1 > 0) lastAngle1 -= 2; } // Y轴处理(垂直方向) if(y < (2048 - DEAD_ZONE)) { if(lastAngle2 > 0) lastAngle2 -= 2; } else if(y > (2048 + DEAD_ZONE)) { if(lastAngle2 < 180) lastAngle2 += 2; } Set_Servo_Angle(lastAngle1, lastAngle2); }

3.2 运动平滑算法

直接设置舵机角度会导致运动生硬。加入加速度控制后,运动更自然:

typedef struct { uint8_t target; uint8_t current; float velocity; } ServoState; void UpdateServoPosition(ServoState *s) { float error = s->target - s->current; s->velocity += error * 0.01f; // P系数 s->velocity *= 0.9f; // 阻尼系数 // 限幅处理 if(s->velocity > 2.0f) s->velocity = 2.0f; if(s->velocity < -2.0f) s->velocity = -2.0f; s->current += (uint8_t)s->velocity; } // 在主循环中调用 ServoState servoX = {90, 90, 0}; ServoState servoY = {90, 90, 0}; void MainLoop() { // ...读取摇杆值 servoX.target = newXAngle; servoY.target = newYAngle; UpdateServoPosition(&servoX); UpdateServoPosition(&servoY); Set_Servo_Angle(servoX.current, servoY.current); delay_ms(20); }

4. 功能扩展与实用技巧

4.1 预设位功能实现

为方便快速定位,可添加三个预设位置:

  1. 归中位:(90°, 90°) 默认视角
  2. 左视位:(30°, 75°) 观察左侧
  3. 右视位:(150°, 75°) 观察右侧

通过按键切换预设位:

#define PRESET_COUNT 3 const uint8_t presets[PRESET_COUNT][2] = { {90, 90}, // 预设1 {30, 75}, // 预设2 {150, 75} // 预设3 }; uint8_t currentPreset = 0; void SwitchPreset() { currentPreset = (currentPreset + 1) % PRESET_COUNT; servoX.target = presets[currentPreset][0]; servoY.target = presets[currentPreset][1]; }

4.2 手机蓝牙控制方案

想摆脱线材束缚?添加HC-05蓝牙模块即可实现手机控制:

  1. 硬件连接:

    • TXD → PA10 (USART1_RX)
    • RXD → PA9 (USART1_TX)
    • VCC → 3.3V
    • GND → GND
  2. 协议设计示例:

    • 'L':向左转
    • 'R':向右转
    • 'U':向上转
    • 'D':向下转
    • 'C':归中

串口中断处理代码:

void USART1_IRQHandler(void) { if(USART_GetITStatus(USART1, USART_IT_RXNE)) { uint8_t cmd = USART_ReceiveData(USART1); switch(cmd) { case 'L': servoX.target -= 10; break; case 'R': servoX.target += 10; break; case 'U': servoY.target -= 10; break; case 'D': servoY.target += 10; break; case 'C': servoX.target = 90; servoY.target = 90; break; } // 限幅保护 if(servoX.target > 180) servoX.target = 180; if(servoX.target < 0) servoX.target = 0; if(servoY.target > 180) servoY.target = 180; if(servoY.target < 0) servoY.target = 0; } }

5. 实际应用中的问题排查

5.1 常见故障与解决方案

在多次项目实践中,我总结出这些典型问题:

  • 舵机抖动不稳

    • 检查电源是否充足(建议单独供电)
    • 添加1000μF电容稳压
    • 确保机械结构没有卡顿
  • 控制响应延迟

    • 优化主循环结构,移除不必要延时
    • 检查ADC采样周期设置
    • 确认没有其他中断抢占资源
  • 角度漂移问题

    • 重新校准舵机中立点
    • 检查PWM信号稳定性
    • 考虑使用带位置反馈的舵机

5.2 性能测试指标

为确保云台可靠工作,建议进行这些测试:

  1. 连续工作测试

    • 持续运行4小时,观察温升
    • 记录舵机齿轮是否打滑
  2. 负载能力测试

    • 逐步增加配重,直到舵机失步
    • 我的测试数据:
摄像头重量(g)水平转向速度(°/s)垂直转向速度(°/s)
509060
1007545
1505030
  1. 精度测试
    • 使用量角器测量实际角度
    • 记录重复定位误差

经过三个版本的迭代,我的云台现在可以平稳支持200g负载,定位精度达到±2°,完全满足日常监控需求。最令我惊喜的是,通过调整控制算法,SG90的寿命明显延长——连续工作半年仍保持良好状态。

版权声明: 本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若内容造成侵权/违法违规/事实不符,请联系邮箱:809451989@qq.com进行投诉反馈,一经查实,立即删除!
网站建设 2026/6/11 2:54:51

OpenMMD:将真人视频转换为3D动画的魔法工具完全指南

OpenMMD&#xff1a;将真人视频转换为3D动画的魔法工具完全指南 【免费下载链接】OpenMMD OpenMMD is an OpenPose-based application that can convert real-person videos to the motion files (.vmd) which directly implement the 3D model (e.g. Miku, Anmicius) animated…

作者头像 李华
网站建设 2026/6/11 2:53:52

中科院DexJoCo:面向灵巧操作的基准测试与工具集

A Benchmark and Toolkit for Task-Oriented Dexterous Manipulation on MuJoCo 实现人类水平的机器人操作能力&#xff0c;需要具备精细交互能力的灵巧机械手&#xff0c;以及标准化的评估基准。近期&#xff0c;来自中国科学院自动化研究所、上海交通大学、香港中文大学等单…

作者头像 李华
网站建设 2026/6/11 2:52:58

如何完整备份QQ空间记忆:GetQzonehistory新手终极指南

如何完整备份QQ空间记忆&#xff1a;GetQzonehistory新手终极指南 【免费下载链接】GetQzonehistory 获取QQ空间发布的历史说说 项目地址: https://gitcode.com/GitHub_Trending/ge/GetQzonehistory 你是否担心QQ空间里的青春记忆会随着时间流逝而消失&#xff1f;那些承…

作者头像 李华
网站建设 2026/6/11 2:51:14

13ft Ladder终极指南:3分钟搭建个人付费墙绕过工具

13ft Ladder终极指南&#xff1a;3分钟搭建个人付费墙绕过工具 【免费下载链接】13ft My own custom 12ft.io replacement 项目地址: https://gitcode.com/GitHub_Trending/13/13ft 你是否曾因付费墙而无法阅读《纽约时报》的深度报道&#xff1f;是否在Medium上看到精彩…

作者头像 李华
网站建设 2026/6/11 2:51:06

定时中断进不来?别只怪 Prescaler,看看 Counter Mode

摘要&#xff1a;TIM 配置 1ms 中断&#xff0c;示波器测出来却是 1.024ms&#xff1f;或者中断偶尔丢失&#xff1f;不是 SystemCoreClock 算错&#xff0c;而是 Counter Mode&#xff08;计数模式&#xff09;​ 与 Center-Aligned&#xff08;中心对齐&#xff09;​ 配置导…

作者头像 李华