查看: 2672|回复: 0
打印 上一主题 下一主题

自动循迹小车

[复制链接]
跳转到指定楼层
沙发
发表于 2015-5-13 08:30:42 | 只看该作者 回帖奖励 |倒序浏览 |阅读模式
山东大学课程设计—自动循迹小车 车体设计
方案1:购买玩具电动车。购买的玩具电动车具有组装完整的车架车轮、电机及其驱动电路。但是一般的说来,玩具电动车具有如下缺点:首先,这种玩具电动车由于装配紧凑,使得各种所需传感器的安装十分不方便。其次,这种电动车一般都是前轮转向后轮驱动,不能适应该题目的方格地图,不能方便迅速的实现原地保持坐标转90度甚至180度的弯角。再次,玩具电动车的电机多为玩具直流电机,力矩小,空载转速快,负载性能差,不易调速。而且这种电动车一般都价格不菲。因此我们放弃了此方案。
方案2:自己制作电动车。经过反复考虑论证,我们制定了左右两轮分别驱动,后万向轮转向的方案。即左右轮分别用两个转速和力矩基本完全相同的直流电机进行驱动,车体尾部装一个万向轮。这样,当两个直流电机转向相反同时转速相同时就可以实现电动车的原地旋转,由此可以轻松的实现小车坐标不变的90度和180度的转弯。
在安装时我们保证两个驱动电机同轴。当小车前进时,左右两驱动轮与后万向轮形成了三点结构。这种结构使得小车在前进时比较平稳,可以避免出现后轮过低而使左右两驱动轮驱动力不够的情况。为了防止小车重心的偏移,后万向轮起支撑作用。
对于车架材料的选择,我们经过比较选择了有机玻璃。用有机玻璃做的车架比塑料车架更加牢固,比铁制小车更轻便,美观。
综上考虑,我们选择了方案2。小车底盘如图1所示:
file:///C:/Users/admin/AppData/Local/Temp/msohtmlclip1/01/clip_image001.gif
电机选择:
最初我们在东明电子市场上买了两个旧电机,有计数脉冲,如下图所示:
file:///C:/Users/admin/AppData/Local/Temp/msohtmlclip1/01/clip_image002.jpg花费了30元的旧电机
file:///C:/Users/admin/AppData/Local/Temp/msohtmlclip1/01/clip_image003.jpg电机产生的脉冲
经过实际比较,我们发现电机的轴太短,根本无法固定轮子,并且其中有一个电机的轴有缺陷,轴上有一个凹槽。最终不得不放弃使用这个电机而去西门从新买了两个新的减速电机,如下图:
file:///C:/Users/admin/AppData/Local/Temp/msohtmlclip1/01/clip_image004.jpg
电机的固定采用的是铝合金直角垫片加铁丝捆绑的方式,这样做非常牢固,但是看起来不是很美观。
轮子方案:
在选定电机后,我们买了一个万向轮,万向轮的高度减去电机的半径就是驱动轮的半径。
轮子是在工程训练中心用尼龙棒在车床上作出来的,当时我们还戏称我们的小车是“机电一体化”的产品。
轮子的截面图:
file:///C:/Users/admin/AppData/Local/Temp/msohtmlclip1/01/clip_image005.gif
万向轮:
当小车前进时,左右两驱动轮与后万向轮形成了三点结构。这种结构使得小车在前进时比较平稳,可以避免出现后轮过低而使左右两驱动轮驱动力不够的情况。为了防止小车重心的偏移,后万向轮起支撑作用。并且可以轻松实现90度甚至180度原地转弯。
硬件设计
系统总设计电路图如下图,PDF格式Rrotel99格式
file:///C:/Users/admin/AppData/Local/Temp/msohtmlclip1/01/clip_image006.gif
各部分电路图及说明:
稳压电路:(上部分稳压至12V,下部分稳压至5V)
file:///C:/Users/admin/AppData/Local/Temp/msohtmlclip1/01/clip_image007.gif
L298电机控制驱动: 可以参考http://bbs.avrvi.com/read.php?tid=252&page=1&toread=1
file:///C:/Users/admin/AppData/Local/Temp/msohtmlclip1/01/clip_image008.gif
电压比较器电路(光电对管检测电路):
可调电阻R3可以调节比较器的门限电压,经示波器观察,输出波形相当规则,可以直接够单片机查询使用。而且经试验验证给此电路供电的电池的压降较小。因此我们选择此电路作为我们的传感器检测与调理电路。
file:///C:/Users/admin/AppData/Local/Temp/msohtmlclip1/01/clip_image009.jpg
实物与分析

