Arduino智能小车调速

 将驱动模块的作用发挥出来。首先大家要了解PWM这个概念。

PWM

  脉宽调制(PWM)基本原理:控制方式就是对逆变电路开关器件的通断进行控制,使输出端得到一系列幅值相等的脉冲,用这些脉冲来代替正弦波或所需要的波形。也就是在输出波形的半个周期中产生多个脉冲,使各脉冲的等值电压为正弦波形,所获得的输出平滑且低次谐波少。按一定的规则对各脉冲的宽度进行调制,即可改变逆变电路输出电压的大小,也可改变输出频率。 

 

工具/原料

  • 驱动模块,arduino模块,杜邦线,公母线,小车

  • ArduinoIDE,等等

方法/步骤

  1. 驱动模块接线

      在前面的教程中已经讲过如果想控制驱动的输出时,需要对驱动的“ENA”“ENB”进行控制,因此我们需要将图中被选中部分的两个跳线帽拔掉。并将“ENA”连接Arduino UNO开发板的“5”引脚,“ENB”连接“6”引脚。 

     

  2. Arduino代码测试如下:

     

    int leftCounter=0,  rightCounter=0;

    unsigned long time = 0, old_time = 0; // 时间标记

    unsigned long time1 = 0; // 时间标记

    float lv,rv;//左、右轮速度

     

    #define STOP        0

    #define FORWARD     1

    #define BACKWARD    2

    #define TURNLEFT    3

    #define TURNRIGHT   4

    #define CHANGESPEED 5

     

    int leftMotor1 = 16;

    int leftMotor2 = 17;

    int rightMotor1 = 18;

    int rightMotor2 = 19;

    bool speedLevel=0;

     

    int leftPWM = 5;

    int rightPWM = 6;

     

    void setup() {

      // put your setup code here, to run once:

      Serial.begin(9600); 

      attachInterrupt(0,RightCount_CallBack, FALLING);

      attachInterrupt(1,LeftCount_CallBack, FALLING);

     

      pinMode(leftMotor1, OUTPUT);

      pinMode(leftMotor2, OUTPUT);

      pinMode(rightMotor1, OUTPUT);

      pinMode(rightMotor2, OUTPUT);

      pinMode(leftPWM, OUTPUT);

      pinMode(rightPWM, OUTPUT);

    }

     

    void loop() {

      // put your main code here, to run repeatedly:

      SpeedDetection();

     

      if(Serial.available()>0)

      {

        char cmd = Serial.read();

     

        Serial.print(cmd);

        motorRun(cmd);

        if(speedLevel)  //根据不通的档位输出不同速度

        {

          analogWrite(leftPWM, 120);

          analogWrite(rightPWM, 120);

        }

        else

        {

          analogWrite(leftPWM, 250);

          analogWrite(rightPWM, 250);

        }

      }  

    }

    /*

     * *速度计算

     */

    bool SpeedDetection()

    {

      time = millis();//以毫秒为单位,计算当前时间 

      if(abs(time - old_time) >= 1000) // 如果计时时间已达1秒

      {  

        detachInterrupt(0); // 关闭外部中断0

        detachInterrupt(1); // 关闭外部中断1

        //把每一秒钟编码器码盘计得的脉冲数,换算为当前转速值

        //转速单位是每分钟多少转,即r/min。这个编码器码盘为20个空洞。

        Serial.print("left:");

        lv =(float)leftCounter*60/20;//小车车轮电机转速

        rv =(float)rightCounter*60/20;//小车车轮电机转速

        Serial.print("left:");

        Serial.print(lv);//向上位计算机上传左车轮电机当前转速的高、低字节

        Serial.print("     right:");

        Serial.println(rv);//向上位计算机上传左车轮电机当前转速的高、低字节

        //恢复到编码器测速的初始状态

        leftCounter = 0;   //把脉冲计数值清零,以便计算下一秒的脉冲计数

        rightCounter = 0;

        old_time=  millis();     // 记录每秒测速时的时间节点   

        attachInterrupt(0, RightCount_CallBack,FALLING); // 重新开放外部中断0

        attachInterrupt(1, LeftCount_CallBack,FALLING); // 重新开放外部中断0

        return 1;

      }

      else

        return 0;

    }

    /*

     * *右轮编码器中断服务函数

     */

    void RightCount_CallBack()

    {

      rightCounter++;

    }

    /*

     * *左轮编码器中断服务函数

     */

    void LeftCount_CallBack()

    {

      leftCounter++;

    }

    /*

     * *小车运动控制函数

     */

    void motorRun(int cmd)

    {

      switch(cmd){

        case FORWARD:

          Serial.println("FORWARD"); //输出状态

          digitalWrite(leftMotor1, HIGH);

          digitalWrite(leftMotor2, LOW);

          digitalWrite(rightMotor1, HIGH);

          digitalWrite(rightMotor2, LOW);

          break;

         case BACKWARD:

          Serial.println("BACKWARD"); //输出状态

          digitalWrite(leftMotor1, LOW);

          digitalWrite(leftMotor2, HIGH);

          digitalWrite(rightMotor1, LOW);

          digitalWrite(rightMotor2, HIGH);

          break;

         case TURNLEFT:

          Serial.println("TURN  LEFT"); //输出状态

          digitalWrite(leftMotor1, HIGH);

          digitalWrite(leftMotor2, LOW);

          digitalWrite(rightMotor1, LOW);

          digitalWrite(rightMotor2, HIGH);

          break;

         case TURNRIGHT:

          Serial.println("TURN  RIGHT"); //输出状态

          digitalWrite(leftMotor1, LOW);

          digitalWrite(leftMotor2, HIGH);

          digitalWrite(rightMotor1, HIGH);

          digitalWrite(rightMotor2, LOW);

          break;

         case CHANGESPEED:

          Serial.println("CHANGE SPEED"); //输出状态

          if(speedLevel)  //接收到换挡命令的时候切换档位

            speedLevel=0;

          else

            speedLevel=1;

          break;

         default:

          Serial.println("STOP"); //输出状态

          digitalWrite(leftMotor1, LOW);

          digitalWrite(leftMotor2, LOW);

          digitalWrite(rightMotor1, LOW);

          digitalWrite(rightMotor2, LOW);

      }

    }

     

  3. 为了便于大家理解,这里特意在解释一下:

         在主函数void loop()中添加PWM输出的函数,analogWrite(pin, value)函数中“pin”代表使用的引脚,“value”代表输出PWM值的大小,范围是0~255。

    if(speedLevel)  //根据不通的档位输出不同速度

        {      

    analogWrite(leftPWM, 120);      analogWrite(rightPWM, 120);  

      }  

      else 

       {   

       analogWrite(leftPWM, 250);      analogWrite(rightPWM, 250); 

        }

     

你可能感兴趣的:(嵌入式)