基于arduino的自动巡轨小车教程(一)电机篇

电机的驱动

在完成基本车体结构的搭建后,首先完成电机部分工作。
本教程使用arduino和LM298驱动模块驱动电机
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");


}

利用串口监视器输出数字及为左右轮的速度。

猜你喜欢

转载自blog.csdn.net/qq_40272342/article/details/81276140