电源电路:
由于本系统需要电池供电,我们考虑了如下几种方案为系统供电。
方案1: 采用10节1.5V干电池供电,电压达到15V,经7812稳压后给支流电机供电,然后将12V电压再次降压、稳压后给单片机系统和其他芯片供电。但干电池电量有限,使用大量的干电池给系统调试带来很大的不便,因此,我们放弃了这种方案。
方案2:采用3节4.2V可充电式锂电池串联共12.6V给直流电机供电,经过7812的电压变换后给支流电机供电,然后将12V电压再次降压、稳压后给单片机系统和其他芯片供电。锂电池的电量比较足,并且可以充电,重复利用,因此,这种方案比较可行。但锂电池的价格过于昂贵,使用锂电池会大大超出我们的预算,因此,我们放弃了这种方案。
方案3:采用12V蓄电池为直流电机供电,将12V电压降压、稳压后给单片机系统和其他芯片供电。蓄电池具有较强的电流驱动能力以及稳定的电压输出性能。虽然蓄电池的体积过于庞大,在小型电动车上使用极为不方便,但由于我们的车体设计时留出了足够的空间,并且蓄电池的价格比较低。因此我们选择了此方案。
综上考虑,我们选择了方案3。这个黑呼呼的东西,让我们可爱的小车变得很难看。
file:///C:/Users/admin/AppData/Local/Temp/msohtmlclip1/01/clip_image010.jpg
稳压模块:
方案1: 采用两片7812将电压稳压至12V后给直流电机供电,然后采用一片7809将电压稳定至9V,最后经7805将电压稳至5V,给单片机系统和其他芯片供电,但7809和7805压降过大,使7809和7805消耗的功率过大,导致7809和7805发热量过大,因此,我们放弃了这种方案。
方案2:采用两片7812将电压稳压至12V后给直流电机供电,然后采用2576将电压稳至5V。2576的输出电流最大可至3A,完全满足系统要求。
综上考虑,我们选择了方案2。 稳压模块如下图:
file:///C:/Users/admin/AppData/Local/Temp/msohtmlclip1/01/clip_image011.jpg(左图:稳压模块)
循迹传感器模块
方案1:用光敏电阻组成光敏探测器。光敏电阻的阻值可以跟随周围环境光线的变化而变化。当光线照射到白线上面时,光线发射强烈,光线照射到黑线上面时,光线发射较弱。因此光敏电阻在白线和黑线上方时,阻值会发生明显的变化。将阻值的变化值经过比较器就可以输出高低电平。
但是这种方案受光照影响很大,不能够稳定的工作。因此我们考虑其他更加稳定的方案。
方案2:用红外发射管和接收管自己制作光电对管寻迹传感器。红外发射管发出红外线,当发出的红外线照射到白色的平面后反射,若红外接收管能接收到反射回的光线则检测出白线继而输出低电平,若接收不到发射管发出的光线则检测出黑线继而输出高电平。这样自己制作组装的寻迹传感器基本能够满足要求,但是工作不够稳定,且容易受外界光线的影响,因此我们放弃了这个方案。
方案3:用RPR220型光电对管。RPR220是一种一体化反射型光电探测器,其发射器是一个砷化镓红外发光二极管,而接收器是一个高灵敏度,硅平面光电三极管。
RPR220采用DIP4封装,其具有如下特点:
·        塑料透镜可以提高灵敏度。
·        内置可见光过滤器能减小离散光的影响。
·        体积小,结构紧凑。
·        当发光二极管发出的光反射回来时,三极管导通输出低电平。此光电对管调理电路简单,工作性能稳定。
此我们选择了方案3。安装后效果如下图:
file:///C:/Users/admin/AppData/Local/Temp/msohtmlclip1/01/clip_image012.jpg
下图是电压比较器:
file:///C:/Users/admin/AppData/Local/Temp/msohtmlclip1/01/clip_image013.jpg
说明文件:
设计名称:循迹小车
时间:2006-12-9
关键词:Atemega32 L298 减速电机 光电对管 7812 7805
作者:古欣 朱岩 王智涌 原瑞花 喻巧群
/*********************************************************/
硬件资源分配1.0:12-9
PA0-PA5 光电对管检测
PB1,PB2,PB3 电机右 PB3为PWM
PB4,PB5,PD7 电机左 PD7为PWM
PD2 int0 码牌 行程检测
/********************************************************/
电机转向:
PB1 = 1
PB2 = 0 右电机前转
PB4 = 0
PB5 = 1 左电机前转
/********************************************************/
flag; //小车状态
//0未偏 1左偏 2右偏 3前出线 4后出线 5脱轨

