怎么用Python控制树莓派机器人电机

小石头
小石头
发布时间:2026-11-14 | 4人浏览过
原创

详细讲解如何使用Python控制树莓派驱动机器人直流电机,涵盖外部独立供电与共地原理、驱动板引脚接线、PWM脉宽调制调速、Python gpiozero编程及双轮差速底盘封装。

控制树莓派机器人电机的核心路径是:通过外接独立电池为电机驱动板供电,利用树莓派的 GPIO 引脚向驱动板输入方向电平与 PWM 脉宽调制信号,由驱动板内部的 H 桥电路放大电流以驱动直流电机旋转,并借助 Python 的 gpiozero 库完成方向切换与转速调节。本文将从硬件拓扑、电气隔离、驱动逻辑到完整面向对象代码封装,逐步完成机器人的电机驱动搭建。

一、核心原理与硬件驱动选型

树莓派自身的 GPIO 引脚输出电平为 3.3V,单个引脚最大允许电流通常仅在 16mA 以内,而常规机器人所用的微型直流减速电机(如常见的小黄电机或 25GA-370 电机)工作电压普遍在 6V 至 12V 之间,启动瞬间电流峰值可高达 1A 乃至数安培。若直接将电机接到树莓派引脚,会立即烧毁树莓派的微处理器芯片。因此,必须引入专用的电机驱动模块作为“功率中继”,并实行控制电源与动力电源的物理分离。

电气隔离与共地原则

1. 动力电源独立:电机的动力电池组(如 2 节 18650 锂电池串联产生的 7.4V~8.4V)严禁并入树莓派的 5V 供电轨,必须直接接至驱动模块的动力输入端。
2. 逻辑地线必须相连(Common GND):树莓派的任意一个 GND 引脚必须与电机驱动板的 GND 端子稳固相连。两者的参考地必须在同一零电位基准,否则方向电平与 PWM 信号将无法被驱动芯片正确识别。

常见的电机驱动芯片主要有 TB6612FNG 与 L298N:

  • TB6612FNG(推荐):采用低内阻 MOSFET 输出,发热量极低,压降低至 0.2V~0.5V 左右,体积小巧,具备独立的待机引脚(STBY),适合轻量型移动小车与轮式机器人。
  • L298N:采用双极型晶体管设计,发热较大,内部压降高达 1.8V~2.5V(会导致 7.4V 电池实际供给电机的电压仅剩 5V 左右),但耐压高、散热片结实、价格便宜。
怎么用Python控制树莓派机器人电机
图 1:树莓派、电机驱动模块、独立动力电源与直流减速电机的电气连接拓扑图

二、电机控制的物理机制:H 桥与 PWM 调速原理

直流电机两端如果直接施加直流电压,电机将以恒定方向与最大速度旋转;当调换两端电压的极性时,电机将反向旋转。在移动机器人中,不可能用机械开关去手动倒转极性,这便需要 H 桥(H-Bridge) 电路来完成电子开关换向。

1. H 桥换向工作模式

H 桥由 4 个开关管(三极管或场效应管)组成,电机位于中心横梁:

  • 正转(Forward):闭合 S1 与 S4,断开 S2 与 S3。电流从左向右流经电机。
  • 反转(Reverse):闭合 S2 与 S3,断开 S1 与 S4。电流从右向左流经电机。
  • 刹车(Brake / 快速制动):同时闭合 S1 与 S2(或同时闭合 S3 与 S4),将电机两端直接短路,电机产生的反向电动势转化为制动力矩,实现即时停转。
  • 滑行停止(Coast / 自由滑行):四个开关管全部断开,电机两端悬空,小车靠惯性逐渐停止。

2. PWM(脉宽调制)无级调速原理

树莓派 GPIO 只能输出高电平(3.3V)或低电平(0V),无法直接输出任意连续模拟电压。为了控制电机转速,采用 脉宽调制(Pulse Width Modulation, PWM) 技术。通过以极高频率(通常在 100Hz 到 10000Hz 之间)反复切换引脚的高低电平,利用高电平持续时间与整个周期的比值——即 占空比(Duty Cycle),调节电机两端的等效平均电压。

怎么用Python控制树莓派机器人电机
图 2:H 桥电路工作状态与 PWM 脉宽调制电压输出对应关系

三、硬件接线与端口分配

为便于后续编写清晰的代码,我们需要在树莓派与电机驱动板之间建立固定的引脚映射关系。本方案以主流的 树莓派 4B/5 搭配 TB6612FNG 为例进行分配:

树莓派物理引脚编号 BCM 编号 引脚功能 / 信号类型 连接驱动板端子 (TB6612) 电气作用与说明
Pin 11 GPIO 17 普通数字输出 (DO) AIN1 控制左电机正转方向电平
Pin 13 GPIO 27 普通数字输出 (DO) AIN2 控制左电机反转方向电平
Pin 12 GPIO 18 硬件 PWM 引脚 (PWM0) PWMA 输入 0~100% 占空比信号控制左轮转速
Pin 15 GPIO 22 普通数字输出 (DO) BIN1 控制右电机正转方向电平
Pin 16 GPIO 23 普通数字输出 (DO) BIN2 控制右电机反转方向电平
Pin 35 GPIO 19 硬件 PWM 引脚 (PWM1) PWMB 输入 0~100% 占空比信号控制右轮转速
Pin 18 GPIO 24 普通数字输出 (DO) STBY (待机使能) 输出高电平唤醒驱动芯片,低电平进入休眠
Pin 6 / 9 / 14 GND 系统接地 (0V) GND 必须与驱动板逻辑 GND、动力电池负极完全并联共地
针对 L298N 模块的接线说明

若使用的是 L298N 驱动模块,其板载有跳线帽短接 ENA、ENB 到 5V。若要进行 PWM 调速,必须拔掉 ENA 和 ENB 上的物理跳线帽,然后将树莓派的 GPIO 18(PWM0)接至 ENA 端子,将 GPIO 19(PWM1)接至 ENB 端子。IN1~IN4 则分别接 GPIO 17、27、22、23。

四、操作步骤流程:从环境配置到硬件测试

为了保证系统可靠性,不要一开始就直接组装完整底盘并运行复杂代码。推荐按照“环境安装 -> 单引脚验证 -> 单电机调速 -> 双电机差速封装”的阶梯步骤逐步推进。

怎么用Python控制树莓派机器人电机
图 3:树莓派机器人电机控制系统标准化搭建与验证步骤

五、编写 Python 电机驱动程序

早期的树莓派教程多使用 RPi.GPIO 库,但该库 API 偏向底层寄存器,需要手动配置 PWM 频率、占空比计算以及复杂的电平反转代码。现代树莓派操作系统(Raspberry Pi OS Bookworm 及更新版本)推荐使用面向对象的 gpiozero 库,它内置了专用的 Motor 和 Robot 类,具有逻辑清晰、自动清理引脚状态、支持高精度 PWM 的优势。

1. 系统环境与驱动库安装

在树莓派终端中执行以下命令,确保依赖库安装就绪:

# 更新软件源
sudo apt-get update

# 安装 Python 3 的 gpiozero 库
sudo apt-get install -y python3-gpiozero python3-pigpio

# 启动 pigpio 高精度守护进程(可选,用于消除软件PWM颤抖)
sudo systemctl enable pigpiod
sudo systemctl start pigpiod

2. 阶段一:单电机基础控制与调速验证

在组装两轮小车前,先编写一个控制单一电机的脚本。通过 Motor(forward=17, backward=27, enable=18),可以直接以 0.0 至 1.0 的浮点数指定速度:

# 文件名:test_single_motor.py
# 运行环境:树莓派本地 Python 3
import time
from gpiozero import Motor, OutputDevice

# 如果使用 TB6612,需要将待机使能引脚 STBY(GPIO 24)拉高以激活芯片
stby = OutputDevice(24, active_high=True, initial_value=True)

# 实例化电机对象:定义正转引脚、反转引脚及 PWM 调速使能引脚
# pwm=True 允许进行 0.0 ~ 1.0 的占空比无级调速
motor_left = Motor(forward=17, backward=27, enable=18, pwm=True)

try:
    print("【测试开始】电机正转,速度 50%...")
    motor_left.forward(speed=0.5)
    time.sleep(2)

    print("【测试加速】电机正转,全速 100%...")
    motor_left.forward(speed=1.0)
    time.sleep(2)

    print("【测试换向】电机反转,速度 60%...")
    motor_left.backward(speed=0.6)
    time.sleep(2)

    print("【测试停转】电机制动停止...")
    motor_left.stop()
    time.sleep(1)

finally:
    # 退出时释放 GPIO 资源,关闭芯片使能
    motor_left.stop()
    stby.off()
    print("GPIO 资源已安全释放。")

3. 阶段二:双轮机器人底盘(面向对象封装)

机器人的移动通常依赖双轮差速转向(Differential Drive): 两轮同向同速转动实现前进或后退;两轮反向旋转实现原地自转;两轮同向但存在转速差时实现弧线拐弯。我们可以将两组电机整合封装为一个 RobotCar 控制类:

