51单片机循迹小车怎样又准又快

51单片机循迹小车怎样又准又快,第1张

初期做这个,左右摇摆是必然的。 因为其本身的循迹方式就是开关式的! 传感器的得到的信息只有两种要么在左边,要么在右边。具体的不知道小车在线的左边多少,右边多少,导致不能让小车拐大弯与拐小弯,只能让车拐。就导致了其左右的摇摆。

如果想不让其摇摆,可以加成一排红外管,虽然不能像摄像头或者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程序技巧等相关内容解答,如果想了解更多相关内容,可以关注我们,你们的支持是我们更新的动力!

欢迎分享,转载请注明来源:内存溢出

原文地址: http://outofmemory.cn/zz/9451680.html

(0)
打赏 微信扫一扫 微信扫一扫 支付宝扫一扫 支付宝扫一扫
上一篇 2023-04-28
下一篇 2023-04-28

发表评论

登录后才能评论

评论列表(0条)

保存