9699|4

1170

帖子

0

TA的资源

至上芯片

楼主
 

STEP BY STEP,用M16改遥控小车为漫游机器人 [复制链接]

 一直想做个小车,自动控制的。从大一就想做,毕业了还没有实现。
小车应该归为移动机器人类,这东西,想做简单,可以做的相当简单,就像本文中的这个;想做复杂,也可以做的相当复杂,什么模式识别,图像处理,路径规划等等,都可以加入。
在大一时,想做个这样的东西,那时有时间啊,却不知道从哪里开始下手,每天等着本电子线路,啃,却什么也没有实现。
后来,单片机算是入门了,却又开始做项目,被导师逼的急的不行,几年下来,小车这个梦想还是没有实现。
这几天,仍然是有项目,仍然是每天加班,却想把这个东西做出来,于是,花了两晚上做了个小车,用遥控小汽车改的,很幼稚的那种,虽然做出来的效果也不是特别理想,但毕竟是实现了以前的梦想,心里也不由的兴奋!
这是以前买了个遥控的小跑车,支解后的机械部分是这样的:

先分析一下这个小车,它一共用了两个电机,一个用于动力,后轮驱动,一个用于方向,在前面的方向轮上,一加电,电机转到头,这样算是转了向。这样最大的好处是简单,成本极低,当然,付出的代价也不小,电机转不动后,耗电急剧增加,这样,好好的一个小车,成了电老虎,玩不起啊,四节新的南孚电池,一下午就干没了。
再来看看它的电路,接收部分由调谐电路和遥控汽车专用芯片RX2,还有驱动电路组成,天线来的信号通过选频,放大和检波后,送至RX2的14脚进行一,二级反相放大,最后从1脚输出,经外围RC电路滤波后,从3脚进入,进行译码处理,如果接收成功的话,将从6脚(右)、7脚(左)、10脚(后)、11脚(前)输出高电平,从而推动驱动电路使小车执行相关的动作。驱动电路是用三极管做的,很经典的双向驱动电路,如下图所示(已经加了后文的滤波):

好了,小车基本解剖完毕。下面来想一下我们的方案。
原小车上我们可以用的,我们不用遥控,所以RX2我们可以不用了,前端的接收电路也不用了,唯一有用的是原车的驱动电路,但这个玩具车是个跑车,速度太快,我们如果直接用的话,不好控制,还要随时准备撞墙。但如果只是慢速的话,这个小车的启动又成了大问题,大家物理都学过,静摩擦大于动摩擦。最好,还要能变速,对于M16来讲,要控制它变速,最好的办法就是PWM了,产生的波形通过RC滤波后,变成可以控制的电压信号,再用于控制电机的转速。于是,我们要做的第一步,在驱动的控制三极管的基极上加一个RC滤波,电阻值为10K,电容值为104,是凭感觉选的值,大概能用。
方向是不准备用它的电路了,太耗电了!要能控制转动角度的,用舵机最方便,于是,我就是了舵机,普通的那种,三四十块一个。舵机一般有三根线,一根电源,一根地,一根控制信号线,电源在5V就可以,控制信号线是用脉冲控制的,脉冲的周期是20ms,当脉宽为2ms时,舵机在中间位置,当脉宽为1.5ms时,舵机逆时针转90度,当脉宽为2.5ms时,舵机顺时针转90度。M16不是有四个通道的PWM吗,用一个来控制舵机,是够了。舵机的个头太大了,我把原先放电机的地方上面挖一个洞,才可以把舵机放进去,然后把原先的齿轮卸下来,在舵机的中间插一根钢柱,然后再把齿轮套上去,改装后的舵机如下图所示:

然后把舵机安到车里去,如下图所示:

好了,现在,这个车如果加上电,给控制端放一个固定电平,它应该是可以跑了,但我们当然不会满足于让它走直线啦,下面,我们要给它加控制电路。
三句不离本行,控制还是用单片机做吧。单片机用MEGA16,至于为什么用M16,这个,我也没有认真考虑过,不过,我这刚好有M16做的最小系统PACK板,所以,就用它了。
最小系统的电路图(讲的烂的不能再烂的东西),如下所示:

