智能车制作

标题: 51单片机小车,不走直线! [打印本页]

作者: 五加六等于一    时间: 2014-8-1 09:12
标题: 51单片机小车,不走直线!
本帖最后由 五加六等于一 于 2014-8-1 09:15 编辑

新手没是那么经验,只是靠兴趣自学了单片机,又自学了C语言,现在做了一个基于51单片机的小车,处于程序调试阶段。大概说说我的小车吧,三个轮子,前面一个万向轮后面两个直流马达驱动另外两个轮子。直流马达采用ULN2803驱动,可以实现PWM调速。小车上一共备有四组红外传感器,Sensor01 和 Sensor02 分别测速 Motor01 和 Motor2,Sensor03 实现避障功能,Sensor04 备用以防不时之需。先上个图,Show 一下我的处女座小车,哈哈......
一开始楼主单纯的认为只要两边的Motor 给相同的电压就可以走直线了,所以随便调来了一个PWM就OK了。结果小车走的那叫一个歪,然后我在网上发帖求助,网友说开环控制不能实现小车直线,最好要闭环控制。然后我就构思了小车的闭环控制,闭环控制的程序流程图请参看下面的截图。

不幸的是小车还是不走直线,然后我就发现测速的两个Sensor有点问题,就是这个读出的数值有偏差,然后我就在同一个马达上调试了这个两个Sensor。如何调试?在红外发光端加大了限流电阻从220欧加到2K,调节红外接收极的分压电阻(滑动变阻器),然后用单片机的定时器定时30s 每个Sensor 收集21个数据,最终调试的结构如下面的截图。

最后我按照之前的思路编写了程序,可是小车还是不能走直线,所以在这里请各位大牛给点建议,只能谢谢了。


[attach]67316[/attach][attach]67317[/attach][attach]67319[/attach]




补充内容 (2014-8-14 11:05):
小车已经搞好了,视频链接: http://v.youku.com/v_show/id_XNzU1NTIxMzcy.html
作者: aytc100    时间: 2014-8-1 09:27
上陀螺吧。一个差不多的陀螺就能让你的小车走直了。
作者: hymwgk    时间: 2014-8-1 09:33
有编码器也可以吧   底盘下面应该有那种光栅编码器的接口
作者: whisker    时间: 2014-8-1 10:02
调占空比,直到走直线
作者: 五加六等于一    时间: 2014-8-1 10:04
aytc100 发表于 2014-8-1 09:27
上陀螺吧。一个差不多的陀螺就能让你的小车走直了。

可否详细说说你的方案,另外在不改造小车主题结构的前提下,是否有使小车走直线的方案?

作者: 五加六等于一    时间: 2014-8-1 10:07
hymwgk 发表于 2014-8-1 09:33
有编码器也可以吧   底盘下面应该有那种光栅编码器的接口

编码器?没有编码器! 小车是自己做的,主板自己画的,底盘在网上淘的。你说编码器就是测速的那个吧,我的小车也有测速模块,就是通过槽型红外传感器实现的。可是还是不能走直线。

作者: 五加六等于一    时间: 2014-8-1 10:08
whisker 发表于 2014-8-1 10:02
调占空比,直到走直线

你确定能够调到一个固定的占空比?

作者: whisker    时间: 2014-8-1 10:10
试试吧,我觉得应该是可以的
作者: 五加六等于一    时间: 2014-8-1 10:18
whisker 发表于 2014-8-1 10:10
试试吧,我觉得应该是可以的

我调试过了,找到了一个数,比这个数大1就左偏,使用这个数就右偏,如何解释?而且小车相同的参数设置,有时候左偏有时候右偏,这个又怎么控制?纠结。。。

作者: hymwgk    时间: 2014-8-1 10:32
五加六等于一 发表于 2014-8-1 10:07
编码器?没有编码器! 小车是自己做的,主板自己画的,底盘在网上淘的。你说编码器就是测速的那个吧,我的 ...

这种车底盘靠近轮子处有一个长槽口   电机上与轮子同轴应该可以接一个光电码盘   就是你说的那个红外传感器   两个是配套的   那个把速度传回来处理一下    设置让两个轮子速度一样应该可以了

作者: hymwgk    时间: 2014-8-1 10:34
五加六等于一 发表于 2014-8-1 10:18
我调试过了,找到了一个数,比这个数大1就左偏,使用这个数就右偏,如何解释?而且小车相同的参数设置,有 ...

那个不行的    电机制造时死区电压不会完全一致   即使完全一致   两个轮子遇到的阻力也不会完全一样   不会一直走直线的   得加个反馈环节

作者: 迷离的眼神    时间: 2014-8-1 10:34
闭环嘛
作者: 五加六等于一    时间: 2014-8-1 11:02
迷离的眼神 发表于 2014-8-1 10:34
闭环嘛

