MiniQ 2WD二轮驱动机器车 - 精品套件 - 博趣

  无线电   专题策划 行业动态 测试测量 单片机 精彩制作 精品套件 基础入门 试阅与下载 往期目录 官方淘宝店 制汇节
当前位置:博趣 -> 无线电 -> 精彩制作 -> 精品套件

TOP

MiniQ 2WD二轮驱动机器车(一)
发表日期:2011-03-22 09:52:19 来源: 作者:刘英杰 【 】 浏览:18900次 评论:0

 

你肯定听说过掌上电脑、掌上游戏机吧,那你听说过“掌上小车”吗?最近我玩了一款这样的小车,嘿嘿,此掌上小车可不是让你在手掌上玩的小车哦,是只有手掌大小,具有避障、循线、寻光、遥控、唱歌等功能,既可以在Arduino环境下开发编程,也可以在AVR环境下开发编程的小车。

整个车的长度为仅为12.2cm左右,比成年人的手掌还短些,跟鼠标差不多长,非常小巧、精致。既然名字里有2WD,顾名思义,小车为两轮的。轮胎采用的是橡胶轮胎,直径42mm、宽度19mm;电机采用的是mini的金属齿轮的电机,非常耐用;车的底盘还有4个蓝色的LED灯,上电后即发光,非常漂亮,在光线暗处看起来更加炫彩夺目。

 

 

中标:避障功能

    2WDminiQ具有两个红外发射管和一个红外接收头,可以利用这3个元件和相应的程序让小车实现避障功能。在程序中,让两个红外发射管发射一定宽度的脉冲,通过检测红外接收管是否接收到脉冲来判断是否有障碍物。有了避障功能就可以将它放在室内放心地跑啦,不用担心它被撞坏或者撞坏其他物体。

 

 

中标:遥控功能

    另外,还可以利用红外接收头配合mini遥控器,实现遥控小车。按下遥控器的按键来发射脉冲,红外接收头接收脉冲,程序中通过对红外接收头接收到的脉冲进行解码来判断是哪一个按键按下,即可让小车执行相应的动作。这下子你可以完全指挥它啦,让它成为你的小兵。

 

 

中标:循线功能

    车底盘具备5个mini循线传感器,实现循线功能。可以先设置一下,让小车记住传感器在非赛道上检测的电压值或者在赛道上的电压值,以此值为界限值来区分赛道和场地,从而实现循线的功能。具备这个功能,你就可以让它去参加循线比赛啦,绝对遵守规则,哪里是赛道就往哪里跑。

 

 

中标:寻光功能

    2WDminiQ具有左右两个光敏电阻,可实现寻光功能。将小车放置在要进行寻光的环境中,让小车记住环境光的电压值,接着将光源对准小车,小车即可随着光源左转、右转、原地转圈。当然,你也可以根据你的思路编写出更炫的寻光程序。

 

 

 

中标:开发环境和下载方式。

    2WDminiQ既可以在Arduino环境下开发使用,又可以在AVR环境下开发使用,真的很方便。建议初玩电子制作的朋友在Arduino环境下开发,这个环境很简单、方便;有经验的朋友们可以两个环境都试试。

    2WDminiQ有3种下载程序的方式:

(1)AVR开发环境下可以利用在线下载程序的方式,即将在线下载器插在小车上标有ICSP的接口上即可下载程序。

(2)Arduino开发环境下可以通过UART串口下载程序。

(3)Arduino环境下还可以利用Wireless Programming Module无线下载模块,以无线方式下载程序。在不便连接或根本就无法连接(如机器鱼)USB线缆的场合,Wireless Programming Module可以在一定范围内实现程序的无线下载。除支持Arduino产品的无线程序下载外,此模块还可以用作通用的无线数据传输(UART接口)。此外,它还可以通过兼容XBee模块的扩展板来实现对Arduino全系列控制器在一定范围内进行无线编程(这种方式还需要使用USB线、XBee适配器配合)。

 

 