主程序:

电机驱动程序:
/****************************************************************
** 文件名:motor.c   电机驱动函数
****************************************************************/
#include "config.h"
/************************左电机动作*****************************/
//左电机前进
void motor_left_forward(uint8speed)
{
motol_uen1;
motol_en2;
if(speed!=0) //加入调速指令
{
  OCR0=speed;
}
T0_EN;
}
//左电机后退
void motor_left_backward(uint8speed)
{
motol_en1;
motol_uen2;
if(speed!=0) //加入调速指令
{
  OCR0=speed;
}
T0_EN;
}
//左电机速度设定
void motor_left_speed_set(uint8speed)
{
if(speed!=0)
{
  OCR0=speed;
}
}
//左电机滑行
void motor_left_stop(void)
{
motol_uen1;
motol_uen2;
T0_UEN;
}
//左电机急停
void motor_left_quick_stop(void)
{
motol_en1;
motol_en2;
T0_UEN;
}
/*************************右电机动作*****************************/
//右电机前进
void motor_right_forward(uint8speed)
{
motor_en1;
motor_uen2;
if(speed!=0) //加入调速指令
{
  OCR2=speed;
  while(ASSR&(1<<TCR2UB)==1) ; //异步操作需要等待 OCR2写入完毕
}
T2_EN;
}
//右电机后退
void motor_right_backward(uint8speed)
{
motor_uen1;
motor_en2;
if(speed!=0) //加入调速指令
{
  OCR2=speed;
  while(ASSR&(1<<TCR2UB)==1) ; //异步操作需要等待 OCR2写入完毕
}
T2_EN;
}
//右电机速度设定
void motor_right_speed_set(uint8speed)
{
if(speed!=0)
{
  OCR0=speed;
  while(ASSR&(1<<TCR2UB)==1) ; //异步操作需要等待 OCR2写入完毕
}
}
//右电机滑行
void motor_right_stop(void)
{
motor_uen1;
motor_uen2;
T2_UEN;
}
//右电机急停
void motor_right_quick_stop(void)
{
motor_en1;
motor_en2;
T2_UEN;
}

延时程序:
/****************************************************************
** 文件名:unit.h   定时函数头文件
****************************************************************/
#ifndef _UNIT_H__
#define _UNIT_H__ 1  
//100us
extern void Delay100us(uint8 n);
//1s
extern void Delay1s(uint16 n);
//1ms
extern void Delay1ms(uint16 n);
#endif
/****************************************************************
** 文件名:unit.c   定时函数
****************************************************************/
#include "config.h"
/***************************************************************************
延时公式
*/
void Delay100us(uint8 n)
{
        uint8i;          //4clock                  
        for(i=147;n!=0;n--)   
        while(--i);      //5 * i clock
}
void Delay1ms(uint16 n)
{        
        for(;n!=0;n--){
               Delay100us(10);
        }
}
void Delay1s(uint16 n)
{
        n=n*40;               
        for(;n!=0;n--){
               Delay100us(250);
        }
}

