关键词:Arduino 霍尔编码器 PWM 中断 轮速
硬件:12V直流电源(或电池)、直流电机(带霍尔编码器)、Arduino UNO板
简单原理:设定一定目标左右轮速,Arduino板根据车轮电机上霍尔编码器采集AB相脉冲数判定车轮实际轮速,根据实际左右轮速差,转换为修正左轮的轮速的PWM。
注意,本文并没有实现实际轮速与设定轮速的修正,后续会增加此部分的代码实现。
#include "Wire.h" //serial
#include "I2Cdev.h" //IIC
#include "MPU6050.h" //acc&gyro Sensor
//把小车右侧电机的编码器OUTA信号连接到Arduino控制器的数字端口2
int PinA_right = 2; 数字端口2是Arduino的外部中断0的端口
int PinB_right = 8; //右侧电机的编码器OUTB 信号对于数字端口8
//把小车左侧电机的编码器OUTA信号连接到Arduino控制器的数字端口3
int PinA_left = 3; //数字端口3是Arduino的外部中断1的端口
int PinB_left = 10; //左侧电机的编码器OUTB 信号对于数字端口10
int E_right =5; //连接小车右侧电机的PWM控制端口到数字接口5
int M_right =4; //连接小车右侧电机的转向控制端口到数字接口4
int M_right2 =12; //连接小车右侧电机的转向控制端口到数字接口12
int E_left =6; //连接小车左侧电机的PWM控制端口到数字接口6
int M_left =7; //连接小车左侧电机的转向控制端口到数字接口7
int M_left2 =13; //连接小车右侧电机的转向控制端口到数字接口13
int PWM_right=150;//设置电机初始PWM功率值
int PWM_left=PWM_right;
int flag; //暂存变量,用于Arduino接受Andriod手机的控制字符
long count_right = 0; //定义编码器码盘计数值(此编码器转一圈发出334个脉冲)
long count_left = 0;
long rpm_right = 0; //每分钟(min)转速(r/min)
long rpm_left = 0;
unsigned long time = 0, old_time = 0;// 时间标记
//初始化
void setup()
{
Wire.begin();
Serial.begin(115200); // 启动串口通信,波特率9600b/s
pinMode(M_right, OUTPUT); //直流电机驱动板的控制端口设置为输出模式
pinMode(M_right2, OUTPUT);
pinMode(E_right, OUTPUT);
pinMode(M_left, OUTPUT);
pinMode(M_left2, OUTPUT);
pinMode(E_left, OUTPUT);
pinMode(PinA_right,INPUT); //伺服电机编码器的OUTA和OUTB信号端设置为输入模式
pinMode(PinB_right,INPUT);
pinMode(PinA_left,INPUT);
pinMode(PinB_left,INPUT);
//定义外部中断的中断子程序Code(),中断触发为下跳沿触发
//当编码器码盘的正交编码板OUTA脉冲信号发生下跳沿中断时,
//将自动调用执行中断子程序Code()。
attachInterrupt(0, Code_right, FALLING);
attachInterrupt(1, Code_left, FALLING);
}
//对直流电机驱动板的使能端口和转向端口进行设置,以使小车
//执行前进、后退、左转、右转、停止和速度切换动作。
void advance()//小车前进
{
digitalWrite(M_right,HIGH);
digitalWrite(M_right2,LOW);
analogWrite(E_right,PWM_right);
digitalWrite(M_left,HIGH);
digitalWrite(M_left2,LOW);
analogWrite(E_left,PWM_left);
}
//主程序
void loop()
{
//Serial.print("Advance!\t");
advance(); //小车前进
time = millis();//以毫秒为单位,计算当前时间
//计算出每0.5秒钟内,编码器码盘计得的脉冲数,
if(abs(time - old_time) >= 500) // 如果计时时间已达0.5秒
{
detachInterrupt(0); // 关闭外部中断0
detachInterrupt(1); // 关闭外部中断1
//此直流减速电机的编码器码盘为334个齿,减速比为21.3。
//把编码器每0.5秒钟计得的脉冲数,换算为当前转速值的计算式
rpm_right =(float)count_right*60*2/(334*21.3);
rpm_left =(float)count_left*60*2/(334*21.3);
//根据左右车轮转速差,乘以比例调节因子2,获得比例调节后的左侧电机PWM功率值
PWM_left=(float)PWM_left+(rpm_right-rpm_left)*2;
//根据刚刚调节后的小车电机PWM功率值,
//及时修正小车前进或者后退状态,以使小车走直线
count_right = 0; //把脉冲计数值清零,以便计算下一个0.5秒的脉冲计数
count_left = 0;
old_time= millis(); // 记录每次0.5秒测速后的时间节点
attachInterrupt(0, Code_right,FALLING); // 重新开放外部中断0
attachInterrupt(1, Code_left,FALLING); // 重新开放外部中断1
}
}
//右侧电机编码器码盘计数中断子程序
void Code_right()
{
count_right += 1; // 编码器码盘计数加一
Serial.print("count_right\t");
Serial.print(count_right);
Serial.print("\n");
}
//左侧电机编码器码盘计数中断子程序
void Code_left()
{
count_left += 1; // 编码器码盘计数加一
Serial.print("count_left\t");
Serial.print(count_left);
Serial.print("\n");
}