
衡山派开发板RT-Thread实战SG90舵机PWM驱动与角度控制详解最近在做一个机械臂的小项目用到了SG90舵机正好手头有衡山派HSPI开发板就想着把舵机驱动移植到RT-Thread系统上。整个过程下来发现从原理理解到代码实现再到实际调试有不少需要注意的细节。今天我就把这次实战的经验整理出来手把手教你怎么在衡山派开发板上用PWM精准控制SG90舵机的角度。这篇文章适合正在学习嵌入式开发特别是对RISC-V、RT-Thread和舵机控制感兴趣的朋友。我会从SG90舵机的基本原理讲起一步步带你完成驱动代码的移植、配置和验证最后还会分析核心代码让你不仅知道怎么做更明白为什么这么做。1. 认识我们的“演员”SG90舵机在开始写代码之前咱们得先了解要控制的对象。SG90是一种微型舵机在机器人、航模里非常常见。核心参数一览参数规格说明驱动电压3V ~ 7.2V推荐使用5V供电电压太低扭矩不足太高可能烧坏。工作扭矩1.6 kg/cm在1厘米的力臂上能产生1.6公斤的力驱动小负载没问题。控制信号PWM脉冲宽度调制这是关键舵机角度由PWM信号的脉冲宽度决定。转动角度180度这是我们今天要控制的范围从0度到180度。信号周期20 ms控制信号需要每20ms发送一次也就是频率为50Hz。注意市面上还有一种360度连续旋转的舵机它不能控制角度只能控制旋转速度和方向。咱们今天用的是180度的版本别买错了。PWM控制原理小白版你可以把舵机想象成一个听话的“小弟”。你不需要告诉它具体转多少度而是通过发送一种特殊的“暗号”PWM波来指挥它。这个暗号就是每20ms发送一个高电平脉冲舵机会根据这个高电平持续的时间长短来判断应该转到哪个位置。0.5ms脉冲- 对应0度位置1.5ms脉冲- 对应90度中间位置2.5ms脉冲- 对应180度位置所以控制角度的核心任务就是让衡山派开发板产生一个周期20ms50Hz且高电平宽度在0.5ms到2.5ms之间可调的PWM信号。2. 工程搭建与驱动移植拿到舵机后第一步不是急着接线写代码而是把开发环境准备好把官方提供的驱动代码“搬”到我们的工程里。2.1 获取资料与驱动代码原始资料里提供了驱动代码的压缩包你需要从资料下载中心找到它。通常它会被放在类似\luban-lite\application\rt-thread\helloworld\user-bsp的文件夹下。如果你没看到user-bsp这个文件夹说明你还没完成模块移植的前置配置需要先去完成必要的环境搭建操作。2.2 修改Kconfig文件驱动代码放好后需要修改工程的Kconfig文件这样后续的配置菜单里才会出现SG90舵机的选项。用VSCode打开你的工程找到这个文件application\rt-thread\helloworld\Kconfig。在文件末尾的#endif语句之前添加下面这行代码# SG90舵机 source application/rt-thread/helloworld/user-bsp/sg90-steering-engine/Kconfig这行代码的作用是告诉构建系统“嘿我这里还有一个SG90舵机的配置目录你把它也包含进来。”2.3 使用menuconfig配置工程接下来我们要在图形化配置界面里启用SG90舵机模块。双击工程根目录下的win_env.bat脚本打开RT-Thread的Env配置工具。在Env命令行中输入scons --list-def查看所有可用的默认配置。找到名为d13x_JLC_rt-thread_helloworld的配置这是衡山派开发板的默认配置记住它的编号比如是7。应用这个配置scons --apply-def7或者直接用配置名scons --apply-defd13x_JLC_rt-thread_helloworld_defconfig输入scons --menuconfig进入图形化配置菜单。在菜单中用方向键找到Porting code using the LCKFB module选项按Y键选中它前面会出现[*]。按回车键进入这个子菜单。在里面找到Using SG90 steering engine选项同样按Y键选中它。最后用左右方向键切换到Save按回车保存配置然后退出菜单。2.4 编译与烧录配置保存后就可以编译了。在Env命令行中输入scons如果你的电脑CPU核心多想加快编译速度可以用-j参数比如scons -j16。编译成功后在\luban-lite\output\d13x_JLC_rt-thread_helloworld\images目录下会生成一个d13x_JLC_v1.0.0.img的镜像文件。最后使用烧录工具将这个镜像文件烧录到衡山派开发板中具体烧录方法可以参考官方文档。3. 核心代码解析与原理烧录完成硬件准备就绪现在我们来深入看看驱动代码到底是怎么工作的。理解了代码你才能举一反三。3.1 头文件与宏定义 (bsp_sg90.h)头文件很简单就是声明了三个我们要用到的函数int SG90_Init(void); // 初始化舵机 int SG90_DeInit(void); // 反初始化关闭 int Set_Servo_Angle(uint32_t Angle); // 设置角度范围0-1803.2 初始化函数 (SG90_Init)这是整个驱动的起点在bsp_sg90.c文件中。我把它拆开一步步讲第一步降低PWM时钟频率ret hal_pwm_set_tb(SG90_PWMA_CHANNEL, 1000000);这行代码非常关键衡山派开发板PWM的默认时钟频率是24MHz。在这个频率下计数器计满一个20ms周期所需要的数值会非常大可能超出寄存器能设置的范围导致无法产生我们需要的长周期信号。所以这里先把PWM1通道的时钟频率降低到1MHz这样后续设置周期值就游刃有余了。这是我调试时遇到的第一个坑原文也特别强调了。第二步查找PWM设备pwm_dev (struct rt_device_pwm *)rt_device_find(SG90_PWM_NAME);RT-Thread中外设都抽象为“设备”。这行代码就是根据设备名这里是”pwm”在系统中找到PWM设备拿到它的操作句柄。第三步设置PWM周期和初始脉宽ret rt_pwm_set(pwm_dev, SG90_PWMA_CHANNEL, SG90_PERIOD, 0);pwm_dev: 刚才找到的设备句柄。SG90_PWMA_CHANNEL: 使用的PWM通道号这里是1。SG90_PERIOD: 周期值定义为20000000纳秒ns也就是20毫秒ms。0: 初始脉冲宽度高电平时间设为0意味着舵机初始状态没有脉冲是安全的。第四步使能PWM输出ret rt_pwm_enable(pwm_dev, SG90_PWMA_CHANNEL);最后这步是“打开开关”让PWM信号实际从对应的硬件引脚输出。3.3 角度控制函数 (Set_Servo_Angle)这是最核心的函数实现了角度到脉冲宽度的映射。int Set_Servo_Angle(uint32_t Angle) { float pulse; // 1. 角度范围检查 if (Angle 180) { LOG_E(Angle out of range !!); return -RT_ERROR; } // 2. 角度到脉宽的换算核心算法 pulse 500000.0f ((2000000.0f / 180.0f) * (float)Angle); // 3. 设置新的脉宽 if (RT_EOK ! rt_pwm_set(pwm_dev, SG90_PWMA_CHANNEL, SG90_PERIOD, (uint32_t)pulse)) { LOG_E(rt_pwm_set failed !!); return -RT_ERROR; } return RT_EOK; }重点解释一下换算公式500000.0f: 这是0度角对应的脉冲宽度单位是纳秒ns即0.5ms。2000000.0f / 180.0f: 这是“每度对应的脉冲宽度增量”。总脉冲变化范围是2.5ms - 0.5ms 2.0ms即2,000,000 ns。把它平分成180份得到每度大约11111 ns。(2000000.0f / 180.0f) * (float)Angle: 计算当前角度相对于0度需要增加的脉冲宽度。两者相加就得到了目标角度对应的精确脉冲宽度。例如设置90度时pulse 500000 (11111 * 90) ≈ 1,500,000 ns正好是1.5ms。3.4 测试线程 (test_sg90_steering_engine.c)官方提供了一个测试线程它创建了一个任务让舵机在0到180度之间自动来回摆动非常适合验证驱动是否正常工作。线程入口函数逻辑初始化舵机 (SG90_Init)。依次将舵机转到45度、90度、0度每个状态保持1秒做一个“开机自检”动作。进入主循环让角度变量Angle从0递增到180再递减回0循环往复。每次循环调用Set_Servo_Angle(Angle)设置角度并延时100ms。这个延时决定了舵机运动的速度延时越小运动越快。如何使用这个测试代码最后用MSH_CMD_EXPORT将函数导出为了Finsh/MSH命令行命令。这意味着当程序运行起来并通过串口连接到开发板后你只需要在终端里输入test_sg90_module舵机就会开始自动来回转动。想停止它就输入test_exit_sg90_module4. 硬件连接与最终验证代码烧录进去之后最后一步就是把舵机接上开发板。接线很简单舵机红线电源- 接开发板的5V引脚。舵机棕线地- 接开发板的GND引脚。舵机橙线信号- 接开发板指定的PWM输出引脚具体是哪个引脚需要根据你使用的PWM通道和衡山派的引脚复用表来确定请参考开发板原理图。提示务必确保共地即开发板和舵机的地线GND要连接在一起这是信号正常工作的基础。连接好硬件和串口调试器后给开发板上电。打开串口终端如Putty、MobaXterm等设置波特率为115200。在终端中输入test_sg90_module命令并回车。如果一切顺利你应该能立刻听到舵机转动的声音并看到它开始周期性地在0到180度之间摆动。看到舵机乖乖听你指挥转动起来是不是很有成就感这个过程涵盖了从原理理解、环境配置、代码移植、编译烧录到硬件验证的完整嵌入式开发流程。你可以基于这个驱动去开发更复杂的项目比如多舵机协同的机械臂、云台摄像头等等。遇到问题别怕多看看串口日志理解每个函数返回值的含义调试的过程就是进步最快的时候。