# 文件名:robot_chassis.py
# 运行环境:树莓派本地 Python 3
import time
from gpiozero import Motor, OutputDevice

class RobotCar:
    """双轮差速移动机器人底盘控制类"""
    def __init__(self, left_pins, right_pins, stby_pin=None):
        # 激活待机使能引脚(若为 TB6612)
        self.stby = OutputDevice(stby_pin, active_high=True, initial_value=True) if stby_pin else None
        
        # 初始化左右轮电机 (forward, backward, enable)
        self.left_motor = Motor(
            forward=left_pins[0], 
            backward=left_pins[1], 
            enable=left_pins[2], 
            pwm=True
        )
        self.right_motor = Motor(
            forward=right_pins[0], 
            backward=right_pins[1], 
            enable=right_pins[2], 
            pwm=True
        )

    def forward(self, speed=0.8):
        """双轮同步前进"""
        self.left_motor.forward(speed)
        self.right_motor.forward(speed)

    def backward(self, speed=0.8):
        """双轮同步后退"""
        self.left_motor.backward(speed)
        self.right_motor.backward(speed)

    def rotate_left(self, speed=0.6):
        """原地逆时针旋转:左轮后退,右轮前进"""
        self.left_motor.backward(speed)
        self.right_motor.forward(speed)

    def rotate_right(self, speed=0.6):
        """原地顺时针旋转:左轮前进,右轮后退"""
        self.left_motor.forward(speed)
        self.right_motor.backward(speed)

    def curve_turn(self, left_speed, right_speed):
        """差速平滑转向:自定义左右轮不同转速"""
        self.left_motor.forward(max(0.0, min(1.0, left_speed)))
        self.right_motor.forward(max(0.0, min(1.0, right_speed)))

    def stop(self):
        """刹车停止"""
        self.left_motor.stop()
        self.right_motor.stop()

    def cleanup(self):
        """完全关闭与引脚资源清理"""
        self.stop()
        if self.stby:
            self.stby.off()

# 示例场景执行
if __name__ == "__main__":
    # 引脚配置定义: [Forward, Backward, PWM_Enable]
    LEFT_WHEEL_PINS = [17, 27, 18]
    RIGHT_WHEEL_PINS = [22, 23, 19]
    STBY_PIN = 24

    car = RobotCar(LEFT_WHEEL_PINS, RIGHT_WHEEL_PINS, STBY_PIN)

    try:
        print("小车启动:平稳前进 2 秒...")
        car.forward(speed=0.7)
        time.sleep(2)

        print("小车大半径左转(差速)1.5 秒...")
        car.curve_turn(left_speed=0.3, right_speed=0.8)
        time.sleep(1.5)

        print("小车原地右转 1 秒...")
        car.rotate_right(speed=0.6)
        time.sleep(1)

        print("小车后退 1.5 秒...")
        car.backward(speed=0.5)
        time.sleep(1.5)

    except KeyboardInterrupt:
        print("检测到用户中断命令。")
    finally:
        car.cleanup()
        print("小车已安全驻停并释放引脚。")

六、常见问题诊断与避坑决策树

在实际调试电机时,初学者经常遭遇“小车一开动树莓派就重启”、“电机嗡嗡响就是不转”、“前后左右方向错乱”等典型硬件与软件问题。遇到故障时,可参照以下诊断决策树有序排查:

怎么用Python控制树莓派机器人电机
图 4:树莓派电机驱动故障排障决策与核心规则图谱

七、总结

使用 Python 控制树莓派机器人电机并不复杂,但成功的关键在于严谨的电气规范与清晰的软件分层:

  1. 电气架构是基础:树莓派自身引脚绝不可直连动力负载,必须通过 TB6612 或 L298N 驱动芯片进行电流放大;动力电池与树莓派主控电源物理隔离,但两者的地线(GND)必须紧密相连建立统一基准。
  2. 物理机制是核心:方向切换依靠 H 桥对向开关管的组合通断,速度控制依靠微秒级占空比高低切换的 PWM 脉宽调制信号。
  3. 现代库是保障:选用官方推荐的 gpiozero 库替代冗长的底层 GPIO 操作,通过将左轮与右轮抽象为对象,封装出直观的 RobotCar 类,为未来加入传感器避障、视觉循线或自主导航打下坚实的运动控制底座。
相关专题:

本站声明

本文内容仅供参考,不代表本站观点。转载或引用请注明出处。如发现内容问题,请通过联系我们页面反馈。

Python 相关产品和应用

全部下载

专题列表