是闭环,可是还好调试好。不知道是程序的问题,还是硬件的问题。程序流程图在上面贴了,两个测速红外传感器也调试过了,帮忙再仔细看看。谢谢了
作者: 五加六等于一    时间: 2014-8-1 11:06
hymwgk 发表于 2014-8-1 10:32
这种车底盘靠近轮子处有一个长槽口   电机上与轮子同轴应该可以接一个光电码盘   就是你说的那个红外传感 ...

配套?自己做的,就怕有误差,可是还是有问题。现在不知道是程序的问题,还是硬件的问题,直觉觉得这个红外是有问题的,但是不知道如何精确的调试?

作者: hymwgk    时间: 2014-8-1 11:15
五加六等于一 发表于 2014-8-1 11:06
配套?自己做的,就怕有误差,可是还是有问题。现在不知道是程序的问题,还是硬件的问题,直觉觉得这个红 ...

看了看    你看是不是调节太过频繁   电机高频启动停止   有可能和地面产生微小的打滑    可以多次采集之后把两轮误差平滑处理一下  稍微缓慢的加到两个轮子上估计会好点

作者: aytc100    时间: 2014-8-1 11:21
五加六等于一 发表于 2014-8-1 10:18
我调试过了,找到了一个数,比这个数大1就左偏,使用这个数就右偏,如何解释?而且小车相同的参数设置,有 ...

你的小车要是这样就没太好的办法了。51的PWM精度不够。要么换主控芯片,飞思卡尔的单片机什么的;要么你就想办法加别的反馈,比如陀螺。

陀螺的简单用法:首先你得有个基本靠谱的陀螺(别是ENC-03)并且能读到它的数据。然后对陀螺输出的角速度数据进行积分,得到角度。接下来就是努力保持角度不变就可以了。

作者: 易湘鑫    时间: 2014-8-1 11:32
加个反馈嘛
作者: '佬々大§    时间: 2014-8-1 11:38
电机特性不同,左右轮的差速不是0,当然不会走直线,闭环控速才是王道
作者: killer1    时间: 2014-8-1 12:35
找你们学长
作者: 时光机╰'    时间: 2014-8-1 12:41
左右轮分别给相同目标速度而不是pwm,电机各自读脉冲调pid
作者: 909885807    时间: 2014-8-1 13:54
PID算法
作者: ddh    时间: 2014-8-1 16:48
加油
作者: 淡忘◎幸福    时间: 2014-8-1 21:49
想当年我玩这种车的时候,任何速度计都没有,事先调好,给不同的PWM,大概走过3m不是很歪就可以了,为了完完全全走直线增加很多东西没必要。
作者: 五加六等于一    时间: 2014-8-1 23:14
hymwgk 发表于 2014-8-1 11:15
看了看    你看是不是调节太过频繁   电机高频启动停止   有可能和地面产生微小的打滑    可以多次采集之 ...

好吧,我上程序吧,该程序是按照上面的那个程序流程图编写的,帮忙看看是程序的问题,还是硬件问题?

void main ()
{
    init();
    TMOD=0x10;                              // T0和T1 的工作方式为方式1
    TH1=(65535-46082)/256;              // 装入初值 50ms
    TL1=(65535-46082)%256;
    EA=1;                                       // 开总中断
    ET1=1;                                     // 开T1 中断
    TR1=1;                                     // 启动T1中断
        while (1)
        {
                /* Motor go , stop if there is something blocking the way*/
                while ( sensor03)
//                while (!flag)
                {
                        for (count00=230;count00>0;count00--)
                        {
                                if (relay_read == 0)
                                        relay_send=1;
                                motor02=0;                        /* PWM */
                                motor01=0;
                                delayms0(10);                               
                                motor02=1;
                        //        delayms0(preset_num);
                                motor01=1;
                                delayms0(20);
                                /* To check sensor01 and sensor02 good or not */
                                if ( sensor01 == 0)
                                        led0=~led0;
                                else
                                        led1=~led1;
                                if ( sensor02 == 0)
                                        led2=~led2;
                                else
                                        led3=~led3;
                                /* To record both motor V(sudu) */
                                if (sensor01==0)
                                {
                                        delayms0(100);
                                        if (sensor01==0)
                                        count01++;
                                        if( count01==130)
                                                count01=0;
                                        circle01++;
                                }

                                if (sensor02==0)
                                {
                                        delayms0(100);
                                        if (sensor02==0)                               
                                        count02++;
                                        if( count02==130)
                                                count02=0;
                                        circle02++;
                                }
                        }
                       
                        /* To control preset_num , then car goes on line*/
                        while (circle02 > circle01)
                        {
                            motor02=0;                        /* PWM */
                                motor01=0;
                                delayms0(1);
                                motor01=1;
                                delayms0(20);
                                if (sensor01==0)
                                {
                                        delayms0(100);
                                        if (sensor01==0)
                                                count01++;
                                        if( count01==130)
                                                count01=0;
                                        circle01++;
                                }
                        }
                       
                }
               
                motor01=0;
                motor02=0;
               
                /* LD E on, if motor stops */
                while (!sensor03)
                {
                        led0=~led0;
                        delayms0(6500);
                    write_time(0x80+8,circle01);
            write_time(0x80+0x40+8,circle02);
                }

        }

}



