本实例可以向串口输入目标转速,电机通过编码器进行调速,并达到目标转速。输入的目标转速为正或负时,电机转速不同。
1 带霍尔编码器的电机
2 接线
UNO引脚 | 外设引脚 |
2 | 编码器A相 |
5 | 编码器B相 |
3 | L298N驱动IN1 |
4 | L298N驱动IN2 |
7 | L298N驱动ENA |
5V | 面包板 |
GND | 面包板- |
编码电机引脚 | 所接引脚 |
电机线﹢ | L298N驱动AOUT2 |
电机线 - | L298N驱动AOUT1 |
编码器5v | 面包板 |
编码器GND | 面包板- |
L298N | 所接引脚 |
5V | 面包板﹢ |
GND | 面包板- |
12V | 驱动12V电源 |
3 实物连接图
4 程序
const unsigned int Motor_PWM=7;
const unsigned int L298N_IN1=3;
const unsigned int L298N_IN2=4;
int value;
#include <FlexiTimer2.h> //定时中断
#define ENCODER_A 2
#define ENCODER_B 5
String Target_Value;
int Velocity,Count=0;
float Velocity_KP =7.2, Velocity_KI =0.68,Target=0;
int startPWM=0;
int PWM_Restrict=255;
void setup()
{
Serial.begin(9600);
Serial.println("/*****开始驱动*****/");
pinMode(ENCODER_A,INPUT);
pinMode(ENCODER_B,INPUT);
pinMode(L298N_IN1,OUTPUT);
pinMode(L298N_IN2,OUTPUT);
pinMode(Motor_PWM,OUTPUT);
FlexiTimer2::set(5, control); //5毫秒定时中断函数,每5s执行一次control函数
FlexiTimer2::start (); //中断使能
attachInterrupt(0, READ_ENCODER_A, CHANGE);
}
void loop()
{
while(Serial.available()>0) //检测串口是否接收到了数据
{
Target_Value=Serial.readString(); //读取串口字符串
Target=Target_Value.toFloat(); //将字符串转换为浮点型,并将其赋给目标值
Serial.print("目标转速频率:"); //串口打印出设定的目标转速
Serial.println(Target);
}
}
void control()
{
Velocity=Count; //单位时间内读取位置信息
Count=0; //并清零
value=Incremental_PI_A(Velocity,Target);
Set_PWM(value);
}
void READ_ENCODER_A()
{
if (digitalRead(ENCODER_A) == HIGH)
{
if (digitalRead(ENCODER_B) == LOW)
Count ; //根据另外一相电平判定方向
else
Count--;
}
else
{
if (digitalRead(ENCODER_B) == LOW)
Count--; //根据另外一相电平判定方向
else
Count ;
}
}
int Incremental_PI_A (int Encoder,int Target)
{ float Bias;
static float PWM=0,Last_bias=0;
Bias=Target-Encoder; //计算偏差
PWM =Velocity_KP*(Bias-Last_bias) Velocity_KI*Bias; //增量式PI控制器
if(PWM>PWM_Restrict)PWM=PWM_Restrict; //限幅
if(PWM<-PWM_Restrict)PWM=-PWM_Restrict; //限幅
Last_bias=Bias; //保存上一次偏差
return PWM; //增量输出
}
void Set_PWM(int motora)
{
if (motora > 0)
{
digitalWrite(L298N_IN1,HIGH);
digitalWrite(L298N_IN2,LOW);
analogWrite(Motor_PWM, motora startPWM);
}
else if(motora == 0)
{
digitalWrite(L298N_IN1,LOW);
digitalWrite(L298N_IN2,LOW);
}
else if (motora < 0)
{
digitalWrite(L298N_IN1,LOW);
digitalWrite(L298N_IN2,HIGH);
analogWrite(Motor_PWM, -motora startPWM);
}
}
5 实验效果