PCB板图,如下所示:

PACK板子,如下所示:

另外,机器人总得有若干传感器吧,否则就是无头苍蝇,到处乱撞。还是用简单点的吧,这里用的是红外反射管,电路如下所示:

然后连线,两个控制端一个放在OC1A,一下放在OC1B,舵机放在OC2上,三个红外接收输出接到ADC0至ADC2上,这样,还可以控制一下灵敏度。最后,我的小车闪亮登场!

下附本小车的程度,我没有做路径规划,只用根据习惯做了一些避障动作,最后做出的效果也只能是凑和,动作不是很连贯,偶尔还会撞墙。以后有时间再做一些路径规划,把动作做的连贯些。另外,在这里提出一点建议,把ADC放在一个定时器中断里,采样再加滤波,得出的障碍情况处理时分时处理,这样,可以在一个障碍没处理完时又碰到另一个障碍,马上转去处理另一个障碍,从而避免在处理障碍时对其它障碍不理的问题。大家可以改进改进,哥们我实在是不行了,现在都早上一点多了。程序是用GCC编的。
/*
* FileName: Robocarmain.c
* Author: yuanding Version: 1.0 Date: 2006-4-16
* Description: a roboticcar controled by m16
* Version:
* Function List:
* 1.
* History:
* <author> <time> <version > <desc>
*/
#include <avr/io.h>
#include <avr/interrupt.h>
#include <avr/signal.h>
#include <inttypes.h>
#include <string.h>
#include <avr/eeprom.h>
#include <stdlib.h>
#include <math.h>
//设置的PWM值,用以控制车速
#define LOWSPEED 195
#define MIDSPEED 230
#define HIGHSPEED 250
//定义控制舵机的PWM值
#define FULL 144
#define STRIGHT 10
#define LEFT 6
#define RIGHT 14
//定义红外传感器的引脚
#define DEAHEAD 0x04
#define DELEFT 0x01
#define DERIGHT 0x02
void SetPWM(uint16_t PWMValue0);
void delay_1ms(void);
void delay_nms(unsigned int n) ;
void Forward(uint16_t Speed);
void Backward(uint16_t Speed);
void SetPosition(uint8_t Position);
void Init(void);
void Stop(void);
void Detect(void);
void StartGo(void);
void StartBack(void);
uint8_t Read_Adc(uint8_t Channel);
uint8_t Get_Evt(void);
uint8_t Pulse_With=0;
uint8_t PeriodCount=0;

/*
* Function: SetPWM
* Description: try OC1 PWM function
* Calls: NONE
* Called By: NONE
* Table Accessed:
* Table Updated:
* Input: the PWM value
* Output: none
* Return: none
* Others:
*/
void SetPWM(uint16_t PWMValue0)
{
TCCR1A=(1<<COM1A1)|(1<<COM1B1)|(1<<WGM11);
TCCR1B=(1<<WGM13)|(1<<WGM12)|(1<<CS10);
ICR1=0X7FF;
if(PWMValue0<2048&&PWMValue0>0)
{
OCR1A=PWMValue0;
OCR1B=PWMValue0;
}
}
void delay_1ms(void) //1ms延时函数
{
unsigned int i;
for (i=0;i<30000;i++);
}

void delay_nms(unsigned int n) //N ms延时函数
{
unsigned int i=0;
for (i=0;i<n;i++)
delay_1ms();
}
/*
* Function: Forward
* Description: to control car go ahead
* Calls: none
* Called By: StartGo,Detect,etc
* Table Accessed:
* Table Updated:
* Input: the speed value
* Output: none
* Return: none
* Others: none
*/
void Forward(uint16_t Speed)
{
TCCR1A=(1<<COM1A1)|(1<<WGM11);
TCCR1B=(1<<WGM13)|(1<<WGM12)|(1<<CS10);
ICR1=0XFF;
if(Speed<2048&&Speed>0)
{
OCR1A=Speed;
}
}

