打印

菜鸟也想做个电机钟,硬件都搞好了,可是显示不稳定啊

[复制链接]
7858|51
手机看帖
扫描二维码
随时随地手机跟帖
跳转到指定楼层
楼主
FZJ|  楼主 | 2007-12-31 13:52 | 只看该作者 回帖奖励 |倒序浏览 |阅读模式
关于余数补偿不知道我这样写对不对,请各位大虾给点思路,谢谢!
采用2个定时器,一个用来检测周期,一个用来显示中断,我的思路是这样的:
TIME1检测周期,在硬件上因手头没有霍尔元件,所以采用红外对管作为作为传感元件,下降沿中断处理,中断服务程序:
      CLOCK_ADDR=0;
       
       time1_dis();
       time1_temp=(TMR1L|TMR1H<<8);  
       TMR1L=TMR1H=0;
       time1_en();
        if    (++cnt>1000)    //去掉余数补偿,采用延时(也就是周期不连续检测比先前显示效果好点。
       {   cnt=0;
          if    ((time1_temp>21000)||(time1_temp<6000))  
         {
            time2_dis();
            time2_interrupt_dis();
            clock_bk_off();
         }
         else
         {   //time1_temp=(time1_temp+data_y);  
             PR2=(time1_temp/360);
             //data_y=(time1_temp%360);  //这个余数补偿感觉不对,使用后显示抖的厉害。
             time2_en();
             time2_interrupt_en();
             clock_bk_on();
             display();
          }
        }
    }
各位大虾给点软件思路,谢谢了!

相关帖子

来自 2楼
emailli| | 2008-1-3 09:07 | 只看该作者

还是10楼看的清楚

我说的是不在中断内做除法

不是说 不要除法哦

中断内只是将显示缓冲区的数据拿出来显示而已

显示缓冲区的数据是 主程序 计算得到的

另外,红外对管测量 转速真的很稳定的。不需要额外的载波等。

这个红外对管测量转速我曾经用51做过一个产品了。但是公司是用于 网络柜 

的 排风扇的转速测量用的。

关键是需要用迟滞比较器就OK了

另外,我主要是增加了一个 人为的零点 位置

感觉这样好处理一点

否则,时钟都不知道显示到什么位置啊。

使用特权

评论回复
板凳
FZJ|  楼主 | 2007-12-31 14:01 | 只看该作者

看了老外的程序,下面这个应该是个去抖功能吧??

**********************************************************/
void Crossing_interrupt(void)
{
static unsigned int LastCount;
static unsigned int TotalCount;
static int Latch;
static unsigned char Lap;

Latch = TCNT1;
TotalCount = Latch - LastCount;
LastCount = Latch;
Lap++;
if (Lap > 250)
   {
   Adder = TotalCount / 378;  //ADDER的值为什么要检测250个周期后去除378??
   Lap = 0;
   }

WeelPosition = 0;
OCR1 = Latch + Adder;
TIFR |= 0x80;
Display();
}

使用特权

评论回复
地板
dai_weis| | 2008-1-1 21:22 | 只看该作者

给红外对管增加一个遮光装置

红外对管范围有角度,为接受管增加一个遮光装置减少角度,对于转速的测量取几圈之后的平均值,最好增加一个稳速装置(例如铝盘)

使用特权

评论回复
5
fzj| | 2008-1-2 09:22 | 只看该作者

求平均基本没用,红外线角度我用热缩管给它套住

造成显示抖动的原因分析
1:电机转速不稳(即前次所测时间与当次相差很大) ,但我用示波器看红外接收波形基本没圈都一致(大概一圈是18MS),这点可以排除电机不稳的问题.
2:红外元件在检测中由于电机旋转造成的抖动(不平衡)而使接收角度有偏差.
  对于平衡电因没有合适的仪器,所以只能是个大概的判断:在初次调试中测得电机工作电流,然后凭感觉在某端点装一根螺杆,越小越好,以使平衡点调试更加精细,测试电机电流,如果变大,换方向安装,如果减小,继续安装螺杆,或者套一个螺帽,直到电机电流最小,这时手握电机旋转基本上抖动不是那么厉害.