工程定义头文件:
/****************************************************************
** 文件名:config.h   工程头文件定义
****************************************************************/
#ifndef __config_H__
#define __config_H__ 1
/*********************************************/
#define M8    1
#define M16   2
#define M32   3
#define M64   4
#define M128  5
/*********************************************/
#define CPU_TYPE  M32
//定义MCU时钟频率
//#define F_CPU14745600
#define F_CPU 7372800
//**************************************************
//包含系统头文件,请根据实际需要进行裁减
//**************************************************
//#pragma REGPARMS
#if CPU_TYPE == M128
#include <iom128v.h>
#endif
#if CPU_TYPE == M64
#include <iom64v.h>
#endif
#if CPU_TYPE == M32
#include <iom32v.h>
#endif
#if CPU_TYPE == M16
#include <iom16v.h>
#endif
#if CPU_TYPE == M8
#include <iom8v.h>
#endif
//#include<intrins.h>
//#include<absacc.h>
#include <string.h>
//#include<FLOAT.H>
//#include<math.h>
//#include<stdlib.h>
#include <macros.h>
//#include<eeprom.h>
//#define const code
//**************************************************
//系统数据类型定义
//**************************************************
#ifndef TRUE
#define TRUE  1
#endif
#ifndef FALSE
#define FALSE 0
#endif
#ifndef NULL
#define NULL 0
#endif
#define MIN(a,b)                      ((a<b)?(a)b))
#define MAX(a,b)                      ((a>b)?(a)b))
#define ABS(x)                        ((x>0)?(x)-x))
typedef unsigned char  uint8;                                   /* 定义可移植的无符号8位整数关键字            */
typedef signed   char int8;                                   /* 定义可移植的有符号8位整数关键字            */
typedef unsigned int   uint16;                                  /*定义可移植的无符号16位整数关键字           */
typedef signed   int  int16;                                  /* 定义可移植的有符号16位整数关键字           */
typedef unsigned long  uint32;                                  /* 定义可移植的无符号32位整数关键字           */
typedef signed   long int32;                                  /* 定义可移植的有符号32位整数关键字           */
//**************************************************
//包含工程头文件,请根据需要进行裁减
//**************************************************
#include "unit.h"
//#include "lcddrive.h"
#include "main.h"
#include "motor.h"
//#include"queue.h"
//#include"TWI.h"
//#include"sio.h"
//**************************************************
//一下为工程变量、端口定义
//**************************************************
/********************************/
/*     "以下为工程配置"         */
/********************************/
#define T0 used
//#define T1 used
#define T2 used
//#define Int0 used
//#define Int1 used
//计数器0比较计数中断允许
#if T0==used
#define T0_EN TIMSK |=(1<<OCIE0)|(1<<TOIE0)
#define T0_UEN TIMSK &=~(1<<OCIE0)|(1<<TOIE0)
#define T0_start TCCR0 |=(1<<WGM00)|(1<<WGM01)|(1<<COM01)|0x04;
//0x04 0100B 代表256预分频
#define T0_stop TCCR0 = 0x00
#endif
//计数器1定时中断允许//OVERflow
#if T1==used
#define T1_EN TIMSK |=(1<<TOIE1)|(1<<TOIE1)
#define T1_UEN TIMSK &=~(1<<TOIE1)|(1<<TOIE1)
#define T1_start TCCR1B = 0x02
#define T1_stop TCCR1B = 0x00
#endif
//定时器2允许,PWM输出
#if T2==used
#define T2_EN TIMSK |=(1<<OCIE2)|(1<<TOIE2)
#define T2_UEN TIMSK &=~(1<<OCIE2)|(1<<TOIE2)
#define T2_start TCCR2 = (1<<WGM20)|(1<<WGM21)|(1<<COM21)|0x06
#define T2_stop TCCR2 = 0x00
//start timer 快速pwm模式,匹配清零,溢出置位 256分频
//高比低为:(OCR2-0X55)/(0XFF-OCR2)   OX55++++++(0X77)__________OXFF
//即OCR2越大,输出越大
#endif
//外部中断T0
#if Int0==used
#define INT0_EN GICR |= (1<<INT0)
#define INT0_UEN GICR &=~ (1<<INT0)
#endif
//外部中断T1
#if Int1==used
#define INT1_EN GICR |= (1<<INT1)
#define INT1_UEN GICR &=~ (1<<INT1)
#endif
#endif
/**********************end****************************************/

/** moto test  电机运转情况测试程序*********************************************************
void main(void)
{
init_devices();
   straight();
    Delay1s(5);
   turn_left();
    Delay1s(5);
   turn_right();
    Delay1s(5);
   straight_back();
    Delay1s(5);
   stop();
while(1)
;
}
*******************************************************************************/

中断处理;(这里都是定时器比较匹配和溢出中断)
/*******************************************************************************
** 文件名:interupts.c   中断处理函数
*******************************************************************************/
#include "config.h"
#pragma interrupt_handlertimer0_ovf_isr:12
void timer0_ovf_isr(void)
{
TCNT0 = 0x01; //reloadcounter value
}
#pragma interrupt_handlertimer0_comp_isr:11
void timer0_comp_isr(void)
{
  //compare occured TCNT0=OCR0
}
#pragma interrupt_handlertimer2_ovf_isr:6
void timer2_ovf_isr(void)
{
TCNT2 = 0x01; //reloadcounter value
}
/******************************************************************************/
// T2 控制PWM输出
// timer2_comp_isr不需要用,但是必须允许中断,在中断时有信号输出变化
/******************************************************************************/
#pragma interrupt_handlertimer2_comp_isr:5
void timer2_comp_isr(void)
{
  //compare occured TCNT2=OCR2
}
小车图片展示
                    
                    
                    
                    
                    
                    
      
  
  
  
  
  
  
  
flash模拟行进路线
请点击开始查看行进情况:

路径图片:
file:///C:/Users/admin/AppData/Local/Temp/msohtmlclip1/01/clip_image075.gif
小车从发车区出发,按照预定的行进路线,完成后自动回到库区。
山东大学课程设计—自动循迹小车 车体设计
方案1:购买玩具电动车。购买的玩具电动车具有组装完整的车架车轮、电机及其驱动电路。但是一般的说来,玩具电动车具有如下缺点:首先,这种玩具电动车由于装配紧凑,使得各种所需传感器的安装十分不方便。其次,这种电动车一般都是前轮转向后轮驱动,不能适应该题目的方格地图,不能方便迅速的实现原地保持坐标转90度甚至180度的弯角。再次,玩具电动车的电机多为玩具直流电机,力矩小,空载转速快,负载性能差,不易调速。而且这种电动车一般都价格不菲。因此我们放弃了此方案。
方案2:自己制作电动车。经过反复考虑论证,我们制定了左右两轮分别驱动,后万向轮转向的方案。即左右轮分别用两个转速和力矩基本完全相同的直流电机进行驱动,车体尾部装一个万向轮。这样,当两个直流电机转向相反同时转速相同时就可以实现电动车的原地旋转,由此可以轻松的实现小车坐标不变的90度和180度的转弯。
在安装时我们保证两个驱动电机同轴。当小车前进时,左右两驱动轮与后万向轮形成了三点结构。这种结构使得小车在前进时比较平稳,可以避免出现后轮过低而使左右两驱动轮驱动力不够的情况。为了防止小车重心的偏移,后万向轮起支撑作用。
对于车架材料的选择,我们经过比较选择了有机玻璃。用有机玻璃做的车架比塑料车架更加牢固,比铁制小车更轻便,美观。
综上考虑,我们选择了方案2。小车底盘如图1所示:
file:///C:/Users/admin/AppData/Local/Temp/msohtmlclip1/01/clip_image001.gif
电机选择:
最初我们在东明电子市场上买了两个旧电机,有计数脉冲,如下图所示:
file:///C:/Users/admin/AppData/Local/Temp/msohtmlclip1/01/clip_image002.jpg花费了30元的旧电机
file:///C:/Users/admin/AppData/Local/Temp/msohtmlclip1/01/clip_image003.jpg电机产生的脉冲
经过实际比较,我们发现电机的轴太短,根本无法固定轮子,并且其中有一个电机的轴有缺陷,轴上有一个凹槽。最终不得不放弃使用这个电机而去西门从新买了两个新的减速电机,如下图:
file:///C:/Users/admin/AppData/Local/Temp/msohtmlclip1/01/clip_image004.jpg
电机的固定采用的是铝合金直角垫片加铁丝捆绑的方式,这样做非常牢固,但是看起来不是很美观。
轮子方案:
在选定电机后,我们买了一个万向轮,万向轮的高度减去电机的半径就是驱动轮的半径。
轮子是在工程训练中心用尼龙棒在车床上作出来的,当时我们还戏称我们的小车是“机电一体化”的产品。
轮子的截面图:
file:///C:/Users/admin/AppData/Local/Temp/msohtmlclip1/01/clip_image005.gif
万向轮:
当小车前进时,左右两驱动轮与后万向轮形成了三点结构。这种结构使得小车在前进时比较平稳,可以避免出现后轮过低而使左右两驱动轮驱动力不够的情况。为了防止小车重心的偏移,后万向轮起支撑作用。并且可以轻松实现90度甚至180度原地转弯。
硬件设计
系统总设计电路图如下图,PDF格式Rrotel99格式
file:///C:/Users/admin/AppData/Local/Temp/msohtmlclip1/01/clip_image006.gif
各部分电路图及说明:
稳压电路:(上部分稳压至12V,下部分稳压至5V)
file:///C:/Users/admin/AppData/Local/Temp/msohtmlclip1/01/clip_image007.gif
L298电机控制驱动: 可以参考http://bbs.avrvi.com/read.php?tid=252&page=1&toread=1
file:///C:/Users/admin/AppData/Local/Temp/msohtmlclip1/01/clip_image008.gif
电压比较器电路(光电对管检测电路):
可调电阻R3可以调节比较器的门限电压,经示波器观察,输出波形相当规则,可以直接够单片机查询使用。而且经试验验证给此电路供电的电池的压降较小。因此我们选择此电路作为我们的传感器检测与调理电路。
file:///C:/Users/admin/AppData/Local/Temp/msohtmlclip1/01/clip_image009.jpg
实物与分析