中标:其他功能

    除了以上的功能,2WDminiQ小车还具有3个可供编程的按键,可以利用蜂鸣器给你唱歌,你可以充分发挥你的才能,利用此小车做出更有趣味的功能。4节5号(AA)电池即可给小车供电。

 

 

下面是在Arduino环境下编写的一个综合程序,这个程序综合了避障、循线、寻光、模拟袭击者行为(没有物体在小车前方时,小车静止不动;当有物体出现在小车前方时,小车突然加速前进。)、模拟小鸡行为(前方没有物体时。小车前进;前方有物体时,小车绕行。)、遥控(按住前进、后退、左转、右转键,小车做出相应动作;松开按键,小车停止。)等功能,各个程序的执行是通过按键选择来进行的。该程序实现的功能如表1所示。:

 

表1

功能或模式

循线功能

避障功能

寻光功能

袭击者模式

小鸡模式

遥控模式

用到的按键

key_1、key_2

key_2

key_2

key_3

key_3

key_3

启动功能

调整传感器(注)完毕后,第6次按key_1按键,两个灯均灭。

第一次按key_2按键

第三次按key_2按键

第一次按key_3按键

第三次按key_3按键

第五次按key_3按键

结束功能

第7次按key_1按键。

第二次按key_2按键。

第四次按key_2按键。

第二次按key_3按键。

第四次按key_3按键。

第六次按key_3按键。

注:将2WDminiQ放到场地的非赛道部分,按一下key_1按键,选择左边第一个传感器,红灯亮;按一下key_2按键,value[0]值加1,直到绿灯亮。重复上述过程,换下一个传感器调整,直到5个传感器都调整好。

 

#define EN1 6//右侧电机使能端

#define IN1 7//右侧电机方向端

#define EN2 5//左侧电机使能端

#define IN2 4//左侧电机方向端

 

#define FORW 1//前进

#define BACK 0//后退

 

#define IR_IN  8//红外接收

#define L_IR 9//左红外发送

#define R_IR 10//右红外发送

 

#define BUZZER 11//蜂鸣器

#define LED_RED 12//红色LED灯

#define LED_GREEN  13//绿色LED灯

 

#define Vr   5//参考电压值

 

int   count;//对返回的脉冲进行计数

float data[8]={

  0X00,0X00,0X00,0X00,0x00,0xff,0x00,0x00};//存储8个通道ad转换的值

char  value[5]={

  0x00,0x00,0x00,0x00,0x00};//5个循线传感器的电压值

char  key_1=0x00,key_2=0x00,key_3=0x00;//按键的计数值

//计数里程

int    count_r=0,count_l=0;//对左右轮返回的脉冲进行计数

//遥控参数

int Pulse_Width=0;//存储脉宽

int  ir_code=0x00; //命令值

 

//控制电机转动

void Motor_Control(int M1_DIR,int M1_EN,int M2_DIR,int M2_EN)

{

  //////////M1////////////////////////

  if(M1_DIR==FORW)//M1方向为FORW

      digitalWrite(IN1,FORW); //向前

  else

    digitalWrite(IN1,BACK);//向后  

  if(M1_EN==0) //M1速度为0

      analogWrite(EN1,LOW);//置低,停止

  else

    analogWrite(EN1,M1_EN);//设置给定的数值

 

  ///////////M2//////////////////////

  if(M2_DIR==FORW) //M2方向为FORW

      digitalWrite(IN2,FORW);//向前

  else

    digitalWrite(IN2,BACK);//向后  

  if(M2_EN==0) //M2速度为0

      analogWrite(EN2,LOW);//置低,停止

  else//否则

  analogWrite(EN2,M2_EN);//设置给定的数值

}

//计数里程

void interrupt01_init(void)//外部中断初始化

{

  EICRA = 0X0F;//设置INT0、INT1为上升沿触发中断

  EIMSK = 0X03;//使能中断INT0、INT1

}

ISR(INT0_vect)//INTO中断函数

{

  if(++count_r==120)//右侧车轮返回脉冲计数

    count_r=0;//计数到120,清零

}

ISR(INT1_vect)//INT1中断函数

