两轮差速模型控制系统
1. 使用开源库驱动多路电机
电路板引脚输出电流电压信号小,需要电机驱动芯片来放大电信号,驱动电路
PWM频率:1秒钟内信号从高电平到低电平再回到高电平的次数
通电设置不同的占空比,比方说,占空比为50% 那就是高电平时间一半,低电平时间一半,在一定的频率下,就可以得到模拟的2.5V输出电压 那么75%的占空比 得到的电压就是3.75V
D/A转换,控制不同的输出电压,控制电机转速
-
引入开源库
lib_deps = https://github.com/fishros/Esp32McpwmMotor.git -
修改代码
在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. 电机速度测量与转换
速度编码器(两个霍尔元件)
原理:根据磁性的有无,产生高低电平的变化(一次从低到高,再由高到低的过程叫做脉冲)
由于减速器的存在,电动机实际的转动圈数更多,获得的扭力更大
单片机可以测量产生的脉冲,轮子转动一圈转换成产生脉冲的次数,从而可以获得轮子的行走距离,从而计算出轮子转速
-
引入开源库
lib_deps = https://github.com/fishros/Esp32PcntEncoder.git -
修改代码
在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());
} -
记录转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]);
}