/*
* Function: Backward
* Description: control the car move back
* Calls: none
* Called By: StartBack,Detect,etc
* Table Accessed:
* Table Updated:
* Input: speed value
* Output: none
* Return:
* Others:
*/
void Backward(uint16_t Speed)
{
TCCR1A=(1<<COM1B1)|(1<<WGM11);
TCCR1B=(1<<WGM13)|(1<<WGM12)|(1<<CS10);
ICR1=0XFF;
if(Speed<2048&&Speed>0)
{
OCR1B=Speed;
}
}

/*
* Function: stop
* Description: stop the car
* Calls:
* Called By:
* Table Accessed:
* Table Updated:
* Input: none
* Output: none
* Return:
* Others:
*/
void Stop(void)
{
TCCR1A=0;
TCCR1B=0;
}
//
/*
* Function: SetPosition
* Description: the control the position motor's degree
* Calls:
* Called By:
* Table Accessed:
* Table Updated:
* Input: the postion value
* Output: none
* Return:
* Others:
*/
void SetPosition(uint8_t Position)
{
cli();
TCCR2=0x0f;
Pulse_With=Position;
OCR2=FULL-Pulse_With;
TIMSK|=(1<<OCIE2);
sei();
delay_nms(500);
}

/*
* Function: interrupt function
* Description: to generate PWM wave to position motor
* Calls:
* Called By:
* Table Accessed:
* Table Updated:
* Input:
* Output:
* Return:
* Others:
*/
SIGNAL(SIG_OUTPUT_COMPARE2)
{
if(OCR2<=30)
{
cbi(PORTD,7);
OCR2=FULL-Pulse_With;
}
else
{
sbi(PORTD,7);
OCR2=Pulse_With;
}
}

void Init(void)
{
//TIMER2 initialize - prescale:8
// WGM: Normal
// desired value: 100uSec
// actual value: 99.826uSec (0.2%)
// TCCR2 = 0x00; //stop
// ASSR = 0x00; //set async mode
// TCNT2 = 0xA4; //setup
// OCR2 = 0x5C;
// TCCR2 = 0x02; //start
// TIMSK|=(1<<TOIE2);
// sei();
DDRA=0x00;
PORTA=0x00;
}
//100uSec overflow interrupt service function
//not use
SIGNAL(SIG_OVERFLOW2)
{
TCNT2 = 0xA4; //reload counter value
PeriodCount++;
if(PeriodCount==FULL)
{
sbi(PORTD,7);
PeriodCount=0;
}
if(PeriodCount==Pulse_With)
{
cbi(PORTD,7);
}
}

/*
* Function: StartGo
* Description: start in high speed to move the car ahead
* Calls: forward()
* Called By:
* Table Accessed:
* Table Updated:
* Input: none
* Output: none
* Return:
* Others:
*/
void StartGo(void)
{
Forward(HIGHSPEED);
delay_nms(300);
Forward(LOWSPEED);
}

/*
* Function: StartBack
* Description: start in high speed to move the car back
* Calls: backward()
* Called By:
* Table Accessed:
* Table Updated:
* Input: none
* Output: none
* Return:
* Others:
*/
void StartBack(void)
{
Backward(MIDSPEED);
delay_nms(200);
Backward(LOWSPEED);
}

