麦克纳姆轮小车 esp32

麦克纳姆轮小车

  1. 车身搭建,简单的电机控制。
  2. 测速
  3. pid控制

开一个坑,借助ChatGPT完成一个小玩具。
不是0基础,还是要有一定单片机电子模块基础的。

1.硬件要求

目前手里有:

1个车架,
4个直流减速电机(淘宝上常见的tt电机),
4个对射光电传感器,
L9110S四路电机驱动板(不太好用,我替换成了一对l298n),
2对麦克纳姆轮(大家买轮子要注意,别买错方向了,亲身踩的坑),
1块esp32+拓展版,
4节18650。

2.避坑经验:

组装小车
1.电机方向一致,供电的两个铜极朝向同一边,能给你后续调试代码节省很多时间。
2.组装小车的时候,轮子的方向别错了,不懂怎么装就按x形(从上往下看)。
3.我的车底盘是金属的,如果你的也是,切记要把模块背面贴上绝缘胶布(或者干脆架起来)。否则模块一上电碰火,啥都烧了。
4.l298n的5V接口可以当做电源给单片机供电的。前提是!!!L298n的外接电源是12v以下的。过了12那个脚测出来就不止5V,容易给esp32干废了。

已经21:37了,今天试着做一下电机控制。

3.chatGPT解答,问题1

给GPT第一个问题:
写一个esp32 micropython pwm 控制直流电机程序
GPT回复了我2段源码

代码说明
引脚初始化:

in1in2 用于控制电机的旋转方向。
enable 是一个 PWM 对象,用于控制电机的速度。
PWM 设置:

使用 enable.freq(1000) 设置 PWM 的频率为 1kHz。这个频率是大多数电机的常用选择,可以根据需要进行调整。
电机控制函数:

motor_forward(speed):使电机按指定速度向前旋转。
motor_backward(speed):使电机按指定速度向后旋转。
motor_stop():停止电机。

速度测试函数:

motor_speed_test() 函数通过一系列速度变化测试电机在不同速度下的运行情况。
错误处理:

使用 try-except 块捕获键盘中断,确保在程序结束时电机被正确停止。

from machine import Pin, PWM
from time import sleep

# 初始化电机引脚
in1 = Pin(15, Pin.OUT)  # IN1 引脚
in2 = Pin(2, Pin.OUT)   # IN2 引脚
enable = PWM(Pin(4))    # ENA 引脚,用于 PWM 控制速度
enable.freq(1000)       # 设置 PWM 频率为 1kHz

def motor_forward(speed):
    """使电机向前运行"""
    in1.value(1)  # IN1 设置为高电平
    in2.value(0)  # IN2 设置为低电平
    # 将速度转换为 0-1023 范围内的 PWM 占空比
    duty_cycle = int(speed * 1023 / 100)
    enable.duty(duty_cycle)
    print(f"Motor forward at {speed}% speed")

def motor_backward(speed):
    """使电机向后运行"""
    in1.value(0)  # IN1 设置为低电平
    in2.value(1)  # IN2 设置为高电平
    duty_cycle = int(speed * 1023 / 100)
    enable.duty(duty_cycle)
    print(f"Motor backward at {speed}% speed")

def motor_stop():
    """停止电机"""
    in1.value(0)
    in2.value(0)
    enable.duty(0)
    print("Motor stopped")

def motor_speed_test():
    """测试电机在不同速度下的运行"""
    try:
        # 前进并逐渐增加速度
        for speed in range(0, 101, 20):  # 从0%到100%,步长为20%
            motor_forward(speed)
            sleep(2)
        
        motor_stop()  # 停止电机
        sleep(2)

        # 后退并逐渐增加速度
        for speed in range(0, 101, 20):
            motor_backward(speed)
            sleep(2)

        motor_stop()  # 停止电机
        
    except KeyboardInterrupt:
        motor_stop()
        print("Program interrupted and motor stopped")

# 主程序
if __name__ == "__main__":
    print("Starting motor control test")
    motor_speed_test()

GPT的代码规范是真规范,表扬一波。

4.最终电机控制测试代码

这里和我的需求有些差异,我手里的模块没有enable(使能口)
稍稍调整一下端口和函数:
上传后的效果是小车前进1秒停1秒。

from machine import Pin, PWM
from time import sleep

