使用pwm控制舵机来回摆动的中心位置

使用pwm控制舵机来回摆动的中心位置,还是基于前两篇的结果,这个让舵机可以在45度的范围摆动,可以使用pwm控制它摆动的中心角度。

 效果:

python写的模拟舵机控制来回摆动的中心点

代码如下:

import tkinter as tk
import math
 
class SwingArm:
    def __init__(self):
        self.current_angle = 0.0  # 当前角度(-45~45)
        self.target_angle = 0.0   # 目标角度
        self.speed = 180.0         #  180.0度/秒
        angle_rad = math.radians(self.current_angle)
        self.x = 200 + 100 * math.cos(angle_rad)
        self.y = 150 - 100 * math.sin(angle_rad)
    def set_target(self, pwm):
        # PWM映射到角度(1000→-45°,2000→45°)
        self.target_angle = (pwm - 1500) * 0.09
        
    def update(self, delta_time):
        # 计算移动方向和距离
        angle_diff = self.target_angle - self.current_angle
        if abs(angle_diff) < 0.1:  # 到达阈值
            return
        
        direction = 1 if angle_diff > 0 else -1
        max_step = self.speed * delta_time
        step = min(abs(angle_diff), max_step) * direction
        
        # 更新当前角度并限制范围
        self.current_angle = max(-45.0, min(45.0, self.current_angle + step))
        
        # 新增摆臂位置计算
        angle_rad = math.radians(self.current_angle)
        self.x = 200 + 100 * math.cos(angle_rad)
        self.y = 150 - 100 * math.sin(angle_rad)

class ServoSimulator:
    def __init__(self, master):
        self.master = master
        master.title("舵机摆动模拟器")
        
        # 界面布局
        self.canvas = tk.Canvas(master, width=400, height=300, bg='white')
        self.canvas.pack(pady=20)
        
        # PWM输入控件
        # 删除原有Entry控件,添加滑动条
        self.pwm_label = tk.Label(master, text="PWM控制 (1000-2000):")
        self.pwm_label.pack()
        
        # 创建水平滑动条
        self.pwm_slider = tk.Scale(master, from_=1000, to=2000, orient=tk.HORIZONTAL,
                                 length=300, command=self.update_angle)
        self.pwm_slider.set(1500)  # 设置默认值
        self.pwm_slider.pack(pady=10)
        
        # 删除原有pwm_entry及其绑定
        self.pwm_entry = tk.Entry(master)
        self.pwm_entry.pack()
        self.pwm_entry.insert(0, "1500")
        
        # 角度显示
        self.angle_label = tk.Label(master, text="当前角度: 0.00°")
        self.angle_label.pack(pady=10)
        
        # 绘制摆臂
        self.arm = self.canvas.create_line(200, 150, 300, 150, width=3, fill='blue')
        
        # 绘制最大最小角度参考线(红色虚线)
        self.min_line = self.canvas.create_line(200, 150, 200, 150, width=1, fill='red', dash=(4,2))
        self.max_line = self.canvas.create_line(200, 150, 200, 150, width=1, fill='red', dash=(4,2))

        # 绑定输入事件
        self.pwm_entry.bind("<KeyRelease>", self.update_angle)
        
        # 新增初始化变量
        self.current_angle = 0.0
        self.direction = 1
        
        self.input_pwm = 0.0
        self.swing_angle = 0.0  # 初始角度

        # 初始化摆臂对象
        self.swing_arm = SwingArm()
        
        # 删除残留的pwm_entry相关代码
        self.pwm_entry.pack_forget()  # 隐藏输入框
        self.pwm_entry.unbind("<KeyRelease>")  # 解除事件绑定
        
        # 启动动画循环
        self.update_animation()
        
    def update_angle(self, pwm_value):
        # 将PWM值传给摆臂对象
        self.swing_arm.set_target(int(pwm_value))
    def do_swing(self, delta_time):
        self.auto_speed = (self.input_pwm-1000)/1000*180.0
        deltaAngle = self.auto_speed * delta_time * self.direction
        new_angle = self.swing_angle + deltaAngle
        
        # 边界检测和方向反转
        if new_angle >= 25 or new_angle <= -25:
            self.direction *= -1
        
        # 更新当前角度并设置目标PWM
        self.swing_angle = new_angle
        target_pwm = 1500 + (self.swing_angle / 0.09)
        self.swing_arm.set_target(int(target_pwm))
    def adjust_swing_center(self, delta_time):
        self.auto_speed = 90
        # 计算中心位置(1000→-25°,2000→25°)
        center = (self.input_pwm - 1500) * 0.05
        
        # 计算摆动边界(中心±22.5度)
        min_angle = center - 22.5
        max_angle = center + 22.5
        
        # 更新角度并检测边界
        new_angle = self.swing_angle + self.auto_speed * delta_time * self.direction
        
        if new_angle > max_angle or new_angle < min_angle:
            self.direction *= -1
            new_angle = max(min(new_angle, max_angle), min_angle)
            
        self.swing_angle = new_angle
        
        # 设置目标PWM
        target_pwm = 1500 + (self.swing_angle / 0.09)
        self.swing_arm.set_target(int(target_pwm))
        

    def adjust_swing_center(self, delta_time):
        self.auto_speed = 90
        # 计算中心位置(1000→-25°,2000→25°)
        center = (self.input_pwm - 1500) * 0.05
        
        # 计算摆动边界(中心±22.5度)
        min_angle = center - 22.5
        max_angle = center + 22.5
        
        # 更新角度并检测边界
        new_angle = self.swing_angle + self.auto_speed * delta_time * self.direction
        
        if new_angle > max_angle or new_angle < min_angle:
            self.direction *= -1
            new_angle = max(min(new_angle, max_angle), min_angle)
            
        self.swing_angle = new_angle
        
        # 设置目标PWM
        target_pwm = 1500 + (self.swing_angle / 0.09)
        self.swing_arm.set_target(int(target_pwm))
        
        # 更新参考线位置
        min_rad = math.radians(min_angle)
        max_rad = math.radians(max_angle)
        self.canvas.coords(self.min_line, 
            200, 150, 
            200 + 100 * math.cos(min_rad), 
            150 - 100 * math.sin(min_rad))
        self.canvas.coords(self.max_line, 
            200, 150, 
            200 + 100 * math.cos(max_rad), 
            150 - 100 * math.sin(max_rad))
    def update_animation(self):
       # self.do_swing(0.02)
        self.adjust_swing_center(0.02)
        self.swing_arm.update(0.02)
        self.angle_label.config(text=f"当前角度: {self.swing_arm.current_angle:+.2f}°")
        self.canvas.coords(self.arm, 200, 150, self.swing_arm.x, self.swing_arm.y)
        self.master.after(50, self.update_animation)
 
 
    def update_angle(self, pwm_value=None):
        try:
            # 从滑动条获取值
            pwm = int(pwm_value) if pwm_value else self.pwm_slider.get()
            print(f"更新pwm: {pwm}")
            #self.swing_arm.set_target(pwm)
            self.input_pwm = pwm

        except Exception as e:
            print(f"更新错误: {e}")
        except ValueError:
            self.angle_label.config(text="输入无效!")
 
if __name__ == "__main__":
    root = tk.Tk()
    app = ServoSimulator(root)
    root.mainloop()

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值