3:最怀疑的一点,软件思路不对,对于一周时间无法给180或360所整除,造成余数引起显示位置不能固定,还有TIME1的分频系数也是引起误差的关键,真的是想不出好的办法,看了N遍老外写的程序也没看明白,感觉如果要使显示稳定,误差必须为0,可如何避免这个误差.
4:难道我的电机速度不够???是不是加快电机装速,以旋转4周或8周甚至更多来作一次动态显示?下面是我写的测试程序,简单到把一个圆平分成60等份,要求显示稳定,惭愧我做不到啊,肯顶高人给我作一下分析,感激不尽
***********************************************************************/
#include   "pic.h"
__CONFIG    (PWRTEN&WDTEN&HS&BORV25&PROTECT);
/***********************************************************************/
 void    mcu_init        (void);
 void    display         (void);   
/***********************************************************************/
 #define   clock_bk_on()          RA2=1
 #define   clock_bk_off()         RA2=0
 #define   time1_en()             T1CON=0x31
 #define   time1_dis()            T1CON=0
 #define   time2_interrupt_en()   PIE1=2
 #define   time2_interrupt_dis()  PIE1=0
 #define   time2_en()             T2CON=7
 #define   time2_dis()            T2CON=0;TMR2=0
/***********************************************************************/
 volatile  unsigned  int  time1_temp;
 volatile  unsigned  char CLOCK_ADDR;
 volatile  unsigned  char data_y;
 volatile  unsigned  char cnt;
 volatile  long           buff;
/************************************************************************/
 void    mcu_init        (void)
 {  TRISA=0;
    TRISB=1;
    OPTION=1;
    INTCON=0XD0;
    ADCON1=7;
    CLRWDT();
 }
/**************************************************************************/
 void    interrupt  isr   (void)
{   if   (INTF)
   {   INTF=0;
       CLOCK_ADDR=0;
       
       time1_dis();
       buff+=(TMR1L|TMR1H<<8);
       TMR1L=TMR1H=0;
       time1_en();
        if    (++cnt>=8)
       {   cnt=0;
           time1_temp=(unsigned int) (buff/8);
           buff=0;
         /* if    ((time1_temp>21000)||(time1_temp<6000))  
         {
            time2_dis();
            time2_interrupt_dis();
            clock_bk_off();
         }
         else
         { */  time1_temp=(time1_temp+data_y);
             PR2=(time1_temp/360);
             data_y=(time1_temp%360);
             time2_en();
             time2_interrupt_en();
             clock_bk_on();
             display();
          //}
        }
    }
/*---------------------------------------------------------------------------*/
            if   (TMR2IF)
        {     TMR2IF=0;
              display();
             
        }
 }
/*********************************************************************************/
   void    display    (void)
 {   if   ( (CLOCK_ADDR==0)||
            (CLOCK_ADDR==15)||
            (CLOCK_ADDR==30)||
            (CLOCK_ADDR==45)||
            (CLOCK_ADDR==60)||
            (CLOCK_ADDR==75)||
            (CLOCK_ADDR==90)||
            (CLOCK_ADDR==105)||
            (CLOCK_ADDR==120)||
            (CLOCK_ADDR==135)||
            (CLOCK_ADDR==150)||
            (CLOCK_ADDR==165)  )   { PORTA|=0xa;PORTB=0X18;}
      else
                                   { PORTA&=0X4;PORTB=0;}
             ++CLOCK_ADDR;
}
/************************************************************************************/
  void    main    (void)
{   unsigned int i;
    PORTA=0;
    PORTB=0;
    TMR0=0;
    mcu_init();
    while  (1)
   {   
        for   (i=10000;i>0;i--)  CLRWDT();
        mcu_init();
   }
}

使用特权

评论回复
6
emailli| | 2008-1-2 16:54 | 只看该作者

电机转速不够

50Hz的显示才可以比较稳定不闪烁

要达到50Hz的显示频率。你的电机转速要 50*60 = 3000 转/分钟

与此同时。你的中断时钟频率需要达到惊人的 0.1mS以下。

我正在考虑该程序的架构和难点。

关于供电我想到了一个方法,使用两个电机。一个用作发电机,一个用作电动机。均采用 有刷直流电机。用电动机来带动指针板和发电机。



如果程序的难点解决了。我打算做几个样板回来玩玩。呵呵!

到时候募集资金一起做啊。

使用特权

评论回复
7
程序匠人| | 2008-1-2 17:12 | 只看该作者

在中断中调用除法,可能不是好办法

PIC没有乘/除法指令。虽然,picc会用内部函数代替除法指令,但毕竟速度和消耗资源方面都不理想。所以,在中断中调用除法,可能会有问题。