电源电路:
由于本系统需要电池供电,我们考虑了如下几种方案为系统供电。
方案1: 采用10节1.5V干电池供电,电压达到15V,经7812稳压后给支流电机供电,然后将12V电压再次降压、稳压后给单片机系统和其他芯片供电。但干电池电量有限,使用大量的干电池给系统调试带来很大的不便,因此,我们放弃了这种方案。
方案2:采用3节4.2V可充电式锂电池串联共12.6V给直流电机供电,经过7812的电压变换后给支流电机供电,然后将12V电压再次降压、稳压后给单片机系统和其他芯片供电。锂电池的电量比较足,并且可以充电,重复利用,因此,这种方案比较可行。但锂电池的价格过于昂贵,使用锂电池会大大超出我们的预算,因此,我们放弃了这种方案。
方案3:采用12V蓄电池为直流电机供电,将12V电压降压、稳压后给单片机系统和其他芯片供电。蓄电池具有较强的电流驱动能力以及稳定的电压输出性能。虽然蓄电池的体积过于庞大,在小型电动车上使用极为不方便,但由于我们的车体设计时留出了足够的空间,并且蓄电池的价格比较低。因此我们选择了此方案。
综上考虑,我们选择了方案3。这个黑呼呼的东西,让我们可爱的小车变得很难看。
file:///C:/Users/admin/AppData/Local/Temp/msohtmlclip1/01/clip_image010.jpg
稳压模块:
方案1: 采用两片7812将电压稳压至12V后给直流电机供电,然后采用一片7809将电压稳定至9V,最后经7805将电压稳至5V,给单片机系统和其他芯片供电,但7809和7805压降过大,使7809和7805消耗的功率过大,导致7809和7805发热量过大,因此,我们放弃了这种方案。
方案2:采用两片7812将电压稳压至12V后给直流电机供电,然后采用2576将电压稳至5V。2576的输出电流最大可至3A,完全满足系统要求。
综上考虑,我们选择了方案2。 稳压模块如下图:
file:///C:/Users/admin/AppData/Local/Temp/msohtmlclip1/01/clip_image011.jpg(左图:稳压模块)
循迹传感器模块
方案1:用光敏电阻组成光敏探测器。光敏电阻的阻值可以跟随周围环境光线的变化而变化。当光线照射到白线上面时,光线发射强烈,光线照射到黑线上面时,光线发射较弱。因此光敏电阻在白线和黑线上方时,阻值会发生明显的变化。将阻值的变化值经过比较器就可以输出高低电平。
但是这种方案受光照影响很大,不能够稳定的工作。因此我们考虑其他更加稳定的方案。
方案2:用红外发射管和接收管自己制作光电对管寻迹传感器。红外发射管发出红外线,当发出的红外线照射到白色的平面后反射,若红外接收管能接收到反射回的光线则检测出白线继而输出低电平,若接收不到发射管发出的光线则检测出黑线继而输出高电平。这样自己制作组装的寻迹传感器基本能够满足要求,但是工作不够稳定,且容易受外界光线的影响,因此我们放弃了这个方案。
方案3:用RPR220型光电对管。RPR220是一种一体化反射型光电探测器,其发射器是一个砷化镓红外发光二极管,而接收器是一个高灵敏度,硅平面光电三极管。
RPR220采用DIP4封装,其具有如下特点:
·        塑料透镜可以提高灵敏度。
·        内置可见光过滤器能减小离散光的影响。
·        体积小,结构紧凑。
·        当发光二极管发出的光反射回来时,三极管导通输出低电平。此光电对管调理电路简单,工作性能稳定。
此我们选择了方案3。安装后效果如下图:
file:///C:/Users/admin/AppData/Local/Temp/msohtmlclip1/01/clip_image012.jpg
下图是电压比较器:
file:///C:/Users/admin/AppData/Local/Temp/msohtmlclip1/01/clip_image013.jpg
说明文件:
设计名称:循迹小车
时间:2006-12-9
关键词:Atemega32 L298 减速电机 光电对管 7812 7805
作者:古欣 朱岩 王智涌 原瑞花 喻巧群
/*********************************************************/
硬件资源分配1.0:12-9
PA0-PA5 光电对管检测
PB1,PB2,PB3 电机右 PB3为PWM
PB4,PB5,PD7 电机左 PD7为PWM
PD2 int0 码牌 行程检测
/********************************************************/
电机转向:
PB1 = 1
PB2 = 0 右电机前转
PB4 = 0
PB5 = 1 左电机前转
/********************************************************/
flag; //小车状态
//0未偏 1左偏 2右偏 3前出线 4后出线 5脱轨

主程序:

