刚刚做好的红外寻线小车,由四路避障小车改变而来,有视频,图片【恢复】
原理完全同红外避障,区别是传感器的位置不同,程序略做修改.我用洞洞板固定红外反射传感器,红外线发射管用稍长热缩套管,目的是限制发射角度,可根据轨迹线的宽度和传感器高度而定.
发射功率的调整是调节38khz载波的占空比,不需要改变电阻,而直接使用固定电阻,可靠性大大提高.现在我设置的占空比是12.5%,发射电流不变,1.5ma,黑线用的是电工胶带,强烈吸收光线.白线就是地板.
从实验效果看,3个传感器的安装位置相对黑线宽度过大,另外程序也很简陋,这引起小车左右调节幅度较大.
视频地址:
http://player.youku.com/player.php/sid/16367883/v.swf
http://cache.amobbs.com/bbs_upload782111/files_11/ourdev_582084.JPG
(原文件名:PICT0757.JPG)
http://cache.amobbs.com/bbs_upload782111/files_11/ourdev_582085.JPG
(原文件名:PICT0758.JPG) 程序由四路避障程序修改而成,连变量名称都没改.前,左,后避障传感器现在对应中,右,左三路寻线传感器.
#include <stdio.h>
#include <intrins.h>
#include "STC12C5410AD.H"
#include "sio.h"
#define MIN9MS 0x0120 //9ms中心是0x0159
#define MAX9MS 0x01a0
#define MIN45MS 0x0090 //4.5ms中心是0x00ac
#define MAX45MS 0x00d0
#define MIN225MS 0x0040 //2.25ms中心是0x0056
#define MAX225MS 0x0080
#define MIN056MS 0x000e //0.56ms中心是0x0015
#define MAX056MS 0x001b
#define MIN168MS 0x0020 //1.68ms中心是0x0040
#define MAX168MS 0x0060
sfr ISP_CUNTR = 0xE7;
sbit LED1 = P1^1;
sbit LED2 = P1^2;
sbit IR_FRONT = P3^3;
sbit IR_LEFT = P3^4;
sbit IR_RIGHT = P3^5;
sbit IR_BACK = P1^3;
sbit IR_OUT = P1^0;
sbit PWM0 = P3^7;
sbit MOTO_IN_A1 = P1^7;
sbit MOTO_IN_A2 = P1^6;
sbit MOTO_IN_B1 = P1^5;
sbit MOTO_IN_B2 = P1^4;
bit power_stat;
static unsigned char car_stat; //小车状态:0,停止;1,前进;2,后退;3,左转;4,右转;ff,自控寻线模式
static unsigned char code led_mod_table = {
{1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0},
{1,0,0,0,1,0,0,0,1,0,0,0,1,0,0,0,1,0,0,0},
{1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0}
};
unsigned char idata led_mod = 0;
static unsigned char idata led_tick = 0;
static unsigned char idata led_ptr = 0;
#define IR_SIGNAL_TOTAL 21
#define IR_SIGNAL_VALID 18
static unsigned char code ir_table = {
1,1,1,0,0,0,0,0,0,1,1,1,1,0,0,0,0,0,0,0,0
};
static unsigned char code ir_check_table = {
0,0,0,0,1,1,1,0,0,0,0,0,0,1,1,1,1,0,0,0,0
};
static unsigned char idata ir_ptr = 0;
static unsigned char idata front_signal = 0;
static unsigned char idata back_signal = 0;
static unsigned char idata left_signal = 0;
static unsigned char idata right_signal = 0;
static bit front_obj = 0, back_obj = 0, left_obj = 0, right_obj = 0;
static void delay(unsigned long v) {
while (v--) {
}
}
/*
* PCA中断计数,根据位置判断信号区域和定义,位置0表示初始,1代表引导码信号,2表示引导码间隔,
* 3表示第一个bit的信号,4表示第一个bit的间隔,以次类推...
* 更具体见对应的红外线协议.
*/
static unsigned char idata pca_tick;
static unsigned char idata pca_int_count;
static unsigned char data pca_int_total; /* 根据引导头确定总长度 */
static unsigned int idata period; /* 红外信号占或空周期计数 */
static unsigned char idata data_buf; /* 红外线协议数据缓冲区 */
static unsigned int idata ccap1; //PCA0上一次的的计数
static unsigned char idata frame_dog; //红外帧看门狗,限定时间未接收完成清除工作
void time0_isr() interrupt 1
{
unsigned char tmp;
if (ir_table) {
IR_OUT = 0;
} else {
IR_OUT = 1;
}
ir_ptr %= IR_SIGNAL_TOTAL;
tmp = ir_check_table;
if ((!IR_FRONT && tmp) || (IR_FRONT && !tmp))
front_signal++;
if ((!IR_LEFT && tmp) || (IR_LEFT && !tmp))
left_signal++;
if ((!IR_RIGHT && tmp) || (IR_RIGHT && !tmp))
right_signal++;
if ((!IR_BACK && tmp) || (IR_BACK && !tmp))
back_signal++;
if (ir_ptr == 0) {
// com_putchar(front_signal);
if (front_signal>= IR_SIGNAL_VALID)
front_obj = 1;
else
front_obj = 0;
if (back_signal>= IR_SIGNAL_VALID)
back_obj = 1;
else
back_obj = 0;
if (left_signal>= IR_SIGNAL_VALID)
left_obj = 1;
else
left_obj = 0;
if (right_signal>= IR_SIGNAL_VALID)
right_obj = 1;
else
right_obj = 0;
front_signal = 0;
back_signal = 0;
left_signal = 0;
right_signal = 0;
}
}
void time0_initialize(void)
{
TMOD &= ~0x0F; /* clear timer 0 mode bits */
TMOD |= 0x02; /* put timer 0 into MODE 2 */
TH0 = 0x5C; /* 256 - XTAL*dur/T1_12/1000000, dur=定时器的周期,以us为单位*/
TL0 = 0x5C; /* 100us */
PT0 = 0; /* 时钟0中断低优先级 */
TR0 = 1;
ET0 = 1;
}
static void wakeup (void) interrupt 2
{
}
static void pca_isr (void) interrupt 6
{
unsigned char i, j;
if (CCF1) {
CCF1 = 0; //清PCA1中断标志
LED1 = IR_RIGHT;
LED2 = IR_RIGHT;
if (!pca_int_count) { //第一次收到信号
if (!IR_RIGHT) {
ccap1 = pca_tick * 256 + CCAP1H;
pca_int_count++;
}
} else { //已经收到一些信号
period = pca_tick * 256 + CCAP1H - ccap1;
ccap1 = pca_tick * 256 + CCAP1H;
//com_putchar(period / 256);
//com_putchar(period % 256);
if (pca_int_count == 1) {
if (period < MIN9MS || period> MAX9MS) { //9ms
pca_int_count = 0;
frame_dog = 0;
} else
pca_int_count++;
} else if (pca_int_count == 2) {
if (period> MIN225MS && period < MAX225MS) { //2.25ms
pca_int_total = 3;
pca_int_count++;
} else if (period> MIN45MS && period < MAX45MS) { //4.5ms
pca_int_total = 67;
pca_int_count++;
} else {
pca_int_count = 0;
frame_dog = 0;
}
} else {
if (IR_RIGHT) {
if (period> MIN056MS && period < MAX056MS) { //0.56ms
if (pca_int_count>= pca_int_total) { //帧接收完毕,下面进行有效性分析.
if (pca_int_total == 67) { //完整信号,含有引导信号,设备码8bit,设备反码8bit,命令字8bit,命令字反码8bit
if ((data_buf ^ data_buf == 0xff) && (data_buf ^ data_buf == 0xff)) {
com_putchar(data_buf);
com_putchar(data_buf);
if (data_buf == 0x40) {
switch (data_buf) {
case 0x5F: //左
car_stat = 3;
break;
case 0x5B: //右
car_stat = 4;
break;
case 0x5A: //上
car_stat = 1;
break;
case 0x5E: //下
car_stat = 2;
break;
case 0x56: //菜单
car_stat = 0;
break;
case 0x0: //数字0
car_stat = 0xff;
break;
case 0x12: //POWER
// power_stat = ~power_stat;
break;
default:
break;
}
}
}
} else { //重复信号,仅含有引导信号
}
pca_int_count = 0;
frame_dog = 0;
} else {
pca_int_count++;
}
} else {
pca_int_count = 0;
frame_dog = 0;
}
} else {
j = (pca_int_count - 3) / 2;
i = j / 8;
j = j % 8;
if (period> MIN168MS && period < MAX168MS) { //1.68ms
// com_putchar(0x01);
data_buf |= (0x01 << j);
pca_int_count++;
} else if (period> MIN056MS && period < MAX056MS) { //0.56ms
// com_putchar(0x00);
data_buf &= ~(0x01 << j);
pca_int_count++;
} else {
pca_int_count = 0;
frame_dog = 0;
}
}
}
}
}
if (CF) { //PCA计数溢出中断,19.6608MHZ晶体大约6.7ms溢出
CF = 0;
pca_tick++;
if (led_tick++>= 10) {
led_tick = 0;
if (led_mod_table) {
LED1 = 0;
LED2 = 0;
} else {
LED1 = 1;
LED2 = 1;
}
led_ptr %= 20;
}
if (pca_int_count) {
frame_dog++;
if (frame_dog>= 15) { //100ms后重新开始分析新的红外线数据包
pca_int_count = 0;
frame_dog = 0;
}
}
}
}
void auto_power_down() {
delay(30000);
ISP_CUNTR = 0x20; //从AP复位并从AP执行
}
void main (void)
{
unsigned char i;
unsigned long j;
MOTO_IN_A1 = 0;
MOTO_IN_A2 = 0;
MOTO_IN_B1 = 0;
MOTO_IN_B2 = 0;
P1M1 = 0xf0; //P1.7~P1.4 强推挽输出
EA = 0;
power_stat = 0;
time0_initialize();
com_initialize (); /* initialize interrupt driven serial I/O */
com_baudrate (4800); /* setup for 1200 baud */
/*
CMOD = 0x01; // #00000000B,PCA空闲计数,PCA计数源=Fosc/12,PCA溢出中断(做一个定时器使用)
CCON = 0x00; //PCA中断标志清0,PCA停止计数
CL = 0x0;
CH = 0x0;
CCAPM1 = 0x31; //PCA1上升下降沿捕获
*/
CMOD = 0x03; /* #00000010B,PCA空闲计数,PCA计数源=fosc/2,PCA溢出中断 */
CCON = 0x00; //PCA中断标志清0,PCA停止计数
CL = 0x0;
CH = 0x0;
CCAPM1 = 0x31; //PCA1上升下降沿捕获
CCAPM0 = 0x42; //PCA0工作模式:8位pwm
PCA_PWM0 = 0x00;
CCAP0L = 0x20;
CCAP0H = 0x20;
EPCA_LVD = 1; //允许PCA和低压检测中断
car_stat = 0;
pca_tick = 0;
pca_int_count = 0;
frame_dog = 0;
EA = 1; /* Enable Interrupts */
CR = 1; //启动PCA计数
while (1)
{
if (power_stat) {
// auto_power_down();
}
if (left_obj || right_obj || front_obj || back_obj) {
LED1 = 0;
LED2 = 0;
}
switch (car_stat) {
case 0:
MOTO_IN_A1 = 0;
MOTO_IN_A2 = 0;
MOTO_IN_B1 = 0;
MOTO_IN_B2 = 0;
break;
case 0xff:
if (!front_obj) { //中线传感器检测到黑线
MOTO_IN_A1 = 1;
MOTO_IN_A2 = 0;
MOTO_IN_B1 = 1;
MOTO_IN_B2 = 0;
j = 50000;
while (j) {
j--;
if (front_obj)
break;
}
} else {
TURNLEFT:
MOTO_IN_A1 = 0;
MOTO_IN_A2 = 1;
MOTO_IN_B1 = 1;
MOTO_IN_B2 = 0;
j = 1000000;
while (1) {
j--;
if (!front_obj) {
goto EXIT;
}
if (!left_obj)
goto TURNLEFT;
if (!back_obj)
goto TURNRIGHT;
if (j == 0)
goto EXIT;
}
TURNRIGHT:
MOTO_IN_A1 = 1;
MOTO_IN_A2 = 0;
MOTO_IN_B1 = 0;
MOTO_IN_B2 = 1;
j = 1000000;
while (j) {
j--;
if (!front_obj)
goto EXIT;
if (!back_obj)
goto TURNRIGHT;
if (!left_obj)
goto TURNLEFT;
}
}
EXIT:
/*
MOTO_IN_A1 = 0;
MOTO_IN_A2 = 0;
MOTO_IN_B1 = 0;
MOTO_IN_B2 = 0;
delay(5000);
*/
break;
default:
break;
}
PCON |= 0x01;
}
} UP,这等好帖没人顶 牛, 这么快就做好了 电路图完全同四路避障,本来就是这个板开发的.区别只是传感器安装位置.电路图在另外一个贴子里,再引用一下.
<br>点击此处下载 ourdev_566183.pdf(文件大小:51K) (原文件名:四路避障主板.pdf)
<br>点击此处下载 ourdev_566184.pdf(文件大小:37K) (原文件名:红外避障模块.pdf) </font> 收藏了 不错不错,收藏 看看 请问你的电机是怎么进行调试的。。达到什么要求就可以了 不错,谢谢分享!! 谢谢分享. 谢谢分享. 我顶……
这么全的资料上哪找,唯有兄台此处可寻! 谢谢无私分享.............. 电路图已经传上去了.阿莫现在太忙. 顶起,要COOL。 顶 支持楼主,有电路图就好了,可以自己做来玩一下。 LZ :红外反射传感器什么型号?哪有卖的,找好久了都没找到,只能用TCRT5000做了 帮顶 应该置COOL 置顶~!~!~!~1
谢谢楼主分享~!~! 太牛了顶 mark,轮子不错 谢谢分享很好很强大 牛逼。我很是欣赏,最近我们也要做小车了希望能有帮助。 收藏,不错哦 好东西 顶先 顶起 不错~做个试下~ 牛人啊 恩!强汉,谢谢楼主,收藏了...... mark 大家都到开源雕刻机了
不过这个帖子一定要顶的,虽然现在还不是很懂 额。。。。砸了不少钱 顶一个 回复【楼主位】ct_dev
-----------------------------------------------------------------------
刚欣赏了尊驾的小车,很cool!!, 小弟有一问题请教,反射回来的38K的红外信号放大后是如何给单片机的?直接接上么? 0,1分别是有或者无障碍的话,那么放大后的0101...的脉冲红外的信号,单片机是识别为有还是识别为没有障碍呢? 红外部分尊驾是怎么做的? 求解答. 回复【36楼】kingkrosson
-----------------------------------------------------------------------
我采用的方法是:
发射特定信号:如 001100111000111...之类的周期信号,边发射边检测接收信号,简单的计算匹配程度,达到某个阀值就认为有障碍.实际有效的是检测1的数量,编码目的是避免接收头的防干扰过滤机制. 做出来困难吗 顶起~! 改天也来制作一个 好车 NB顶一下 在这里找到了LZ的代码, 前期买了LZ的备件, 忘记买这个小车了. 回复【43楼】qiushui
在这里找到了LZ的代码, 前期买了LZ的备件, 忘记买这个小车了.
-----------------------------------------------------------------------
不好意思,小店没打理好,东西不显眼.
http://cache.amobbs.com/bbs_upload782111/files_28/ourdev_543919.jpg
(原文件名:三轮小车(橡胶万向轮).jpg)
新做的三轮小车,双轴承橡胶万向轮,噪音小,转弯实在太灵活了.这次用光敏三极管做的寻线,明显运行光滑流畅很多.
视频:
避障视频(4节充电电池供电):
http://v.youku.com/v_show/id_XMTQ3ODY2MzMy.html
寻线视频:
http://v.youku.com/v_show/id_XMTUwMjQwNDAw.html 电路板可以放在车体内吗? 回复【46楼】wj851127
电路板可以放在车体内吗?
-----------------------------------------------------------------------
做得小的话可以的.其实把电池放进车体内更好,重心降低了稳,太高了方向突变会翘头. 学习 不错 回复【37楼】ct_dev
-----------------------------------------------------------------------
楼主你好,做的小车很精致,我想问下,你用的是红外发射管和一体化就收头吧,一体化就收好像只对38k的信号有反应,那你的单片机发送的信号时38k否,接收又是怎么判定的啊?我菜鸟,你和36楼解释的我不太明白,谢谢了。 回复【50楼】zeunike
回复【37楼】ct_dev
-----------------------------------------------------------------------
楼主你好,做的小车很精致,我想问下,你用的是红外发射管和一体化就收头吧,一体化就收好像只对38k的信号有反应,那你的单片机发送的信号时38k否,接收又是怎么判定的啊?我菜鸟,你和36楼解释的我不太明白,谢谢了。
-----------------------------------------------------------------------
单片机产生的是38k左右的载波,然后按脉宽发送数据.接收头收到的是低电平的脉宽.注意接收头有最小周期和最小脉宽,最大脉宽限制,具体看datasheet. 好铁,有分量,得顶
必须的! 采用楼主的淘宝店卖的该三轮小车进行本校区内部的小车比赛,一个月下来 ,对这个车有些许体会,包括跟圆梦小车与98元四轮车进行对比。先上几张测试版的图,板子坐的比较丑,但是跑起来比较流畅,硬件电路也特别少,最重要是程序怎么调~
http://cache.amobbs.com/bbs_upload782111/files_28/ourdev_550346.jpg
小车测试版-整体外观 (原文件名:DSCN2363.jpg)
http://cache.amobbs.com/bbs_upload782111/files_28/ourdev_550347.jpg
小车测试版-侧面外观 (原文件名:DSCN2365.jpg)
http://cache.amobbs.com/bbs_upload782111/files_28/ourdev_550348.jpg
(原文件名:DSCN2366.jpg)
http://cache.amobbs.com/bbs_upload782111/files_28/ourdev_550349.jpg
后轮2个光电开关,实现2轮的壁障 (原文件名:DSCN2367.jpg)
http://cache.amobbs.com/bbs_upload782111/files_28/ourdev_550350.jpg
寻迹采用5个传感器,正中间的传感器为黑线反馈传感器,其相邻左右传感器为直线校准传感器,最外面为急转弯处理传感器~ 5个传感器位置间距可调,伸缩长度可调~ (原文件名:DSCN2368.jpg)
前轮进行寻迹,后轮进行寻迹~~~~~~~! 看速度直接看视频 http://v.youku.com/v_show/id_XMTY4OTgyMDY0.html
程序调得好 完全可以跟用舵机控制的火拼,我就是这个体会,由于准备时间比较仓促,用硬件到调试完程序用了4天三夜左右,没有具体的优化,我们采用的是7.2V电池,其实完全可以进行升压行驶,这个速度完全额可以控制的,~! 郑同学取得了比较好的成绩,先祝贺一下!
郑同学淘宝上买的98元小车在比赛前夕都坏了(齿轮和电机都烂了,以前论坛上也有人说过),应急采用我做的57元的三轮小车(功率比较小0.5W,全速跑也不快),打败了88元的圆梦小车和98元的其他组小车,仅比采用舵机,而且用大功率驱动电机的飞尔卡思速度稍慢(好几百元的),全场运行流畅,没有脱轨,而且全部电路和程序都是自己独立完成,取得了非常好的成绩和学习经验. mark 我做的比他跑的慢点,速度大概70~80cm/s吧,不过也是比98块的那些强,那些这次好像都是机械问题全体悲剧了。 店主的那个避障的光电管很不错!相当灵敏!检测距离20~70厘米!相当不错,避障趣味赛的时候我们车最灵活了! mark 回复【58楼】vip_windy
店主的那个避障的光电管很不错!相当灵敏!检测距离20~70厘米!相当不错,避障趣味赛的时候我们车最灵活了!
-----------------------------------------------------------------------
你做的其实也不错.你的头像也有点太那个了吧,还是学生时代呢?呵呵
避障模块确实挺灵敏的,距离还可以更远,超过1米,不过太远对于小车就有点不合适了.
比淘宝上卖25元的强多了,那个很耗电,100ma.距离差不多.价格差不多只一半. 小车好玩 准备去区里面比赛了 呵呵 呵呵,很不错的了。 学习了,呵呵 回复【楼主位】ct_dev
-----------------------------------------------------------------------
楼主用的是HS0038B来做红外接收头的吧 cool!!学习学习!! 牛!学习学习! 再顶一下 mark,楼主对机器人的热爱让我钦佩,程序很干净。美中不足的是注释太少了,读着费劲,如果楼主不介意的话请阐述一下本程序的思路,N_S图就更好了。让像我一样的小白可以看明白。 mark good 回复【2楼】ba1731
-----------------------------------------------------------------------
向楼主学习 很好很强大 收藏了 学习一下! 顶啊 我想单做个循迹的,功能也不用那么复杂,LZ能帮忙提供下程序跟原理图吗??避障的就省掉了,也不用液晶 不错,路过接收·· 学习…………………… 支持 MARK 支持顶起 收藏,不错哦 好精致啊 很好 向你学习啊 哈哈!!!!!!!!!!!!!!!! 不错!!!!!!!!!!!!!!!!!!!!! 诸多 何意? 挺好。。。。。 要顶一下 的确很牛叉 酷 膜拜啊! 顶好多个!
页:
[1]