{

  if(++count_l==120)//左侧车轮返回脉冲计数

    count_l=0;//计数到120,清零

}

//避障

void L_Send40KHZ(void)//左发射管发射频率为40kHz脉冲

{

  int i;

  for(i=0;i<24;i++)

  {

    digitalWrite(L_IR,LOW);//设置左发射管为高电平

    delayMicroseconds(8);//延时

    digitalWrite(L_IR,HIGH);//设置左发射管为低电平

    delayMicroseconds(8);//延时

  }

}

void R_Send40KHZ(void)//右发射管发射频率为40kHz脉冲

{

  int i;

  for(i=0;i<24;i++)

  {

    digitalWrite(R_IR,LOW);//设置右发射管为高电平

    delayMicroseconds(8);//延时

    digitalWrite(R_IR,HIGH);//设置右发射管为低电平

    delayMicroseconds(8);//延时

  }

}

void pcint0_init(void)//引脚变化中断初始化

{

  PCICR = 0X01;//使能第0组引脚变化中断

  PCMSK0 = 0X01;//使能第0组的第0个引脚变化中断

}

ISR(PCINT0_vect)//PB0引脚变化中断

{

  count++;//计数接收到的脉冲

}

void Obstacle_Avoidance(void)//避障子函数

{  

  char i;

  count=0;

  for(i=0;i<20;i++)//左发射管发射20个脉冲

  {

    L_Send40KHZ();

    delayMicroseconds(600);   

  }

  if(count>20)//接收超过10个脉冲,判断有障碍物

  {

    if(key_2==1||key_3==3)//避障模式或者是小鸡模式

    {

      Motor_Control(BACK,100,BACK,100);//后退

      delay(500);//延时

      Motor_Control(BACK,100,FORW,100);//右转

      delay(500);//延时

    }

    if(key_3==1)//袭击者模式

    {

      Motor_Control(FORW,100,FORW,100);//前进

      delay(300);//延时

    }

  }

  else

  {

    if(key_2==1||key_3==3)//避障模式或者小鸡模式

      Motor_Control(FORW,100,FORW,100);//前进

    if(key_3==1)//袭击者模式

      Motor_Control(FORW,0,FORW,0);//前进

  }

 

 

  count=0;

  for(i=0;i<20;i++)//右发射管发射20个脉冲

  {

    R_Send40KHZ();

    delayMicroseconds(600);       

  }

  if(count>20)

  {

    if(key_2==1||key_3==3)//避障模式或者小鸡行为

    {

      Motor_Control(BACK,100,BACK,100);//后退

      delay(500);//延时

      Motor_Control(FORW,100,BACK,100);//左转

      delay(500);//延时

    }

    if(key_3==1)//袭击者

    {

      Motor_Control(FORW,100,FORW,100);//前进

      delay(300);//延时

    }

  }

  else

  {

    if(key_2==1||key_3==3)//避障模式或者小鸡行为

      Motor_Control(FORW,100,FORW,100);//前进

    if(key_3==1)//袭击者行为

      Motor_Control(FORW,0,FORW,0);//前进

  }

}

//读取模拟端口电压值

void Read_Value(void)

  int i;

  for(i=0;i<8;i++)

  {

    data[i]=analogRead(i);//读取模拟i口电压值

    data[i]= ((data[i]*Vr)/1024); //转换成模拟值

  }

}

//循线

void value_adjust(unsigned char num)//调整循线传感器的值

