电机的驱动
在完成基本车体结构的搭建后,首先完成电机部分工作。
本教程使用arduino和LM298驱动模块驱动电机
具体连线如下:
代码如下:
接线与代码之间引脚的定义不同自行改变引脚
#define PIN_PWML 9
#define PIN_AIN3 A3//对应板子上INPUT3
#define PIN_AIN4 A4//对应板子上INPUT4
#define PIN_PWMR 10
#define PIN_AIN1 A1//对应板子上INPUT1
#define PIN_AIN2 A2//对应板子上INPUT2
void setup() {
pinMode(PIN_PWML,OUTPUT);
pinMode(PIN_AIN3,OUTPUT);
pinMode(PIN_AIN4,OUTPUT);
pinMode(PIN_PWMR,OUTPUT);
pinMode(PIN_AIN1,OUTPUT);
pinMode(PIN_AIN2,OUTPUT);
}
void loop() {
analogWrite(PIN_PWML,200);
digitalWrite(PIN_AIN3,LOW);
digitalWrite(PIN_AIN4,HIGH);
delay(3000);
analogWrite(PIN_PWMR,200);
digitalWrite(PIN_AIN1,LOW);
digitalWrite(PIN_AIN2,HIGH);
delay(3000);
}
以上代码能实现两轮同时转动(电机接入正负不同,要使得两轮同时向前转,调节电机接入的正负极即可)利用pwm控制轮子的转速。这里设置的pwm输出为200。
PWM控制技术就是对半导体开关器件的导通和关断进行控制,使输出端得到一系列幅值相等而宽度不相等的脉冲,用这些脉冲来代替正弦波或其他所需要的波形。按一定的规则对各脉冲的宽度进行调制,既可改变逆变电路输出电压的大小,也可改变输出频率。
电机的测速
pwm控制输出的与电压有关,所以输出的就是力矩。为了小车能实现被控制能走直线进而转弯,就要对两边的pwm波进行调节。该教程我们使用PID调节方法。为之后实验做准备,我们就要先实现对电机的测速。
- 当测试状态为一轮FALLING,一轮RISING时计数。
- 转速计算方法:用捕获值(一秒内输出的脉冲数)/编码器线数(转速一圈输出脉冲数)/电机减数比(内部电机转动圈数与电机输出轴转动圈数比,即减速齿轮比)
本教程使用的电机每转动一周输出390个脉冲,PERIOD为测速周期
速度计算公式为:
velocity =(encoderVal / 780.0)*3.1415 *2.0 (1000 / PERIOD)*实验代码如下
#include<MsTimer2.h>
//左右电机码盘
#define ENCODER_R1 3
#define ENCODER_R2 4
#define ENCODER_L1 2
#define ENCODER_L2 5
//左右电机PWM波以及电机正负极接入
#define PWML_R 10
#define INL_R1 A2
#define INL_R2 A1
#define PWML_L 9
#define INL_L1 A4
#define INL_L2 A3
#define PERIOD 10
volatile long encoderVal_R = 0;
volatile long encoderVal_L = 0;
volatile float velocityR;
volatile float velocityL;
void getEncoder_l(void){
if(digitalRead(ENCODERL_A)==LOW){
if(digitalRead(ENCODERL_B)==LOW )
{
encoderVal_l--;
}
else
{
encoderVal_l++;
}
}
else
{
if(digitalRead(ENCODERL_B)==LOW)
{
encoderVal_l++;
}
else
{
encoderVal_l--;
}
}
}
void getEncoder_r(void){
if(digitalRead(ENCODERR_A)==LOW){
if(digitalRead(ENCODERR_B)==LOW )
{
encoderVal_r--;
}
else
{
encoderVal_r++;
}
}
else
{
if(digitalRead(ENCODERR_B)==LOW)
{
encoderVal_r++;
}
else
{
encoderVal_r--;
}
}
}
void control(void)
{
velocityR = (encoderVal_R*2.0)*3.1415*2.0*(1000/PERIOD)/780;
encoderVal_R = 0;
velocityL = (encoderVal_L*2.0)*3.1415*2.0*(1000/PERIOD)/780;
encoderVal_L = 0;
}
void setup()
{
TCCR1B = TCCR1B & B11111000 | B00000001;
pinMode(INL_L1,OUTPUT);
pinMode(INL_L2,OUTPUT);
pinMode(PWML_L,OUTPUT);
pinMode(INL_R1,OUTPUT);
pinMode(INL_R2,OUTPUT);
pinMode(PWML_R,OUTPUT);
pinMode(ENCODER_R1,INPUT);
pinMode(ENCODER_R2,INPUT);
pinMode(ENCODER_L1,INPUT);
pinMode(ENCODER_L2,INPUT);
attachInterrupt(ENCODER_R1 - 2,getEncoderR,FALLING);
attachInterrupt(ENCODER_L1 - 2,getEncoderL,FALLING);
//寻迹模块D0引脚初始化
pinMode(trac1, INPUT);
pinMode(trac2, INPUT);
pinMode(trac3, INPUT);
// pinMode(trac4, INPUT);
pinMode(trac5, INPUT);
pinMode(trac6, INPUT);
pinMode(trac7, INPUT);
// pinMode(tracL,INPUT);
// pinMode(tracR,INPUT);
MsTimer2::set(PERIOD,control);
MsTimer2::start();
Serial.begin(9600);
}
}
void loop() {
delay(10);
Serial.print("velocityR=");
Serial.print(velocityR);
Serial.print("velocityL =");
Serial.print(velocityL);
Serial.print(" ");
Serial.print("\r\n");
}
利用串口监视器输出数字及为左右轮的速度。