SmartRobot三轮避障平台开发历程

作者:Edison钟

日期:2012.6

产品&技术开发背景

  1. 基于之前理论学习系统性实践嵌入式产品开发
  2. 初步实现对摄像头的驱动及图像显示
  3. 了解机器视觉的基本原理及目标识别追踪

设计目标及要求

  1. 驱动类型:2个DC减速电机前轮驱动,后轮采用万向轮
  2. 运动控制: 前进,后退,左转,右转,壁障,目标追踪
  3. 控制方式:红外壁障,摄像头目标追踪,PC无线控制,RF四路无线控制
  4. 上位机开发用于摄像头图像显示及追踪目标的RGB设置

设计思路及原理:

  1. 驱动摄像头读取图像传感器的原始数据RGB565格式并解码各自R,G,B值用于目标识别
  2. 对图像像素级扫描,识别到目标颜色后记录当前像素的X,Y坐标值判断该目标在该视场的相对位置
  3. 驱动前轮实现目标的追踪或者避障,驱动双舵机摄像头云台实现目标的精细追踪
  4. IR传感器主要用于近距离避障
  5. 通过VS6开发的上位机软件实现与小车的串口通信用于图像显示及目标颜色设置

硬件选型:

  1. 电源:DC5V
  2. 核心控制器:STC12C5A60S2 1T单片机,硬件资源:两个16位定时器,两路8位PWM输出,两个自带独立波特率发生器串口,两路外部中断
  3. 传感器:
  •      红外线传感器
  •     OV7670 CMOS图像传感器
  1. 动力执行元件:
  •     DC电机类型:TT减速电机,额定转速180RPM, 减速比48:1
  •     输出轴连接方式:腰型头
  •     2路辉盛SG90 9克舵机
  1. 电机驱动板:
  •     驱动类型:L293D双H桥
  •     最大允许电压:36V
  •     持续工作电流:1A
  •     最高工作电流:2A
  •     控制方式:电机方向控制,2路PWM 0%-100%无极调速

模型总装图

上位机图像显示及目标RGB设置

实测避障算法初步测试

视频链接: 小车避障测试-CSDN直播

设计注意事项:

  1. 红外壁障如何去除可见光干扰
  2. 摄像头如何通过算法对目标的识别
  3. 后续建议加入三轴磁力计实现方位的精准建模

项目回顾及展望:

  1. 通过前期的理论学习第一次实现了对整个系统各硬件的驱动与控制
  2. 初步实现了目标的识别和追踪
  3. 践行了概念到原型机落地测试的整个开发过程
  4. 为后续项目的概念开发及验证打下坚实基础

控制软件版本更改记录:

V0.1:

  1. 原始版本
  2. MCU: STC90C516RD@11.0592MHz
  3. 定时器0产生38KHz PWM信号用于红外壁障
  4. 定时器1用于串口波特率发生器
  5. 串口波特率为57600

V0.2:

  1. MCU: STC12C5A60S2@10592MHz
  2. 更改红外发射延时时间

V0.3:

  1. 增加2舵机以控制摄像头上下左右转动追踪目标
  2. 定时器0产生8路PWM信号控制2路舵机
  3. 因定时器0用于产生PWM信号控制舵机,红外壁障功能被取消

最新软件代码:

/*******************************************V0.3*******************************************/

/**************************************************************************
This program is to control the robot to run automatically, the robot can 
detect the barriers in front of it by using 2 IR sensors, and can execute 
responding actions preprogrammed to avoid crashing the barrier.
Sensors like acceleration detect, IR human detect could be added to extend 
the function and make it smarter.

MCU: STC12C5A60S2
晶震频率:11.0592MHz
**************************************************************************/

#include <REG51.h>
#include "Robot_Driver.h"
#include "MCU_Setting.h"
#include "OV7670.h"

#include "Servo_Driver.h"
//#include "LCD_GYTF018LB35B0M.h"

#define uchar unsigned char
#define uint  unsigned int

#define RGBVALUE 0x00
#define COMMAND  0x01
#define STOP     0xff

#define red   0xf800
#define green 0x07e0
#define blue  0x001f
#define white 0xffff
#define black 0x0000


uchar ReData[4],SenData[],PCCommand=0;
uchar KEY_A=0;

uchar Capture=0,OV7670_flag=0;
uchar Quit=1;
uchar i=0;
uchar temp;
uchar Target_R=255,Target_G=0,Target_B=0;
uchar Robot_EN=0;

uchar order_flag,Deg_1,Deg_2,Deg_3,Deg_4,Deg_5,Deg_6,Deg_7,Deg_8;
uint  T_1,T_2,T_3,T_4,T_5,T_6,T_7,T_8;

bit servo_3;
bit servo_4; 
bit servo_5;
bit servo_6;
bit servo_7;
bit servo_8;