电机驱动程序:
/****************************************************************
** 文件名:motor.c   电机驱动函数
****************************************************************/
#include "config.h"
/************************左电机动作*****************************/
//左电机前进
void motor_left_forward(uint8speed)
{
motol_uen1;
motol_en2;
if(speed!=0) //加入调速指令
{
  OCR0=speed;
}
T0_EN;
}
//左电机后退
void motor_left_backward(uint8speed)
{
motol_en1;
motol_uen2;
if(speed!=0) //加入调速指令
{
  OCR0=speed;
}
T0_EN;
}
//左电机速度设定
void motor_left_speed_set(uint8speed)
{
if(speed!=0)
{
  OCR0=speed;
}
}
//左电机滑行
void motor_left_stop(void)
{
motol_uen1;
motol_uen2;
T0_UEN;
}
//左电机急停
void motor_left_quick_stop(void)
{
motol_en1;
motol_en2;
T0_UEN;
}
/*************************右电机动作*****************************/
//右电机前进
void motor_right_forward(uint8speed)
{
motor_en1;
motor_uen2;
if(speed!=0) //加入调速指令
{
  OCR2=speed;
  while(ASSR&(1<<TCR2UB)==1) ; //异步操作需要等待 OCR2写入完毕
}
T2_EN;
}
//右电机后退
void motor_right_backward(uint8speed)
{
motor_uen1;
motor_en2;
if(speed!=0) //加入调速指令
{
  OCR2=speed;
  while(ASSR&(1<<TCR2UB)==1) ; //异步操作需要等待 OCR2写入完毕
}
T2_EN;
}
//右电机速度设定
void motor_right_speed_set(uint8speed)
{
if(speed!=0)
{
  OCR0=speed;
  while(ASSR&(1<<TCR2UB)==1) ; //异步操作需要等待 OCR2写入完毕
}
}
//右电机滑行
void motor_right_stop(void)
{
motor_uen1;
motor_uen2;
T2_UEN;
}
//右电机急停
void motor_right_quick_stop(void)
{
motor_en1;
motor_en2;
T2_UEN;
}

延时程序:
/****************************************************************
** 文件名:unit.h   定时函数头文件
****************************************************************/
#ifndef _UNIT_H__
#define _UNIT_H__ 1  
//100us
extern void Delay100us(uint8 n);
//1s
extern void Delay1s(uint16 n);
//1ms
extern void Delay1ms(uint16 n);
#endif
/****************************************************************
** 文件名:unit.c   定时函数
****************************************************************/
#include "config.h"
/***************************************************************************
延时公式
*/
void Delay100us(uint8 n)
{
        uint8i;          //4clock                  
        for(i=147;n!=0;n--)   
        while(--i);      //5 * i clock
}
void Delay1ms(uint16 n)
{        
        for(;n!=0;n--){
               Delay100us(10);
        }
}
void Delay1s(uint16 n)
{
        n=n*40;               
        for(;n!=0;n--){
               Delay100us(250);
        }
}