{

  if(num==1)//调节第1个循线传感器

  {

    if(data[0]>value[0])

    {

      digitalWrite(LED_RED,HIGH); //当前值小红灯亮

      digitalWrite(LED_GREEN,LOW);

    }

    else

    {

      digitalWrite(LED_RED,LOW);

      digitalWrite(LED_GREEN,HIGH);//绿灯亮

    }

  }

  if(num==2)//调节第2个循线传感器

  {

    if(data[1]>value[1])

    {

      digitalWrite(LED_RED,HIGH); //当前值小红灯亮

      digitalWrite(LED_GREEN,LOW);

    }

    else

    {

      digitalWrite(LED_RED,LOW);

      digitalWrite(LED_GREEN,HIGH);//绿灯亮

    }

  }

  if(num==3)//调节第3个循线传感器

  {

    if(data[2]>value[2])

    {

      digitalWrite(LED_RED,HIGH); //当前值小红灯亮

      digitalWrite(LED_GREEN,LOW);

    }

    else

    {

      digitalWrite(LED_RED,LOW);

      digitalWrite(LED_GREEN,HIGH);//绿灯亮

    }

  }

  if(num==4)//调节第4个循线传感器

  {

    if(data[3]>value[3])

    {

      digitalWrite(LED_RED,HIGH); //当前值小红灯亮

      digitalWrite(LED_GREEN,LOW);

    }

    else

    {

      digitalWrite(LED_RED,LOW);

      digitalWrite(LED_GREEN,HIGH);//绿灯亮

    }

  }

  if(num==5)//调节第5个循线传感器

  {

    if(data[4]>value[4])

    {

      digitalWrite(LED_RED,HIGH); //当前值小红灯亮

      digitalWrite(LED_GREEN,LOW);

    }

    else

    {

      digitalWrite(LED_RED,LOW);

      digitalWrite(LED_GREEN,HIGH);//绿灯亮

    }

  }

}

void huntline_deal(void)

{

  if(data[0]>(value[0]-1)&&data[1]>(value[1]-1)&&data[2]<(value[2]-1)&&data[3]>(value[3]-1)&&data[7]>(value[4]-1))//测一下实际值

    Motor_Control(FORW,100,FORW,100);//前进

  else if(data[0]>(value[0]-1)&&data[1]>(value[1]-1)&&data[2]<(value[2]-1)&&data[3]<(value[3]-1)&&data[7]>(value[4]-1))

    Motor_Control(BACK,20,FORW,100);//右转

  else if(data[0]>(value[0]-1)&&data[1]>(value[1]-1)&&data[2]>(value[2]-1)&&data[3]<(value[3]-1)&&data[7]>(value[4]-1))

    Motor_Control(BACK,100,FORW,100);//快速右转      

  else if(data[0]>(value[0]-1)&&data[1]>(value[1]-1)&&data[2]>(value[2]-1)&&data[3]<(value[3]-1)&&data[7]<(value[4]-1))

    Motor_Control(BACK,100,FORW,100);//快速右转

  else if(data[0]>(value[0]-1)&&data[1]>(value[1]-1)&&data[2]>(value[2]-1)&&data[3]>(value[3]-1)&&data[7]<(value[4]-1))

    Motor_Control(BACK,100,FORW,100);//快速右转

  else if(data[0]>(value[0]-1)&&data[1]<(value[1]-1)&&data[2]<(value[2]-1)&&data[3]>(value[3]-1)&&data[7]>(value[4]-1))

    Motor_Control(FORW,100,BACK,20);//左转

  else if(data[0]>(value[0]-1)&&data[1]<(value[1]-1)&&data[2]>(value[2]-1)&&data[3]>(value[3]-1)&&data[7]>(value[4]-1))

    Motor_Control(FORW,100,BACK,100);//快速左转

  else if(data[0]<(value[0]-1)&&data[1]<(value[1]-1)&&data[2]>(value[2]-1)&&data[3]>(value[3]-1)&&data[7]>(value[4]-1))

    Motor_Control(FORW,100,BACK,100);//快速左转

  else if(data[0]<(value[0]-1)&&data[1]>(value[1]-1)&&data[2]>(value[2]-1)&&data[3]>(value[3]-1)&&data[7]>(value[4]-1))

    Motor_Control(FORW,100,BACK,100);//快速左转

}

//寻光

void hunt_light(void)//寻光子函数

{

  if (data[4] >1&&data[4]< 2)   //根据实际的实验环境进行测量

    Motor_Control(BACK,100,FORW,100);//右转

  else if (data[4] > 4 && data[4] < 5)

    Motor_Control(FORW,100,BACK,100);//左转

  else

    Motor_Control(FORW,0,FORW,0);//停止

}