作者: 五加六等于一    时间: 2014-8-1 23:16
aytc100 发表于 2014-8-1 11:21
你的小车要是这样就没太好的办法了。51的PWM精度不够。要么换主控芯片,飞思卡尔的单片机什么的;要么你就 ...

难道51单片机不能搞定?

作者: 五加六等于一    时间: 2014-8-1 23:18
易湘鑫 发表于 2014-8-1 11:32
加个反馈嘛

反馈加了,程序流程图如下/:

[attach]67325[/attach]

作者: 五加六等于一    时间: 2014-8-1 23:49
时光机╰' 发表于 2014-8-1 12:41
左右轮分别给相同目标速度而不是pwm,电机各自读脉冲调pid

PID 从前没有接触过,能够给个教程?

作者: wjfuture    时间: 2014-8-2 16:43
显然是你的PWM的精度不够。两边电机对相同占空比的PWM响应也不一定一样,用双电机的话要精确的测出来两个电机分别对PWM占空比的响应才行。
作者: 五加六等于一    时间: 2014-8-2 20:15
wjfuture 发表于 2014-8-2 16:43
显然是你的PWM的精度不够。两边电机对相同占空比的PWM响应也不一定一样,用双电机的话要精确的测出来两个电 ...

你讲的很靠谱,可否详细说说?

作者: 五加六等于一    时间: 2014-8-4 16:27
本帖最后由 五加六等于一 于 2014-8-4 16:35 编辑

向大家报道一个喜讯,小车目前来看有望走直线了,我晚上回去就去调程序。目前来看, 之前的测速程序有很大问题,楼主之前的测速程序用的大循环里的if 语句:
while(1)
{
          /* PWM to control motor speed */
     motor01=0;     motor02=0;
     delayms(5);
     motor01=1;
     motor02=1;
     delayms(20);

     /* Check the speed of motor */
     if (sensor01==0)
         pulse_motor01++;
     if (sensor02==0)
         pulse_motor02++;

}


这个测速程序非常有问题,这个就是楼主写了半天程序,逻辑没错可是不按照设想走直线的原因,回去就去用定时器的计数模式改测速程序,然后再来汇报。
PS : 楼主正在研究 PID ,等我搞懂了PID的 概念和方法, 再来请教。

作者: 五加六等于一    时间: 2014-8-5 09:55
hymwgk 发表于 2014-8-1 11:15
看了看    你看是不是调节太过频繁   电机高频启动停止   有可能和地面产生微小的打滑    可以多次采集之 ...

兄台,问题找到了,测速程序有问题,之前的测速程序是在大循环里用IF 判断,后来想了想这个方法完全错误,先把程序贴上:

while (1)
{
     /* PWM */
     motor01=0;
     motor02=0;
     delayms(10);
     motor01=1;
     motor02=1;
     delayms(30);


     /* Check the speed */
     if (sensor01==0)
       speed01++;
     if (sensor02==0)
       speed02++;

}

这个程序测得的脉冲个数根本不能反映马达的速度,后来我发现应该用T0,T1 的计数器模式来读取motor01 motor02的脉冲个数来测速,可是这样的话52 单片机就三个定时器, 感觉定时器好紧张。
我的思路, 用T0, T1 计数器模式记录motor 脉冲, T2来控制PWM, 大概就是这个样子,兄台有什么建议?

作者: 五加六等于一    时间: 2014-8-5 11:49
aytc100 发表于 2014-8-1 11:21
你的小车要是这样就没太好的办法了。51的PWM精度不够。要么换主控芯片,飞思卡尔的单片机什么的;要么你就 ...

我买了个陀螺准备研究一下, 目前正在改进 小车的程序。谢谢指点

作者: wzqvip    时间: 2016-4-6 14:57
五加六等于一 发表于 2014-8-5 09:55
兄台,问题找到了,测速程序有问题,之前的测速程序是在大循环里用IF 判断,后来想了想这个方法完全错误 ...

楼主你最后是用51的还是52的?还有你说的是码盘测速吗?就是加在tt马达装轮子另外一边的那里的?

作者: wzqvip    时间: 2016-4-7 10:24
aytc100 发表于 2014-8-1 09:27
上陀螺吧。一个差不多的陀螺就能让你的小车走直了。

您好请教一下,陀螺仪是怎么用让车走直线的

作者: wzqvip    时间: 2016-4-7 10:34
你好,看到你做的测面积的小车挺厉害的,能否请教一下你几个问题哈?我最近忙着做毕设,卡住了,真心谢谢你
作者: 564388806    时间: 2016-12-21 16:51
aytc100 发表于 2014-8-1 09:27
上陀螺吧。一个差不多的陀螺就能让你的小车走直了。

只加陀螺仪可以吗?是不是需要电子罗盘矫正;如果只用电子罗盘可以不
作者: 默雨    时间: 2018-3-13 09:38
楼主,你最后是怎么把他调成跑直线的?求指点




欢迎光临 智能车制作 (http://111.231.132.190/) Powered by Discuz! X3.2