工程定义头文件:
/****************************************************************
** 文件名:config.h   工程头文件定义
****************************************************************/
#ifndef __config_H__
#define __config_H__ 1
/*********************************************/
#define M8    1
#define M16   2
#define M32   3
#define M64   4
#define M128  5
/*********************************************/
#define CPU_TYPE  M32
//定义MCU时钟频率
//#define F_CPU14745600
#define F_CPU 7372800
//**************************************************
//包含系统头文件,请根据实际需要进行裁减
//**************************************************
//#pragma REGPARMS
#if CPU_TYPE == M128
#include <iom128v.h>
#endif
#if CPU_TYPE == M64
#include <iom64v.h>
#endif
#if CPU_TYPE == M32
#include <iom32v.h>
#endif
#if CPU_TYPE == M16
#include <iom16v.h>
#endif
#if CPU_TYPE == M8
#include <iom8v.h>
#endif
//#include<intrins.h>
//#include<absacc.h>
#include <string.h>
//#include<FLOAT.H>
//#include<math.h>
//#include<stdlib.h>
#include <macros.h>
//#include<eeprom.h>
//#define const code
//**************************************************
//系统数据类型定义
//**************************************************
#ifndef TRUE
#define TRUE  1
#endif
#ifndef FALSE
#define FALSE 0
#endif
#ifndef NULL
#define NULL 0
#endif
#define MIN(a,b)                      ((a<b)?(a)b))
#define MAX(a,b)                      ((a>b)?(a)b))
#define ABS(x)                        ((x>0)?(x)-x))
typedef unsigned char  uint8;                                   /* 定义可移植的无符号8位整数关键字            */
typedef signed   char int8;                                   /* 定义可移植的有符号8位整数关键字            */
typedef unsigned int   uint16;                                  /*定义可移植的无符号16位整数关键字           */
typedef signed   int  int16;                                  /* 定义可移植的有符号16位整数关键字           */
typedef unsigned long  uint32;                                  /* 定义可移植的无符号32位整数关键字           */
typedef signed   long int32;                                  /* 定义可移植的有符号32位整数关键字           */
//**************************************************
//包含工程头文件,请根据需要进行裁减
//**************************************************
#include "unit.h"
//#include "lcddrive.h"
#include "main.h"
#include "motor.h"
//#include"queue.h"
//#include"TWI.h"
//#include"sio.h"
//**************************************************
//一下为工程变量、端口定义
//**************************************************
/********************************/
/*     "以下为工程配置"         */
/********************************/
#define T0 used
//#define T1 used
#define T2 used
//#define Int0 used
//#define Int1 used
//计数器0比较计数中断允许
#if T0==used
#define T0_EN TIMSK |=(1<<OCIE0)|(1<<TOIE0)
#define T0_UEN TIMSK &=~(1<<OCIE0)|(1<<TOIE0)
#define T0_start TCCR0 |=(1<<WGM00)|(1<<WGM01)|(1<<COM01)|0x04;
//0x04 0100B 代表256预分频
#define T0_stop TCCR0 = 0x00
#endif
//计数器1定时中断允许//OVERflow
#if T1==used
#define T1_EN TIMSK |=(1<<TOIE1)|(1<<TOIE1)
#define T1_UEN TIMSK &=~(1<<TOIE1)|(1<<TOIE1)
#define T1_start TCCR1B = 0x02
#define T1_stop TCCR1B = 0x00
#endif
//定时器2允许,PWM输出
#if T2==used
#define T2_EN TIMSK |=(1<<OCIE2)|(1<<TOIE2)
#define T2_UEN TIMSK &=~(1<<OCIE2)|(1<<TOIE2)
#define T2_start TCCR2 = (1<<WGM20)|(1<<WGM21)|(1<<COM21)|0x06
#define T2_stop TCCR2 = 0x00
//start timer 快速pwm模式,匹配清零,溢出置位 256分频
//高比低为:(OCR2-0X55)/(0XFF-OCR2)   OX55++++++(0X77)__________OXFF
//即OCR2越大,输出越大
#endif
//外部中断T0
#if Int0==used
#define INT0_EN GICR |= (1<<INT0)
#define INT0_UEN GICR &=~ (1<<INT0)
#endif
//外部中断T1
#if Int1==used
#define INT1_EN GICR |= (1<<INT1)
#define INT1_UEN GICR &=~ (1<<INT1)
#endif
#endif
/**********************end****************************************/

/** moto test  电机运转情况测试程序*********************************************************
void main(void)
{
init_devices();
   straight();
    Delay1s(5);
   turn_left();
    Delay1s(5);
   turn_right();
    Delay1s(5);
   straight_back();
    Delay1s(5);
   stop();
while(1)
;
}
*******************************************************************************/

中断处理;(这里都是定时器比较匹配和溢出中断)
/*******************************************************************************
** 文件名:interupts.c   中断处理函数
*******************************************************************************/
#include "config.h"
#pragma interrupt_handlertimer0_ovf_isr:12
void timer0_ovf_isr(void)
{
TCNT0 = 0x01; //reloadcounter value
}
#pragma interrupt_handlertimer0_comp_isr:11
void timer0_comp_isr(void)
{
  //compare occured TCNT0=OCR0
}
#pragma interrupt_handlertimer2_ovf_isr:6
void timer2_ovf_isr(void)
{
TCNT2 = 0x01; //reloadcounter value
}
/******************************************************************************/
// T2 控制PWM输出
// timer2_comp_isr不需要用,但是必须允许中断,在中断时有信号输出变化
/******************************************************************************/
#pragma interrupt_handlertimer2_comp_isr:5
void timer2_comp_isr(void)
{
  //compare occured TCNT2=OCR2
}
小车图片展示
                    
                    
                    
                    
                    
                    
      
  
  
  
  
  
  
  
flash模拟行进路线
请点击开始查看行进情况:

路径图片:

小车从发车区出发,按照预定的行进路线,完成后自动回到库区。

回复

使用道具 举报

您需要登录后才可以回帖 登录 | 加入中科因仑

本版积分规则

快速回复 返回顶部 返回列表