# 初始化电机引脚,别再问怎么接线啦!!!
in1 = PWM(Pin(13))  # IN1 引脚用于 PWM 控制速度
in2 = PWM(Pin(12))  # IN2 引脚用于 PWM 控制速度
in3 = PWM(Pin(16))  
in4 = PWM(Pin(27))  
in5 = PWM(Pin(26))  
in6 = PWM(Pin(25))  
in7 = PWM(Pin(33))  
in8 = PWM(Pin(32))  

inNlist = [in1,in2,in3,in4,in5,in6,in7,in8]
for i in inNlist:
    i.freq(1000)       # 设置 PWM 频率为 1kHz
    i.duty(0)  # IN1 设置占空比为0,初始速度设为0

#	我太懒了,不想写引脚,干脆封装成轮子,后面直接操作轮子对象
class Wheel:
    def __init__(self,ina,inb):
        self.ina = ina
        self.inb = inb
        
# 后左轮 后右 前左 前右	分别为wa,wb,wc,wd
wa = Wheel(in1,in2)
wb = Wheel(in3,in4)
wc = Wheel(in5,in6)
wd = Wheel(in7,in8)

def motor_forward(wheel,speed):
    """使电机运行,范围[-100,100]"""
    duty_cycle = int(abs(speed) * 1023 / 100)	# 将速度转换为 0-1023 范围内的 PWM 占空比
    if(speed>0):
        wheel.ina.duty(duty_cycle)  # 所需速度
        wheel.inb.duty(0)  # 占空比0
    elif(speed<0):
        wheel.inb.duty(duty_cycle)  #	速度反向
        wheel.ina.duty(0)  
    else:
        wheel.ina.duty(0)  # 没输入速度就停止,避免有奇奇怪怪bug
        wheel.inb.duty(0)  
    print(f"Motor forward at {speed}% speed")

# 主程序
if __name__ == "__main__":
    print("Starting motor control test")
    while(1):
        motor_forward(wa,30)
        motor_forward(wb,30)
        motor_forward(wc,30)
        motor_forward(wd,30)
        sleep(1)
        motor_forward(wa,0)
        motor_forward(wb,0)
        motor_forward(wc,0)
        motor_forward(wd,0)
        sleep(1)


GPT代码分析
大家遇到看不懂的代码,也可以扔给GPT,比如我把我改过的代码扔回去了
她甚至给我意见怎么改,泪目
在这里插入图片描述

下面是gpt回复内容:


这段代码是用来控制四个电机的简单程序,可能用于一个四轮小车或机器人。代码使用了 PWM(脉宽调制)来控制每个电机的速度和方向。

5.ChatGPT代码分析

1. 引入库和初始化电机引脚
from machine import Pin, PWM
from time import sleep

# 初始化电机引脚
in1 = PWM(Pin(13))  # IN1 引脚用于 PWM 控制速度
in2 = PWM(Pin(12))  # IN2 引脚用于 PWM 控制速度
in3 = PWM(Pin(16))  
in4 = PWM(Pin(27))  
in5 = PWM(Pin(26))  
in6 = PWM(Pin(25))  
in7 = PWM(Pin(33))  
in8 = PWM(Pin(32))  

inNlist = [in1,in2,in3,in4,in5,in6,in7,in8]
for i in inNlist:
    i.freq(1000)       # 设置 PWM 频率为 1kHz    
    i.duty(0)  # IN1 设置占空比为0
  • 这里导入了两个模块:machine 用于控制引脚,time 用于处理延时。
  • 使用 PinPWM 初始化了八个引脚(in1in8),用于控制四个电机(每个电机需要两个引脚)。
  • 频率被设置为 1kHz,这个频率适合多数电机的 PWM 控制。
  • duty 方法被设置为 0,这表示电机初始状态是停止的,因为占空比为 0 时,电机没有接收到电压。
2. 封装成 Wheel 类
# 我太懒了,不想写引脚,干脆封装成轮子,后面直接操作轮子对象
class Wheel:
    def __init__(self,ina,inb):
        self.ina = ina
        self.inb = inb
        
# 后左轮 后右 前左 前右 分别为 wa, wb, wc, wd
wa = Wheel(in1,in2)
wb = Wheel(in3,in4)
wc = Wheel(in5,in6)
wd = Wheel(in7,in8)
  • 创建了一个 Wheel 类,用于封装每个轮子所需的两个引脚。
  • 初始化四个 Wheel 对象 wa, wb, wc, 和 wd,分别代表后左轮、后右轮、前左轮和前右轮。
  • 封装类的做法使得后续代码更简洁,易于管理和修改。