/*****************************************************

                    入口函数

*****************************************************/
void main(void)
{
   MCU_init();	                    //MCU初始化
   //LCD_init();					//LCD初始化
   OV7670_init();					//摄像头初始化
   //LCD_paint(black);				//LCD刷黑色
   while(1)
   { 
  	   //ET0=0;
/****************************************************
       if(RF_INPUT_A==1)         //遥控控制模式切换
	   {
	       while(RF_INPUT_A);
	       KEY_A++;
		   Robot_EN=1;
	       if(KEY_A>3) KEY_A=0;
	    }
/****************************************************/	    	     
		if(ReData==10) KEY_A=0;	   //PC控制模式切换
	    if(ReData==11) KEY_A=1;
	    if(ReData==12) KEY_A=2;
		if(ReData==13) KEY_A=3;
/****************************************************/
		//KEY_A=3;
		if(KEY_A==0) PC_control(); //控制模式
	    if(KEY_A==1) RF_control();
	    if(KEY_A==2) IR_control();
        if(KEY_A==3) camera_control();
    }
}


/*****************************************************
                  定时器中断函数
/****************************************************/
void timer0(void) interrupt 1 using 1
                           
{

    //PWM_output=!PWM_output; //产生38KHz脉冲用于发送红外信号

   switch(order_flag)
   {
      case 1: 
	     
		  servo_1=1;
          TH0=T_1>>8;  //TH0=-t1/256;
          TL0=T_1;     //TH0=-t1%256;
          break;

      case 2: 
	     
		  servo_1=0;        
		  TH0=(0xf700-T_1)>>8; //-(2700-t1)/256
          TL0=(0xf700-T_1);    //-(2700-t1)%256		
          break;

      case 3: 
	   
	      servo_2=1;
          TH0=T_2>>8;
          TL0=T_2;
          break;

      case 4: 
	  
	      servo_2=0;
          TH0=(0xf700-T_2)>>8;
          TL0=(0xf700-T_2);
          break;

      case 5: 
	  
	      servo_3=1;
          TH0=T_3>>8;
          TL0=T_3;
          break;

      case 6: 
	   
	      servo_3=0 ;
          TH0=(0xf700-T_3)>>8;
          TL0=(0xf700-T_3);
          break;

      case 7: 
	  
	      servo_4=1;
          TH0=T_4>>8;
          TL0=T_4;
          break;
		   
      case 8: 
	  
	      servo_4=0;
          TH0=(0xf700-T_4)>>8;
          TL0=(0xf700-T_4);
          break;

      case 9: 
	  
	      servo_5=1;
          TH0=T_5>>8;
          TL0=T_5;		 
          break;

      case 10: 
	  
	      servo_5=0;
          TH0=(0xf700-T_5)>>8;
          TL0=(0xf700-T_5);
          break;

      case 11: 
	  
	      servo_6=1;
          TH0=T_6>>8;
          TL0=T_6;
          break;

      case 12:
	  
	      servo_6=0;
          TH0=(0xf700-T_6)>>8;
          TL0=(0xf700-T_6);
          break;

      case 13: 
	  
	      servo_7=1;
          TH0=T_7>>8;
          TL0=T_7;
          break;

      case 14:
	  
	      servo_7=0;
          TH0=(0xf700-T_7)>>8;
          TL0=(0xf700-T_7);
          break;

      case 15: 
	  
	      servo_8=1;
          TH0=T_8>>8;
          TL0=T_8;
          break;

      case 16:
	  
	      servo_8=0;
          order_flag=0;
          TH0=(0xf700-T_8)>>8;
          TL0=(0xf700-T_8);
          break;
    }
    order_flag++;

}


/*****************************************************
                   串口中断程序
*****************************************************/
void ser_int (void) interrupt 4 using 1
{ 
    if(RI == 1)           //RI接受中断标志
    { 
	    RI = 0;		      //清除RI接受中断标志
				
	    ReData[i] = SBUF; //SUBF接受/发送缓冲器
		i++;
	    if(i==4&&ReData[0]==COMMAND)
		{
		   //ES=0;
		   if(ReData[1]     ==10) {KEY_A=0;Robot_EN=0;Quit=0;} //PC控制模式切换
	       else if(ReData[1]==11) {KEY_A=1;Robot_EN=0;Quit=0;}
	       else if(ReData[1]==12) {KEY_A=2;Robot_EN=0;Quit=0;}
		   else if(ReData[1]==13) {KEY_A=3;Robot_EN=0;Quit=0;}
		   else if(ReData[1]==14) {Robot_EN=1;}
		   else if(ReData[1]==15) {Robot_EN=0;}
		   else PCCommand=ReData[1];
		   i=0;
		   /*
		   SBUF=ReData[0];
		   while(!TI);
		   TI=0;
		   SBUF=ReData[1];
		   while(!TI);
		   TI=0;
		   SBUF=ReData[2];
		   while(!TI);
		   TI=0;
		   SBUF=ReData[3];
		   while(!TI);
		   TI=0;
		   //ES=1;
		   */
		}

	    else if(i==4&&ReData[0]==RGBVALUE)
		{  
		   //ES=0;
		   Target_R=ReData[1];  //PC控制模式切换
	       Target_G=ReData[2];
	       Target_B=ReData[3];
		   i=0;
		   /*
		   SBUF=ReData[0];
		   while(!TI);
		   TI=0;
		   SBUF=ReData[1];
		   while(!TI);
		   TI=0;
		   SBUF=ReData[2];
		   while(!TI);
		   TI=0;
		   SBUF=ReData[3];
		   while(!TI);
		   TI=0;
		   //ES=1;*/
		}
		
		else if(i>=4)i=0;	     
     }
}



评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

Edison钟

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值