/*
* Function: Detect
* Description: to detect whether there are obstructions
* Calls:
* Called By:
* Table Accessed:
* Table Updated:
* Input:
* Output:
* Return:
* Others:
*/
void Detect(void)
{
uint8_t temp=0;
temp=Get_Evt();//PINA;
if((temp&DEAHEAD)&&(temp&DELEFT)&&(temp&DERIGHT))
{
Backward(HIGHSPEED);
delay_nms(100);
SetPosition(STRIGHT);
StartBack();
}
else if((temp&DEAHEAD)&&(!(temp&DELEFT))&&(!(temp&DERIGHT)))
{
Backward(HIGHSPEED);
delay_nms(100);
SetPosition(RIGHT);
StartBack();
delay_nms(600);
SetPosition(LEFT);
StartGo();
delay_nms(600);
SetPosition(STRIGHT);
Forward(LOWSPEED);
}
else if((temp&DEAHEAD)&&(temp&DELEFT)&&(!(temp&DERIGHT)))
{
Backward(HIGHSPEED);
delay_nms(100);
SetPosition(RIGHT);
StartBack();
delay_nms(1200);
SetPosition(STRIGHT);
StartGo();
}
else if((temp&DEAHEAD)&&(!(temp&DELEFT))&&(temp&DERIGHT))
{
StartBack();
delay_nms(100);
SetPosition(LEFT);
StartBack();
delay_nms(2000);
SetPosition(STRIGHT);
StartGo();
}
else if((!(temp&DEAHEAD))&&(temp&DELEFT)&&(!(temp&DERIGHT)))
{
SetPosition(RIGHT);
Forward(LOWSPEED);
delay_nms(600);
SetPosition(STRIGHT);
Forward(LOWSPEED);
}
else if((!(temp&DEAHEAD))&&(!(temp&DELEFT))&&(temp&DERIGHT))
{
SetPosition(LEFT);
Forward(LOWSPEED);
delay_nms(600);
SetPosition(STRIGHT);
Forward(LOWSPEED);
}
else if((!(temp&DEAHEAD))&&(!(temp&DELEFT))&&(!(temp&DERIGHT)))
{
Forward(LOWSPEED);
}
}

/*
* Function: Read_Adc
* Description: start a ADC ,and return the value,8 bit
* Calls:
* Called By:
* Table Accessed:
* Table Updated:
* Input: none
* Output: the adc result,8 bit
* Return:
* Others:
*/
uint8_t Read_Adc(uint8_t Channel)
{
ADMUX=1<<ADLAR|Channel;
ADCSRA=1<<ADEN|1<<ADSC|6<<ADPS0;
loop_until_bit_is_set(ADCSRA,ADIF);
ADCSRA|=1<<ADIF;
return ADCH;
}

/*
* Function: Get_Evt
* Description: get the environment situation
* Calls:
* Called By:
* Table Accessed:
* Table Updated:
* Input:
* Output: 0b00000(ahead)(left)(right)
* Return:
* Others:
*/
uint8_t Get_Evt(void)
{
uint8_t temp=0;
if(Read_Adc(0)>=30)
temp|=0x01;
if(Read_Adc(1)>=30)
temp|=0x02;
if(Read_Adc(2)>=40)
temp|=0x04;
return temp;
}
//enter here
int main(void)
{
DDRD=0xff;
Init();
SetPosition(STRIGHT);
StartGo();
while(1)
{
Detect();
}
return 0;
}

最新回复

  详情 回复 发表于 2010-9-18 17:21
点赞 关注
 
 

回复
举报

1759

帖子

0

TA的资源

裸片初长成(高级)

沙发
 

回复:STEP BY STEP,用M16改遥控小车为漫游机器人

不错 支持
个人签名南京璞晓电子   www.cpx0.com需要
msn:njlianjian@hotmail.com
 
 
 

回复

527

帖子

0

TA的资源

五彩晶圆(中级)

板凳
 
好东东,就是程序的格式看起来,头晕啊!
 
 
 

回复

391

帖子

0

TA的资源

纯净的硅(高级)

4
 
楼主没看到图
 
 
 

回复

119

帖子

0

TA的资源

一粒金砂(中级)

5
 
 
 
 

回复
您需要登录后才可以回帖 登录 | 注册

随便看看
查找数据手册?

EEWorld Datasheet 技术支持

相关文章 更多>>
关闭
站长推荐上一条 1/7 下一条

 
EEWorld订阅号

 
EEWorld服务号

 
汽车开发圈

About Us 关于我们 客户服务 联系方式 器件索引 网站地图 最新更新 手机版

站点相关: 国产芯 安防电子 汽车电子 手机便携 工业控制 家用电子 医疗电子 测试测量 网络通信 物联网

北京市海淀区中关村大街18号B座15层1530室 电话:(010)82350740 邮编:100190

电子工程世界版权所有 京B2-20211791 京ICP备10001474号-1 电信业务审批[2006]字第258号函 京公网安备 11010802033920号 Copyright © 2005-2025 EEWORLD.com.cn, Inc. All rights reserved
快速回复 返回顶部 返回列表