//遥控功能函数

void timer1_init(void)

{

  TCCR1A = 0X00;

  TCCR1B = 0X05;//给定时器时钟源 

  TCCR1C = 0X00;

  TCNT1 = 0X00;

  TIMSK1 = 0X00;  //禁止定时器溢出中断

}

void remote_deal(void)

{

  switch(ir_code)

  {

  case 0xff00:

    Motor_Control(FORW,0,FORW,0);//停止

    break;

  case 0xfe01:

    Motor_Control(FORW,100,FORW,100);//前进

    break;

  case 0xf609:

    Motor_Control(BACK,100,BACK,100);//后退

    break;

  case 0xfb04:

    Motor_Control(FORW,100,BACK,100);//左转

    break;

  case 0xf906:

    Motor_Control(BACK,100,FORW,100);//右转

    break;

  }

}

char logic_value()

{

  while(!(digitalRead(8))); //低等待

  Pulse_Width=TCNT1;

  TCNT1=0;

  if(Pulse_Width>=7&&Pulse_Width<=10)//低电平560us

  {

    while(digitalRead(8));//是高就等待

    Pulse_Width=TCNT1;

    TCNT1=0;

    if(Pulse_Width>=7&&Pulse_Width<=10)//接着高电平560us

      return 0;

    else if(Pulse_Width>=25&&Pulse_Width<=27) //接着高电平1.7ms

      return 1;

  }

  return -1;

}

void pulse_deal()

