Skip to main content

两轮差速模型控制系统

1. 使用开源库驱动多路电机

电路板引脚输出电流电压信号小,需要电机驱动芯片来放大电信号,驱动电路

PWM频率:1秒钟内信号从高电平到低电平再回到高电平的次数

通电设置不同的占空比,比方说,占空比为50% 那就是高电平时间一半,低电平时间一半,在一定的频率下,就可以得到模拟的2.5V输出电压 那么75%的占空比 得到的电压就是3.75V

D/A转换,控制不同的输出电压,控制电机转速

  1. 引入开源库

    代理:http://github.fishros.org/

    lib_deps = https://github.com/fishros/Esp32McpwmMotor.git
  2. 修改代码

    在example中查看如何使用

    #include <Arduino.h>
    #include <Esp32McpwmMotor.h>

    Esp32McpwmMotor motor; // 创建一个名为motor的对象,用于控制电机

    void setup()
    {
    Serial.begin(115200); // 初始化串口通信,波特率为115200

    motor.attachMotor(0, 22, 23); // 将电机0连接到引脚22和引脚23
    motor.attachMotor(1, 12, 13); // 将电机1连接到引脚12和引脚13
    }

    void loop()
    {
    motor.updateMotorSpeed(0, -70); // 设置电机0的速度为负70
    motor.updateMotorSpeed(1, 70); // 设置电机1的速度为正70
    delay(2000); // 延迟两秒

    motor.updateMotorSpeed(0, 70); // 设置电机0的速度为正70
    motor.updateMotorSpeed(1, -70); // 设置电机1的速度为负70
    delay(2000); // 延迟两秒
    }

2. 电机速度测量与转换

速度编码器(两个霍尔元件)

原理:根据磁性的有无,产生高低电平的变化(一次从低到高,再由高到低的过程叫做脉冲)

由于减速器的存在,电动机实际的转动圈数更多,获得的扭力更大

单片机可以测量产生的脉冲,轮子转动一圈转换成产生脉冲的次数,从而可以获得轮子的行走距离,从而计算出轮子转速

  1. 引入开源库

    代理:http://github.fishros.org/

    lib_deps = https://github.com/fishros/Esp32PcntEncoder.git
  2. 修改代码

    在example中查看如何使用

    #include <Arduino.h>
    #include <Esp32PcntEncoder.h>

    Esp32PcntEncoder encoders[2]; // 创建一个数组用于存储两个编码器

    void setup()
    {
    // 1.初始化串口
    Serial.begin(115200); // 初始化串口通信,设置通信速率为115200

    // 2.设置编码器
    encoders[0].init(0, 32, 33); // 初始化第一个编码器,使用GPIO 32和33连接
    encoders[1].init(1, 26, 25); // 初始化第二个编码器,使用GPIO 26和25连接
    }

    void loop()
    {
    delay(10); // 等待10毫秒

    // 读取并打印两个编码器的计数器数值
    Serial.printf("tick1=%d,tick2=%d\n", encoders[0].getTicks(), encoders[1].getTicks());
    }
  3. 记录转10圈所产生的脉冲数,再除以10,就是1圈产生的脉冲数

    fishbot一圈1930个脉冲,l轮子直径65mm,转一圈距离为65*Pi

    一个脉冲距离为65*Pi/1930 = 0.105805mm

    计算代码:

    #include <Arduino.h>
    #include <Esp32McpwmMotor.h>
    #include <Esp32PcntEncoder.h>

    Esp32PcntEncoder encoders[2]; // 创建一个数组用于存储两个编码器

    Esp32McpwmMotor motor; // 创建一个名为motor的对象,用于控制电机

    int64_t last_ticks[2] = {0, 0};
    int16_t delta_ticks[2] = {0, 0};
    int64_t last_update_time = 0;
    float current_speed[2] = {0, 0};

    void setup()
    {
    // 初始化串口
    Serial.begin(115200); // 初始化串口通信,波特率为115200

    motor.attachMotor(0, 22, 23); // 将电机0连接到引脚22和引脚23
    motor.attachMotor(1, 12, 13); // 将电机1连接到引脚12和引脚13
    // 设置编码器
    encoders[0].init(0, 32, 33); // 初始化第一个编码器,使用GPIO 32和33连接
    encoders[1].init(1, 26, 25); // 初始化第二个编码器,使用GPIO 26和25连接
    // 设置电机
    motor.updateMotorSpeed(0, 100);
    motor.updateMotorSpeed(1, 100);
    }

    void loop()
    {
    delay(10); // 等待10毫秒
    // 计算编码器差值
    int16_t dt = millis() - last_update_time;
    delta_ticks[0] = encoders[0].getTicks() - last_ticks[0];
    delta_ticks[1] = encoders[1].getTicks() - last_ticks[1];
    current_speed[0] = delta_ticks[0] * 0.105805 / dt;
    current_speed[1] = delta_ticks[1] * 0.105805 / dt;

    // 下次正常计算,更新时间
    last_ticks[0] = encoders[0].getTicks();
    last_ticks[1] = encoders[1].getTicks();
    last_update_time = millis();

    // 读取并打印两个编码器的计数器数值
    Serial.printf("speed1=%f\n,speed2=%f\n", current_speed[0], current_speed[1]);
    }