匠人正在写程序,目前考虑的也是这个问题。正在考虑尽量不用到乘除法,具体算法还没有成型,程序也还没有写好。待程序调通后,会公布。

欢迎协同讨论

使用特权

评论回复
8
emailli| | 2008-1-2 22:49 | 只看该作者

我的思路是这样的

不需要在 中断内用除法的

定时中断内查表

将圆周分成360等分

每一等分亮灯为为1,不亮灯位为0,根据显示数据的不同,将360等分的数据做成一个表格。

利用红外或者霍尔器件做一个过零检测和速度检测

根据速度计算出 1°所需要的时间,用于初始化定时器

根据零点位置开始复位定时器,然后每进一次定时器意味着过了1°。

至于显示用的表格可以在主程序中计算。

这里说的可能还不是很清楚。下次整理好了再发。呵呵。

使用特权

评论回复
9
xwj| | 2008-1-3 00:24 | 只看该作者

哈哈,你不用除法怎么“根据速度计算出 1°所需要的时间”

使用特权

评论回复
10
fsaok| | 2008-1-3 07:44 | 只看该作者

猜想

1.和一周的整除毫无关系,因为可以是用外部中断来调整内部计数脉冲,可以参考彩电的行同步信号。

2.把运算放在中断外,运算结束后转入显示区使用。

3.由于红外对管的干扰比较大,要加强模拟方面的处理,必要时采用红外载波

使用特权

评论回复
11
fzj| | 2008-1-3 09:28 | 只看该作者

谢谢各位老师的分析

emailli :0.1MS的中断速度对于PIC来讲根本不是问题,因为我用的时钟为16M,而PIC的指令多数是单周期指令,虽然我写的只是个初步的测试程序,但因速度上反应不过来而造成的显示不稳定基本没有,即使我加大程序.
程序老大:就如XWJ意思,如果就一个测试周期端点,不用除法我想不到更好的办法,其实PIC是有除法指令的,只不过是在中高端单片机上,如17 18 系列的都有乘除法指令,如果真因速度来不及那好解决,您说是吗?
而我的想法正好和fsaok的想法相反,我认为造成我现在显示抖动的问题根本不在电机转数,从我所做的实验我更加肯定是一个周期时间无法给整除所引起,而关键就是这个余数补偿,相反我这个所谓的余数补偿把它去掉反而效果更加好,有时显示还比较稳定,为此我也试着多装了红外探头,目得减小误差,通电测试结果发现显示比以前稳定的许多,但还是不够稳定,我又将程序中的"余数补偿"加进去测试结果显示抖动更加厉害.
从以上实验分析我认为这个旋转显示效果要保持位置固定真的没想象的简单,而这也是本显示设计最大的难点吧.
在这里多谢各位老大的分析和建议!

使用特权

评论回复
12
emailli| | 2008-1-3 10:04 | 只看该作者

不用余数补偿的

你用除法计算出来的1°所需要的时间肯定不会是精确的1°的时间

我之所以要增加 过零点的 检测就是从一定程度上解决这个问题的。

你用除法计算出来的1°的时间 在确定定时器初值的时候,需要舍。千万不能入。

如果是舍的话,那么360次定时中断后,应当还未达到真正的360°。

但是由于有一个过零点的检测。你可以在余下的 1°或者是零点几度的角度内不显示了。

这样就实现了整个显示区域的平移。

所以,只要你的电机速度够稳定。那么,每次都是那么1°左右没有显示

照样可以稳定的显示出想要显示的数据了。

关键是 RAM用的比较多,如果用的是 8个灯以下的的旋转灯,那么,显示缓冲区一共需要 360*8bit = 360 Byte
如果用的是16个灯,则增加一倍了。

显示缓冲区第一字节就是第一次进入定时中断需要点亮的灯的位置,1为亮,0为灭
……
第10字节就是第十次进入定时中断需要点亮的位置
……
第360字节就是第360次进入定时中断需要点亮的位置数据

当第360次定时中断产生后,关闭定时器。等待过零检测信号的到来 后重新开启定时器就OK了!

这种方法,不知道各位还有什么建议没有?

使用特权

评论回复
13
程序匠人| | 2008-1-3 10:33 | 只看该作者

不用除法也可以计算出 1°所需要的时间

答复xwj ,不用除法也可以计算出 1°所需要的时间。
匠人已经有了初步的想法,待程序调通经过验证后公布。

