基于韦东山STM32MP157开发板实现智能家居项目(PWM驱动-SG90舵机)
本文介绍了SG90舵机的驱动开发过程,包括其工作原理、参数特性以及与STM32的接口连接方式。舵机通过PWM信号控制,脉冲宽度在0.5ms-2.5ms间变化,对应0°-180°角度变化。文章详细记录了设备树信息修改过程,但在实际测试中发现开发板PD8引脚无法复用为定时器通道,导致硬件PWM方案失败。最终改用软件模拟PWM方案,利用GPIO和内核定时器实现舵机控制,虽然精度可能受系统负载影响,但能满
今日进行SG90舵机驱动开发,功能:实现舵机精准旋转角度
1.SG90原理
SG90舵机在大家入门STM32时应该都接触过,也叫伺服电机,在嵌入式开发中,舵机作为一种常见的运动控制组件,具有广泛的应用。其中,SG90 舵机以其高效、稳定的性能特点,成为了许多工程师和爱好者的首选,无论是航模、云台、机器人、智能小车中都有它的身影。
工作参数如下:
-
工作扭矩:1.6kg/cm
-
反应速度:0.12 - 0.13秒/60°
-
死区设定:5us
-
转动角度:常见0°、90°、180°、360°
-
齿轮材质:尼龙塑料齿
-
工作电压:3V - 6V
-
温度范围:-30° ~ +60°
引脚接线参考如下:
| SG90 | STM32 |
|---|---|
| PWM 信号线(橙色线) | 任意GPIO |
| VCC(红线) | 3.3/5V |
| GND(棕色线) | GND |
舵机的控制信号是通过脉冲宽度调制(PWM)来实现的。PWM 信号的周期通常为20ms,而脉冲宽度则在 0.5ms 至 2.5ms 之间变化。这个脉冲宽度与舵盘的位置呈线性关系,范围从0度到180度。
当给舵机提供特定宽度的脉冲信号时,输出轴会保持在相应的角度上,不受外界转矩的影响,直到接收到不同宽度的脉冲信号才会改变输出角度,使舵盘移动到新的位置。舵机内部有一个基准电路,产生周期为 20ms、宽度为 1.5ms 的基准信号。同时,还有一个比较器,用于将外部输入信号与基准信号进行比较,以确定转动方向和幅度,并生成驱动电机转动的信号。
控制电路板接收来自信号线的 PWM 控制信号,然后控制电机的转动。电机带动一系列齿轮组,在经过减速传动后,将力量传递到输出舵盘上。舵机的输出轴与位置反馈电位计相连,当舵盘旋转时,位置反馈电位计也会随之变化,向控制电路板输出电压信号进行反馈。控制电路板根据位置反馈信号判断当前位置,并决定电机的转动方向和速度,以实现目标停止。
为了控制舵机,需要使用单片机来生成周期为 20ms 的脉冲信号,并通过控制脉冲的高电平时间在 0.5ms 至 2.5ms 之间来控制舵机的角度。这样,我们可以通过调整 PWM 信号的脉冲宽度来精确控制舵机的位置和运动。
以 SG90,180度版为例,那么对应的控制关系是这样的:
| 0.5ms | 0° | 2.5% |
|---|---|---|
| 1.0ms | 45° | 5.0% |
| 1.5ms | 90° | 7.5% |
| 2.0ms | 135° | 10.0% |
| 脉冲高电平 | 角度 | 占空比 |
| 2.5ms | 180° | 12.5% |
2.编写设备树信息
查看韦东山STM32MP157开发板的外接模块,我选择了PD8引脚(后续发现这个引脚不可用)
修改pwm 的pinctrl设备树信息:
vi stm32mp157-100ask-pinctrl.dtsi
![]()
找到pwm1_pins_a,在其pinmux中增加定时器1通道3,指定PD8引脚

然后找到定时器的设备树文件stm32mp15xx-100ask.dtsi,修改定时器1
vi arch/arm/boot/dts/stm32mp15xx-100ask.dtsi

将状态设置为okay,并在pwm前添加pwm1
最后编写SG90设备节点,找到设备树stm32mp157c-100ask-512d-lcd-v1.dts,修改设备树将指定好的pwm映射到sg90所连接的GPIO引脚(即pinctrl子系统,我这里映射到了PD8上)(周期20ms应该是20000000,我搞错了。)
vi arch/arm/boot/dts/stm32mp157c-100ask-512d-lcd-v1.dts

编译内核,上传开发板,编写驱动程序、测试程序
3.上机测试
加载驱动后提示报错,从错误信息来看,问题出现在设备树匹配上,具体错误是:
[ 553.986279] stm32mp157-pinctrl soc:pin-controller@50002000: invalid function.
[ 553.995751] my_sg90: probe of pwm_sg90 failed with error -22
错误代码-22表示EINVAL(无效参数)。这通常是因为设备树节点配置不正确,或者平台设备无法正确匹配和初始化。

需要确认PD8的正确复用功能。根据STM32MP157的数据手册

通过数据手册可知,PD8不可用复用为定时器引脚,并且我查阅开发板外设模块其它引脚信息,发现都不可以复用为定时器引脚。
查询了一些资料,可用的GPIO引脚都不能复用为定时器通道,那么无法使用硬件PWM。但是我们可以通过软件方式模拟PWM信号来控制SG90舵机。
SG90舵机要求的是50Hz的PWM信号(周期20ms),脉宽在0.5ms到2.5ms之间。我们可以使用一个GPIO引脚,通过软件控制高低电平的时间来模拟PWM。
注意:软件模拟PWM会占用CPU资源,但SG90舵机只需要50Hz,这个频率不高,在Linux系统中可以通过内核定时器来实现。
方案:使用GPIO模拟PWM
我们将使用一个GPIO引脚,然后通过内核定时器来精确控制高低电平的持续时间。具体步骤:
-
请求GPIO引脚,并设置为输出。
-
使用高精度定时器(hrtimer)来精确控制时间。
-
在定时器中断处理函数中切换GPIO电平,并计算下一个中断的时间。
但是,由于Linux内核是抢占式的,软件模拟的PWM精度可能会受到系统负载的影响。但对于舵机控制,50Hz的频率和毫秒级的精度要求,通常是可以接受的。
好像也可以使用步进电机来代替舵机,等过几天我再尝试一下,目前lab事情比较多,每天就上午可以捣鼓一下这个。
更多推荐


所有评论(0)