{

  int i;

 

  //执行8个0

  for(i=0; i<8; i++)

  {

    if(logic_value() != 0) //不是0

        return;

  }

  //执行6个1

  for(i=0; i<6; i++)

  {

    if(logic_value()!= 1) //不是1

        return;

  }

  //执行1个0

  if(logic_value()!= 0) //不是0

      return;

  //执行1个1

  if(logic_value()!= 1) //不是1

      return;

 

 

  //解析遥控器编码中的command指令

  ir_code=0x00;//清零

  for(i=0; i<16;i++ )

  {

    if(logic_value() == 1)

    {

      ir_code |=(1<

    }

  }

}

void remote_decode(void)

{

  TCNT1=0X00;      

  while(digitalRead(8))//是高就等待

  {

    if(TCNT1>=1563)  //当高电平持续时间超过100ms,表明此时没有按键按下

    {

      ir_code = 0xff00;

      return;

    } 

  }

 

  //如果高电平持续时间不超过100ms

  TCNT1=0X00;

 

  while(!(digitalRead(8))); //低等待

  Pulse_Width=TCNT1;

  TCNT1=0;

  if(Pulse_Width>=140&&Pulse_Width<=141)//9ms

  {

 

    while(digitalRead(8));//是高就等待

    Pulse_Width=TCNT1;

    TCNT1=0;

    if(Pulse_Width>=68&&Pulse_Width<=72)//4.5ms

    {

      pulse_deal();

      return;

    }

    else if(Pulse_Width>=34&&Pulse_Width<=36)//2.25ms

    {

      while(!(digitalRead(8)));//低等待

      Pulse_Width=TCNT1;

      TCNT1=0;

      if(Pulse_Width>=7&&Pulse_Width<=10)//560us

      {

        return;

      }

    }

  }

 

}

 

//蜂鸣器声音

void buzzer(void)//蜂鸣器发出一种声音

{

  digitalWrite(BUZZER,HIGH);//置高,蜂鸣器响

  delay(1);

  digitalWrite(BUZZER,LOW);//置低,蜂鸣器不响

  delay(10);

}

//按键扫描

void key_scan(void)

{

  if(data[5]>4.50&&data[5]<6.00)//没有按键按下

    return;//返回

  else

  {

    if(data[5]>=0.00&&data[5]<0.50)//按键1按下

    {

      delay(10);//延时消抖

      if(data[5]>=0.00&&data[5]<0.50)//按键1确实按下

      {

        buzzer();//蜂鸣器响

        while(data[5]>=0.00&&data[5]<0.50)

          Read_Value();

        key_1++;//按键1计数

        if(key_1>=1&&key_1<=5)

          value_adjust(key_1);//循线传感器的值调整

      }

    }

    else if(data[5]>=0.50&&data[5]<1.5)

    {

      delay(10);//延时消抖

      if(data[5]>=0.50&&data[5]<1.5)

      {

        buzzer();//蜂鸣器响

        while(data[5]>=0.50&&data[5]<1.5)

          Read_Value();

        if(key_1>=1&&key_1<=5)//按键1的值在1~5之间

        {

          value[key_1-1]++;//传感器的分辨轨迹的界限值加加(调整)

          value_adjust(key_1);//跟实际值对比

        }

        else

        {

          key_2++;//key2计数

        }

      }

    }

    else if(data[5]>=1.5&&data[5]<2.5)

    {

      delay(10);//延时消抖

      if(data[5]>=1.5&&data[5]<2.5)

      {

        buzzer();//蜂鸣器响

        while(data[5]>=1.5&&data[5]<2.5)

          Read_Value();

        if(key_1>=1&&key_1<=5)//按键1的值在1~5之间

        {

          value[key_1-1]--;//传感器的分辨轨迹的界限值减减(调整)

          value_adjust(key_1);//跟实际值对比

        }

        else

        {

          key_3++;//key3计数

        }

      }

    }

  }

}

void key_deal()

{

  if(key_1==6)//循线

  {

    digitalWrite(LED_RED,LOW);//红灯灭

    digitalWrite(LED_GREEN,LOW);//绿灯灭

    huntline_deal();//调用循线处理子函数

  }

  if(key_2==1||key_3==1||key_3==3)//避障,小鸡行为,袭击者

  {

    digitalWrite(LED_RED,HIGH);

    pcint0_init();//引脚变化中断初始化

    interrupt01_init();//外部中断0和1中断初始化

    sei();     //全局中断使能

    Obstacle_Avoidance();

  }

  if(key_2==3)//寻光

  {

    digitalWrite(LED_RED,HIGH);

    hunt_light();//调用寻光子函数

  }

  if(key_3==5)//遥控

  {

    digitalWrite(LED_RED,HIGH);//红灯亮

    timer1_init();//定时器初始化函数

    remote_decode();  //译码

    remote_deal();   //执行译码结果

  }

  if(key_1==7||key_2==2||key_2==4||key_3==2||key_3==4||key_3==6)

  {

    //按键值清零

    key_1=0;

    if(key_2==4)

      key_2=0;

    if(key_3==6)

      key_3=0;

    digitalWrite(LED_RED,LOW);

    Motor_Control(FORW,0,FORW,0);//停止

  }

}

//低电压检测

void low_voltage_check(void)

{

  if(data[6]<2.5)//当电压低于2.5V时

  {

    buzzer(); //蜂鸣器响

  }

}

void setup()

{

  int i;

  for(i=4;i<=13;i++)//设置引脚模式

  {

    pinMode(i,OUTPUT);

  }

  pinMode(IR_IN,INPUT);//红外线接收的引脚为输入

}

void loop()

{

  Motor_Control(FORW,0,FORW,0);//小车停止 

  while(1)

  {

    Read_Value();//读取模拟口的值

    key_scan();//扫描按键

    key_deal();//按键处理

    low_voltage_check();//低电压检测

  }

}

 

 > 相关内容:

 
Tags:《无线电》 制作 责任编辑:zhangxiao
首页 上一页 1 2 3 4 5 6 7 下一页 尾页 1/7/7
】【打印繁体】【投稿】【收藏】 【推荐】【举报】【评论】 【关闭】 【返回顶部
上一篇无线模块让Arduino更自由 下一篇把玩我的3PA三轮小车

评论区

已有0位网友发表评论
帐  号: 密码: (如果您还不是博趣会员,欢迎注册)
表  情:
内  容:
网友评论仅供其表达个人看法,并不表明博趣网同意其观点或证实其描述。

赞助商链接

最新文章

热门文章

推荐文章