3. 电机控制函数
def motor_forward(wheel, speed):
    """使电机运行,范围[-100,100]"""
    duty_cycle = int(abs(speed) * 1023 / 100)  # 将速度转换为 0-1023 范围内的 PWM 占空比
    if(speed>0):
        wheel.ina.duty(duty_cycle)  # 所需速度
        wheel.inb.duty(0)  # 占空比0
    elif(speed<0):
        wheel.inb.duty(duty_cycle)  # 速度反向
        wheel.ina.duty(0)  
    else:
        wheel.ina.duty(0)  # 没输入速度就停止,避免有奇奇怪怪bug
        wheel.inb.duty(0)  
    print(f"Motor forward at {speed}% speed")
  • 函数 motor_forward 用于控制电机的运动方向和速度。
  • 参数
    • wheel: Wheel 类的一个实例。
    • speed: 控制速度的整数,范围为 -100 到 100。
  • 逻辑
    • 速度转换为 PWM 的占空比(duty_cycle)。这里假设最大占空比为 1023(常用于 10 位 PWM)。
    • speed 大于 0 时,表示正转,ina 设置为 duty_cycleinb 设置为 0。
    • speed 小于 0 时,表示反转,inb 设置为 duty_cycleina 设置为 0。
    • speed 等于 0 时,停止电机。
  • 注意事项
    • duty_cycle 计算部分使用了 abs 函数,因此 speed 的符号用于确定电机方向,而不影响 duty_cycle 的计算。
4. 主程序
if __name__ == "__main__":
    print("Starting motor control test")
    while(1):
        motor_forward(wa, 30)
        motor_forward(wb, 30)
        motor_forward(wc, 30)
        motor_forward(wd, 30)
        sleep(1)
        motor_forward(wa, 0)
        motor_forward(wb, 0)
        motor_forward(wc, 0)
        motor_forward(wd, 0)
        sleep(1)
  • 主程序中包含了一个无限循环,用于测试电机的前进和停止。
  • 电机被设置为 30% 的速度运行 1 秒,然后停止 1 秒。
  • sleep 函数用于实现简单的时间控制。
  • 代码中的 while(1) 是一个无限循环,可以根据需要修改成其他逻辑,如使用条件退出循环或者中断信号。

可能的改进

  1. 引入更多控制功能

    • 可以添加反转、转弯等更多控制功能。通过增加新的函数来实现不同的运动模式,比如:
      def motor_reverse(wheel, speed):
          """反转电机"""
          motor_forward(wheel, -speed)
      
  2. PWM频率和占空比的调整

    • 可以根据具体电机和应用调整 PWM 频率和占空比,以便实现更好的控制效果。
    • 对于不同类型的电机,可能需要使用不同的 PWM 频率来优化性能和减少噪音。
  3. 异常处理

    • 增加异常处理来捕获可能的错误,比如引脚初始化错误、参数值超出范围等。
    • 使用 try...except 结构来处理硬件异常:
      try:
          in1 = PWM(Pin(13))
          # 初始化其他引脚
      except Exception as e:
          print("Error initializing PWM:", e)
      
  4. 增加对PWM值的范围检查

    • 确保 speed 参数在合适范围内,例如限制在 [-100, 100],以防止误操作。
    • motor_forward 中可以增加范围检查:
      if speed < -100 or speed > 100:
          raise ValueError("Speed must be between -100 and 100")
      
  5. 改进结构设计

    • 可以考虑用继承和多态来设计更加模块化和可扩展的结构,例如将电机的前进和停止封装成方法。
    • 通过继承基础 Wheel 类,创建特定行为的类:
      class Car:
          def __init__(self, wheels):
              self.wheels = wheels
          
          def move_forward(self, speed):
              for wheel in self.wheels:
                  motor_forward(wheel, speed)
          
          def stop(self):
              for wheel in self.wheels:
                  motor_forward(wheel, 0)
      
      car = Car([wa, wb, wc, wd])
      

总结

这段代码是一个简单的电机控制例程,适合初学者学习如何使用 PWM 控制电机。通过以上的分析和建议,你可以更好地理解代码,并进行改进以满足更复杂的需求。请根据具体应用场景进行调整和扩展,以便获得最佳性能和稳定性。如果有任何其他问题或需要进一步的帮助,请随时告诉我!


  • 1
    点赞
  • 4
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值