---------------------------------------------------
xwj 发表于 2008-1-3 00:24 侃单片机 ←返回版面    

9楼: 哈哈,你不用除法怎么“根据速度计算出 1°所需要的时间”呢? 

使用特权

评论回复
14
fzj| | 2008-1-3 12:18 | 只看该作者

emailli的思路不错,但用这么多显示数据RAM是不是太奢侈了点

在最后一个角度允许有小于1度的误差,前提:必须保证电机速度严格保持稳定,否则避免不了抖动.
如果电机能保持恒速运行,那CPU就没这个"自测自调"的说法,也正因为"自测自调"破坏了显示的稳定性,这个如果CPU在时间上计算没太大的漏洞,我想你把电机恒速旋转想象的太完美了,我们先不管最后一个角度误差多大,就来说前面几个角度,你能保证精确定位?即使变化很小也会引起人眼看的到的抖动除非找一个高精度转数电机或者用高精度快反应的PWM作反馈调节.
我想这个严格定位没想象的那么简单,因为电机每旋转一周不可能US不差,如果有误差在除法运算后前后数据就有偏差,这个偏差也就是前次扫描和当次扫描角度的误差,当误差大到一定程序就造成了肉眼看的到的抖动.
而作为CPU计算上也会产生误差,每次中断前后都要备份还原一些重要的数据,而这些时间又该如何把握和补偿呢?
最"笨"的想法就是在每个角度安装一个传感器,可是数量.....无语.......

使用特权

评论回复
15
程序匠人| | 2008-1-3 12:28 | 只看该作者

回13楼emailli:这样设置显示缓冲区,是不是有点太浪费了?

如果只有8个灯,那还好说,大不了把整个圆分成180等份,也就只需要180个RAM。

但是,如果是16个或者更多的LED灯,甚至是双色的,需要切换。那需要的RAM空间可就太大了。

最好能在后台进行预处理,先把显示数据加工成“半成品”。然后在中断中再进行进一步的“精加工”。这样既可以加快中断的执行速度,又可以节省RAM资源。

使用特权

评论回复
16
xwj| | 2008-1-3 12:45 | 只看该作者

呵呵,偶滴想法就是先用奢侈的方法实现:-)

现在有开始写程序了,等试了再说:-)...

使用特权

评论回复
17
emailli| | 2008-1-3 17:09 | 只看该作者

速度不是用这个MCU控制的

我还是那句老话。要用双CPU来控制

第一个底板上的CPU用来控制转速和启动、停止。

底板CPU也要有转速测量的功能,同时还有转速控制的功能。这个应该不难。

让电机转起来后转速稳定在 3000±20应该不会很难吧!20转的差别对系统影响不大的!

虽然占空间,可是 这个可是 典型的  空间换时间的 做法哦。

呵呵。奢侈就奢侈吧。谁要这种方式速度最快呢! 

:)

使用特权

评论回复
18
程序匠人| | 2008-1-3 17:15 | 只看该作者

控制转速?

有必要吗?
没必要吗?
有必要吗?
没必要吗?
有必要吗?
没必要吗?
有必要吗?
没必要吗?
有必要吗?
没必要吗?
有必要吗?
没必要吗?
有必要吗?
没必要吗?
有必要吗?
没必要吗?
有必要吗?
没必要吗?
有必要吗?
没必要吗?
有必要吗?
没必要吗?
有必要吗?
没必要吗?
有必要吗?
没必要吗?
有必要吗?
没必要吗?
有必要吗?
没必要吗?
有必要吗?
没必要吗?
有必要吗?
没必要吗?
有必要吗?
没必要吗?
有必要吗?
没必要吗?
有必要吗?
没必要吗?
有必要吗?
没必要吗?
有必要吗?
没必要吗?

使用特权

评论回复
19
emailli| | 2008-1-3 20:12 | 只看该作者

调速还是有必要的

我觉得调速还是有必要的

并且还是很有必要的哦。

使用特权

评论回复
20
wangkj| | 2008-1-4 16:32 | 只看该作者

不用可以控制转速

完全没有必要,我第一版程序控制了转速,后面的没用,主要是起始点的检测。
汉字显示总共用了不到10行程序。

使用特权

评论回复
发新帖 我要提问
您需要登录后才可以回帖 登录 | 注册

本版积分规则

FZJ

32

主题

184

帖子

3

粉丝