python-鲁班猫1进行PWM控制MG996R舵机源码(比例输出)

舵机的控制原理各位可以看这篇文章——舵机控制原理

python3有相应的PWM控制库,如 python3-libgpiodpython-periphery 。但由于不同舵机实际的0°~180°对应的脉宽为不一定是0.5ms~2.5ms,也可能为0.4ms~2.4ms这样的微小误差,这会导致你标准库控制舵机的角度就不精确。

所以本次采用的是python3的文件IO来配置Linux板子的PWM设备,其控制进准度代码如下:

import time

# 导出 PWM 控制器
def pwm_export(pwmid):
    with open('/sys/class/pwm/pwmchip%d/export' % pwmid, 'wb') as f:
        f.write("0".encode())

# 取消导出 PWM 控制器
def pwm_unexport(pwmid):
    with open('/sys/class/pwm/pwmchip%d/unexport' % pwmid, 'wb') as f:
        f.write("0".encode())

# 配置 PWM 周期和占空比
def pwm_config(pwmid, pwmPeriod, pwmDutyCycle):
    with open('/sys/class/pwm/pwmchip%d/pwm0/period' % pwmid, 'wb') as f:
        f.write(str(pwmPeriod).encode())
    with open('/sys/class/pwm/pwmchip%d/pwm0/duty_cycle' % pwmid, 'wb') as f:
        f.write(str(pwmDutyCycle).encode())

# 使能 PWM 控制器
def pwm_enable(pwmid):
    with open('/sys/class/pwm/pwmchip%d/pwm0/enable' % pwmid, 'wb') as f:
        f.write("1".encode())

# 禁用 PWM 控制器
def pwm_disable(pwmid):
    with open('/sys/class/pwm/pwmchip%d/pwm0/enable' % pwmid, 'wb') as f:
        f.write("0".encode())

# 设置 PWM 极性
def pwm_polarity(pwmid, pwmPolarity):
    with open('/sys/class/pwm/pwmchip%d/pwm0/polarity' % pwmid, 'wb') as f:
        f.write(pwmPolarity.encode())

# 初始化 PWM 控制器
def pwm_structure(pwmid, pwmPeriod, pwmDutyCycle, pwmPolarity):
    pwm_export(pwmid)
    pwm_config(pwmid, pwmPeriod, pwmDutyCycle)
    pwm_polarity(pwmid, pwmPolarity)
    pwm_enable(pwmid)

# 销毁 PWM 控制器
def pwm_destruction(pwmid):
    pwm_disable(pwmid)
    pwm_unexport(pwmid)

# 角度转换为 PWM 占空比
def set_servo_angle(angle):
    min_pulse = 500  # 最小脉冲宽度
    max_pulse = 2500  # 最大脉冲宽度
    # 限制角度在0到180度之间
    angle = max(0, min(180, angle))
    # 计算占空比
    pwmDutyCycle = 1000 * int((angle / 180.0) * (max_pulse - min_pulse) + min_pulse)
    # 配置 PWM
    pwm_config(1, 20000000, pwmDutyCycle)

# 比例控制函数
def P_control(initial_value, target_value, change_rate):
    while abs(initial_value - target_value) > 0.5:  # 当最后一个返回的值接近设定值时退出循环
        error = target_value - initial_value
        change = error * change_rate
        initial_value += change
        set_servo_angle(initial_value)

# 主函数
if __name__ == '__main__':
    pwm_index = 1
    pwm_structure(pwm_index, 20000000, 0, "normal")  # 初始化 PWM 控制器,设置周期和占空比
    try:
        while True:
            # 使用比例控制器进行控制
            P_control(5, 180, 0.001)  # 从角度5逐渐增加到180
            P_control(180, 5, 0.001)  # 从角度180逐渐减少到5
    finally:
        pwm_destruction(1)  # 销毁 PWM 控制器

以上的注释应该也很详细了。比例控制就根据给的比例系数change、目标角度target_value与实际角度initial_value的差值,去计算每次控制舵机变化的角度值,让舵机先快后慢去稳定达到目标角度,实现舵机的丝滑控制!其中pwmid要根据自己要用的pwm编号去设置。


于是这个py文件可以作为控制舵机的一个库来使用,可根据不同舵机先调试一下脉宽范围,修改一下里面的脉宽参数,就能达到精准控制的效果了。


简单吧?(呆萌蛇)

  • 10
    点赞
  • 4
    收藏
    觉得还不错? 一键收藏
  • 2
    评论
可以使用STM32F103C8T6的TIM1模块来控制PA10引脚的PWM信号,从而实现对MG996R舵机控制。下面是一个简单的示例代码: ``` #include "stm32f10x.h" void TIM1_PWM_Init(void) { GPIO_InitTypeDef GPIO_InitStructure; TIM_TimeBaseInitTypeDef TIM_TimeBaseStructure; TIM_OCInitTypeDef TIM_OCInitStructure; RCC_APB2PeriphClockCmd(RCC_APB2Periph_TIM1 | RCC_APB2Periph_GPIOA, ENABLE); // 配置PA10引脚为复用推挽输出 GPIO_InitStructure.GPIO_Pin = GPIO_Pin_10; GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF_PP; GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz; GPIO_Init(GPIOA, &GPIO_InitStructure); // 设置TIM1为PWM模式 TIM_TimeBaseStructure.TIM_Period = 20000 - 1; // 定时器周期为20ms,即50Hz TIM_TimeBaseStructure.TIM_Prescaler = 72 - 1; // 定时器分频系数为72,即计数频率为1MHz TIM_TimeBaseStructure.TIM_ClockDivision = TIM_CKD_DIV1; TIM_TimeBaseStructure.TIM_CounterMode = TIM_CounterMode_Up; TIM_TimeBaseInit(TIM1, &TIM_TimeBaseStructure); // 配置TIM1_CH3通道为PWM输出模式 TIM_OCInitStructure.TIM_OCMode = TIM_OCMode_PWM1; TIM_OCInitStructure.TIM_OutputState = TIM_OutputState_Enable; TIM_OCInitStructure.TIM_Pulse = 1500; // 初始占空比为50% TIM_OCInitStructure.TIM_OCPolarity = TIM_OCPolarity_High; TIM_OC3Init(TIM1, &TIM_OCInitStructure); TIM_Cmd(TIM1, ENABLE); } void setServoPosition(int position) { // 将0-180度的角度值转换为500-2500us的脉冲宽度 int pulse_width = position * 10 + 500; TIM_SetCompare3(TIM1, pulse_width); } int main(void) { TIM1_PWM_Init(); while (1) { // 控制舵机旋转到0度 setServoPosition(0); Delay(1000); // 控制舵机旋转到90度 setServoPosition(90); Delay(1000); // 控制舵机旋转到180度 setServoPosition(180); Delay(1000); } } ``` 上述代码中,TIM1_PWM_Init()函数用于初始化PA10引脚和TIM1定时器,setServoPosition()函数用于设置舵机的位置。主函数中演示了如何将舵机从0度旋转到180度。你可以根据需要修改setServoPosition()函数来控制舵机旋转到特定的位置。 相关问题: 1. 如何使用STM32定时器控制PWM信号? 2. 如何将角度值转换为舵机控制信号的脉冲宽度? 3. MG996R舵机的工作原理是什么?

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值