【Arduino玩具】东张西望的避障车

   日期:2021-03-30     浏览:104    评论:0    
核心提示:目录简介演示BOM接线Arduino IDE 代码参考简介通过舵机的左右旋转来控制超声波模块的测量区域。障碍物出现时, 即探测到的距离小于10cm时,底盘会朝着远离障碍物的方向转动。演示 【Arduino玩具】东张西望的避障车 BOMArduino UNO x 1超声波测距模块(HC-SR04) x 1舵机(SG 90) x 1红色LED x 1履带式底盘,含两个.

目录

    • 简介
    • 演示
    • BOM
    • 接线
    • Arduino IDE 代码
    • 参考

简介

通过舵机的左右旋转来控制超声波模块的测量区域。障碍物出现时, 即探测到的距离小于10cm时,底盘会朝着远离障碍物的方向转动。

演示

【Arduino玩具】东张西望的避障车

BOM

Arduino UNO x 1
超声波测距模块(HC-SR04) x 1
舵机(SG 90) x 1
红色LED x 1
履带式底盘,含两个减速电机(Pololu Zumo) x 1
马达驱动版(Zumo Shield V1.3) x 1

接线

Arduino IDE 代码

舵机的操控使用了 ATmega328P 的 timer-2, 代码稍微复杂一些。因为马达驱动板的库文件 <ZumoShield.h> 使用的是 timer -1,会与 <Servo.h> 冲突。如果使用其它不需要库文件的马达驱动的话,代码会简单很多,例如 L298N。



#include <Wire.h> 
#include <ZumoShield.h> //马达驱动板需要的库文件 
ZumoMotors motors;

#define Echo 2 //HC-SR04 Echo pin//超声波测距模块的“回声”引脚接 D2
#define Trig 3 //HC-SR04 Trig pin//超声波测距模块的“激发”引脚接 D3
#define SERVO 11 //Servo pin//舵机接 D11或 D3,因为要使用 timer-2
#define LED 5 //LED pin//LED接 D5


uint16_t volatile servoTime = 0;
uint16_t volatile servoHighTime = 3000; // Pulse width in units of 0.5us//高电平持续时间
 boolean volatile servoHigh = false;    

float distance;                         //distance measured by HC-SR04//超声波模块探测到的距离 

void setup(){ 
  Serial.begin(9600);
  pinMode(Trig, OUTPUT); pinMode(Echo, INPUT); pinMode(LED, OUTPUT);
  servoInit();
}
 
void loop(){ 
    //Drive Forward//前进*******************************************************************************************
    motors.setLeftSpeed(100);   motors.setRightSpeed(100); //0-25

    //Look Right//向右看*********************************************************************************************
    servoSetPosition(1000);                                      //Send 1000us pulses to servo//1000us的脉冲,转动舵机
    distance = MeasureDistance();                                //HC-SR04//超声波模块测距
    
    while (distance <10 ) {                                       //turn left, till the obstacle is more than 10cm away
      motors.setLeftSpeed(-100); motors.setRightSpeed( 100);     //底盘向左转动,直到障碍物处于10cm开外 
      digitalWrite(LED, HIGH);                                   
      distance = MeasureDistance();}
    
    digitalWrite(LED, LOW); 
    delay(700);                                                  //for stable HC-SR04 readings
                                                                 //700ms毫秒的延迟貌似会让超声波模块的读数稳定一些
   //Look Forward//向前看********************************************************************************************
   servoSetPosition(1500);  
    distance = MeasureDistance();
    while (distance <15) {   
      motors.setLeftSpeed(-100);   motors.setRightSpeed( 100); 
      digitalWrite(LED, HIGH); 
      distance = MeasureDistance();}
      digitalWrite(LED, LOW); 
    delay(700);
    
    //Look Forward//向右看********************************************************************************************
    servoSetPosition(2000); 
      distance = MeasureDistance();
      while(distance <10) {   
      motors.setLeftSpeed( 100);   motors.setRightSpeed(-100);
      digitalWrite(LED, HIGH);
      distance = MeasureDistance();}
      digitalWrite(LED, LOW); 
     delay(700);

    //Look Forward//向前看********************************************************************************************
     servoSetPosition(1500); 
    distance = MeasureDistance();
    while (distance <15 ) {   
      motors.setLeftSpeed( 100);   motors.setRightSpeed(-100); 
      digitalWrite(LED, HIGH);
      distance = MeasureDistance();}
      digitalWrite(LED, LOW); 
    delay(700);
}

//Functions//函数****************************************************************************************************

float MeasureDistance(){  //测距
     float d;
     digitalWrite(Trig, LOW);  delayMicroseconds(2);
     digitalWrite(Trig, HIGH); delayMicroseconds(10);
     digitalWrite(Trig, LOW);
     d = (pulseIn(Echo, HIGH) / 2) * 343/10000; //测距公式,"d" 的单位是 "cm"
     Serial.println(d);
     return d; } 

//在Timer 2 达到 OCR2A 并重置后启动ISR
ISR(TIMER2_COMPA_vect){                //Timer/Counter2 Compare Match A//中断向量
  servoTime += OCR2A + 1;
  static uint16_t highTimeCopy = 3000;
  static uint8_t interruptCount = 0;
  if(servoHigh){ 
    if(++interruptCount == 2){ 
      OCR2A = 255;}
    if(servoTime >= highTimeCopy){   //Servo引脚处在高电平状态
      digitalWrite(SERVO, LOW);     //做一个下降沿
      servoHigh = false;
      interruptCount = 0;}
    } 
  else{                              //Servo引脚处在低电平状态
    if(servoTime >= 40000){     
      highTimeCopy = servoHighTime;
      digitalWrite(SERVO, HIGH);    //做一个上升沿
      servoHigh = true; servoTime = 0; interruptCount = 0;
      OCR2A = ((highTimeCopy % 256) + 256)/2 - 1;}
  }
}
 
void servoInit(){ 
  digitalWrite(SERVO, LOW); pinMode(SERVO, OUTPUT);
  //开启CTC模式,Timer 2 会增加到 OCR2A 然后重置,造成中断
  TCCR2A = (1 << WGM21);
  TCCR2B = (1 << CS21);            //0.5us分辨率
  TCNT2 = 0; OCR2A = 255;          
  TIMSK2 |= (1 << OCIE2A);         // 开启 timer compare interrupt.
  sei();                           // 开启中断
}
 
void servoSetPosition(uint16_t highTimeMicroseconds){ 
  TIMSK2 &= ~(1 << OCIE2A);        // 关闭 timer compare interrupt.
  servoHighTime = highTimeMicroseconds * 2;
  TIMSK2 |= (1 << OCIE2A);         // 开启 timer compare interrupt.
}

参考

  1. 中断处理教程
  2. ATmega328P 数据手册
  3. Polulu Zumo 底盘,驱动版手册
 
打赏
 本文转载自:网络 
所有权利归属于原作者,如文章来源标示错误或侵犯了您的权利请联系微信13520258486
更多>最近资讯中心
更多>最新资讯中心
更多>相关资讯中心
0相关评论

推荐图文
推荐资讯中心
点击排行
最新信息
新手指南
采购商服务
供应商服务
交易安全
关注我们
手机网站:
新浪微博:
微信关注:

13520258486

周一至周五 9:00-18:00
(其他时间联系在线客服)

24小时在线客服