初期做这个,左右摇摆是必然的。 因为其本身的循迹方式就是开关式的! 传感器的得到的信息只有两种要么在左边,要么在右边。具体的不知道小车在线的左边多少,右边多少,导致不能让小车拐大弯与拐小弯,只能让车拐。就导致了其左右的摇摆。
如果想不让其摇摆,可以加成一排红外管,虽然不能像摄像头或者ccd得到连续的信息。但是可以进行相对的转向细分。 知道是大偏差还是小偏差。使之连续路线。当然这个跟机械的红外的间隔等等都有关系。
延时效果,我认为我不加延时为好,本来就有可能丢线呢,还加延时。 延时可能是为了拐固定的角度,比如90度 180度,利用延时可以粗略的控制。
几相的步进电机啊?用不用驱动芯片?用的话选什么型号的驱动芯片?你要说具体点啊!
先给你三相的,个不用驱动芯片的步进电机程序。(驱动电路自己做)
#include<reg51h>
#define uchar unsigned char
#define uint unsigned int
uint time
void timer1(void) interrupt 1 using 1{ //定时器0中断,定时1ms//
TH0=(65536-1000)/256;
TL0=(65536-1000)%256;
time++;
}
void delay(uint n){ //一般延时
while(--n);
}
void delay(uint dtime){ //延时
TR0=1;
while(time<=dtime);
time=0;
TR0=0;
}
void moto(bit cf,uchar n,uint dtime){ //电机驱动子程序,
uchar idata zhpai[4]={0x78,0xb8,0xd8,0xe8};
uchar idata fpai[4]={0xe8,0xd8,0xb8,0x78};
uchar i,l=0;
if(cf==0) //正转,A-B-C-A
for(i=0;i<n;i++){
P1=zhpai[l];//P17~14为输出口,分别为A、B、C、D
l++;
delay(dtime);
if(l==4)l=0;
}
else{ //反转,C-B-A-C
for(i=0;i<n;i++){
P1=fpai[l];
l++;
delay(dtime);
if(l==4)l=0;
}
}
}
void main(){
TMOD=0x01;
TH0=(65536-1000)/256;
TL0=(65536-1000)%256;
EA=1;
ET0=1;
while(1){
moto(0,4,70);//正转,转四相,每相间隔70ms
delay(10000);
moto(1,4,70);//反转,转四相,每相间隔70ms
delay(10000);
}
}
既然是技巧的话那就不提供详细的代码了,首先要看你这个小车是几轮几驱动的,首先假设你只用一个L298n驱动板的话,那么再假设只含左右两个轮,只对左右两个轮进行控制的话,那么就简单了,首先你要知道L298N驱动板怎么用,不同的驱动板功能都不一定相同,不过控制引脚一般来说都是4根,可以控制两个直流电机的正反转,同时还有两个PWM接口,可以控制两个电机的转速。
假设4个控制引脚分为A1、A2和B1、B2,A1、A2控制第一个直流电机,B1、B2控制第二个直流电机,当A1和A2接不同方向的电流后直流电机会正转或反转,同理B1和B2也是一样。PWM是通过控制占有率来控制电机速度的,即控制高电平和低电平的时间的,不同,这样在规定时间内,如果高电平的时间占有比例越高则电机转速越快,输出功率越高。
知道以上内容了那么之后的内容就更容易理解了
前进:两个直流电机朝正方向同时转动即可
后退:两个直流电机朝反方向同时转动即可
原地左转:类似原地打转,只需让两个电机一个正转一个反转即可,即左转为左边电机反转,右边电机正转
原地右转:与原地左转相反即可
固定轮转:固定左边令右侧轮前进即可实现固定轮转向的目的,例如左转的话令左边电机停止,右侧电机正向转动即可,向右转的话与左转相反。
至于keil程序,这个要根据具体的硬件来写,别人的无法通用,不过这些都不难,只要原理弄懂了,稍微花一点儿时间还是能很容易写出来的,先从控制电机的转向开始。别人的程序的话可能会越看越难理解,还是自己动手比较好,先不考虑调速的情况下完成了之后再去看看有关PWM调速的内容。
第一:你这个不是电机调速的,用外部中断是测速的呀。
下面是我写的PID部分的代码就不给了,想加的话,自己找可以了
#include <AT89X52H>
#include "commonh"
#define _WHEEL_C_
#define Left_moto_pwm P1_5
#define Right_moto_pwm P1_4
#define Left_moto_go {IN1=0,IN2=1;}
#define Left_moto_back {IN1=1,IN2=0;}
#define Right_moto_go {IN3=1,IN4=0;}
#define Right_moto_back {IN3=0,IN4=1;}
sbit IN1=P1^0;
sbit IN2=P1^1;
sbit IN3=P1^2;
sbit IN4=P1^3;
unsigned char pwm_val_left=0;
unsigned char push_val_left=0;
unsigned char pwm_val_right=0;
unsigned char push_val_right=0;
float L_Count=0,R_Count=0;
unsigned int TimerNum=0,SYS_TimeNum=0;
float Save_L_Distance=0,Save_R_Distance=0,Left_Speed=0,Right_Speed=0;
unsigned char Left_point=0,Right_point=0;
unsigned char sys_1ms=0,sys_1s=0,TurnFlag=0;
//初始化PWM调速函数
void Init_Wheel()
{
TMOD = 0x01;
TH0 = 0x0FF;
TL0 = 0x0A4;
EA = 1;
ET0 = 1;
TR0 = 1;
}
void Init_WheelSpeedInter()
{
IT0=1; //INT0下降沿中断
EX0=1; //允许INT1中断
IT1=1; //INT1下降沿中断
EX1=1; //允许INT1中断
EA=1;
}
//得到上一次05秒的行驶距离
float GetLeftWheelMileage()
{
return Save_L_Distance;
}
//得到上一次025秒的行驶距离
float GetRightWheelMileage()
{
return Save_R_Distance;
}
void Inter_Left(void) interrupt 0
{
L_Count++;
}
void Inter_Right(void) interrupt 2
{
R_Count++;
}
//小车向前函数
void Wheel_Run(char left_val,char right_val)
{
push_val_left=left_val;
push_val_right=right_val;
Left_moto_go ;
Right_moto_go ;
}
//小车后退函数
void Wheel_Back(char left_val,char right_val)
{
push_val_left=left_val;
push_val_right=right_val;
Left_moto_back;
Right_moto_back;
}
//小车停止函数
void Wheel_Stop(void)
{
Wheel_Run(0,0);
}
//左轮PWM调速函数
void pwm_out_left_moto(void)
{
if(pwm_val_left>200)
{
pwm_val_left=0;
}else
{
if(pwm_val_left<=push_val_left)
{
Left_moto_pwm=1;
}
else
{
Left_moto_pwm=0;
}
}
}
//右轮调速函数
void pwm_out_right_moto(void)
{
if(pwm_val_right>200)
{
pwm_val_right=0;
}else
{
if(pwm_val_right<=push_val_right)
{
Right_moto_pwm=1;
}
else
Right_moto_pwm=0;
}
}
//PWM调速中断(TIMER0--工作方式1)
void Wheel_Interrupt(void) interrupt 1
{
TH0 = 0x0FF;
TL0 = 0x0A4;
TimerNum++;
if(TimerNum>=2500)
{
//左右轮速度cm/s
Left_Speed=4L_Count;
Right_Speed=4R_Count;
//左右轮025秒行驶距离
Save_L_Distance+=L_Count;
Save_R_Distance+=R_Count;
//数据发送到串口图示
DataScope_Get_Channel_Data(L_Count, 1 ); //将数据 10 写入通道 1
DataScope_Get_Channel_Data(R_Count, 2 ); //将数据 20 写入通道 2
Send_Count = DataScope_Data_Generate(2); //生成10个通道的 格式化帧数据,返回帧数据长度
for( DateNum = 0 ; DateNum < Send_Count; DateNum++) //循环发送,直到发送完毕
{
SendByte(DataScope_OutPut_Buffer[DateNum]);
}
TimerNum=0;
L_Count=0;
R_Count=0;
}
pwm_val_left++;
pwm_val_right++;
pwm_out_left_moto();
pwm_out_right_moto();
}
利用单片机的定时器TIMER_A(TA)中断产生脉冲信号,通过在响应的中断程序中实现步进电机步数和圈数的准确计数,通过PWM实现转速控制。
可以利用P10端口的中断关闭TA中断程序,并推入堆栈,停止电机;P11中断则开启TA中断,堆栈推入程序计器(PC),开启电机。
P31端口输出高电平由PMM8713的U/D端口控制电机的转向;P3.0~P37端口接8279的8个数据接口。
单片机扫描到矩阵键盘有键按下时,利用P2端口的中断设置TA,控制启停、调速和转向等,同时单片机反馈给8279控制LED管显示转速和转向。
扩展资料
1、单片机所接收到控制命令暂存在RXBUFFER中,与存储在片内Flash的中断程序的入口地址相比较,相同就进入中断,实现步进电机的控制。
2、当P10中为高电平时,其内部三极管导通,使电机转动。当P10为低电平时,内部三极管截止,电路断开,电机停止转动。所以在程序中可以利用P10口输出PWM波来控制电机的转速。
参考资料来源:百度百科-单片机
参考资料来源:百度百科-电动机的单片机控制
以上就是关于51单片机循迹小车怎样又准又快全部的内容,包括:51单片机循迹小车怎样又准又快、求单片机c语言控制步进电机调速程序、51单片机控制两路直流电机转速的c程序技巧等相关内容解答,如果想了解更多相关内容,可以关注我们,你们的支持是我们更新的动力!
欢迎分享,转载请注明来源:内存溢出
评论列表(0条)