实验一转速测量与控制(一)

时间:2023-03-08 09:37:01 其他毕业论文 我要投稿
  • 相关推荐

实验一转速测量与控制(一)

由速度传感器可以将测得的电机转速转换成相应的电压信号,该信号经整形
放大后送到CPU。CPU将采集来的数据经过一定的算法处理后,送给D/A转换芯片,该芯片将数字信号转换为模拟信号输出,模拟信号经信号放大后,由弱电变为强电,从而实现电机转速的控制。另外CPU与外界的交互通过I/O接口来实现。

 硬件电路设计原理
 1)信号产生与放大整形
 
①速度传感器
 转速传感器将电动机转速转化为电压信号,作为输入。
本实验中采用光电式转速传感器,其工作原理是:利用电动机带动一个圆周上有均匀分布小孔的圆盘来控制发光二极管的光强,使光的强度呈周期性变化。光电二极管的回路电流也呈周期性变化,频率f=N/60×360=6N Hz,其中N为转速,单位为 R/min。
 ②信号整形放大
 信号整形放大部分用于将传感器输出的幅值较小的电压信号进行放大整形,使其信号电压与芯片驱动电压相匹配,并除去部分干扰,使输出波形为方波的形势。
 本实验中电动机、光电传感器、信号放大整形电路都集成在一起,封装于一个圆柱形容器内。输出的信号经过经过反向器和缓冲器后输送给82C50单片机T0管脚。
 2)数据采集与处理
 电路板上有一个由555集成定时器构成的单稳态触发器,提供1秒钟的定时,来控制74HC244缓冲器的通与断,这样单片机计数器一次所累积的数即为脉冲频率,经换算后可得到电动机的转速。
 ①单稳态触发器
 
555定时器是一种多用途的时基电路,只要在外部配上几个适当的电阻、电容,就可以构成单稳态触发器。
 输出电压高电平的时间取决于RC的充电时间。
单稳态触发器的输出信号,控制缓冲器74244的通断,测得的电压信号通过缓冲器接到8052的T0端口。在这里缓冲器起到了增加驱动、消除干扰的作用。
 ②单片机
 
本实验所用CPU为8052,如上图,当为高电平时,CPU执行片内程序存储器命令。当为低电平时,CPU实行片外程序存储器命令。
在本实验中单片机主要负责数据的数据采集、数据处理、与键盘显示的交互控制、以及直流电机的控制。
 3)键盘与显示部分
 ①I2C串行总线接口7290
ZLG7290芯片功能强大,I2C 串行接口提供键盘中断信号方便与处器接口并可驱动8 位共阴数码管或64 只独立LED 和64 个按键。因为ZLG7290采用I2C串行总线,而AT89C52内部没有集成I2C总线接口,因此利用软件模拟I2C总线接口功能。本实验中采取的是24个管脚的封装形式。
 如前所述, 7290的SDA、 SCL管脚与8052P10、P11口相连,中断管脚与8052的INT0相连,Dig0—Dig8连接LED 显示位驱动及键盘扫描线;Seg0—Seg8连接LED 显示段驱动及键盘扫描线 OSC1、OSC2管脚接外部晶振,RES脚接上电复位电路。
 ②键盘及数码管
数码管的左四位显示数值为当前所处状态,右四位显示数值为对应状态的数值。以数值表示的状态含义如下:
0101――当前电机转速
0102――设置电机转速
 4ⅹ4键盘布键如下:
 
 测量当前电机转速,则按一下“电机”键,数码管右四位即表示当前电机转速;若要改变转速,则按一下设置键,这时,数码管左四位显示“0102”,即可进行设置转速,设置好后再按“确定”键。再按一次“电机”键,即可看到电机当前转速,再按一次又回到设置转速;设置时如想修改,按“取消”,即可重新输入设置值(设置值500-2500R/M,否则无效)。
  4)、控制电路
①D/A转换芯片TLV5618
 12位双通道串行接口;可编程设置转换时间,高速模式下为2.5us,低速模式下为12us;89C52将保存的设置预期转速值转换成串行数据输出到5618的SDI端,从SDI端输入的数字信号经TLV5618转换成模拟信号,由OUTB端输出,经放大后作用于直流电机,达到闭环控制目的。
 
    ②信号放大器
 直流电机的驱动电流和电压都比较大,而D/A输出的信号电压和电流比较小,电压范围为0-5V,不能直接驱动,中间要经过电压、电流放大。原理图如下:

 针对ZLG7290的I2C总线读写程序如下:
/*头文件说明*/
#include <AT89x52.h>
#include <Intrins.h>
#include <math.h>
/*定义8052的端口*/
#define iscl P1_1
#define isda P1_0
#define sdi  P1_2
#define sdo  P1_3
#define sclk P1_4
#define rd1  P3_5
/*指针定义*/
unsigned char xdata *p=0x8001;
unsigned char xdata *adp=0x8004;
unsigned char s=1,num=1,need=1,new=0,lp=1;    /*the number of project */
unsigned char display[]= /* display array */
              {0,0,0,0,1,1,3};
unsigned int r1,r2=0,r3=0x0;   /*rotate speed r1测量所得温度,r2设置所得温度*/
unsigned char f1=0;  /* times and congiguration flag ,设置完温度完成标志 f1=1*/
unsigned int  bri=0;  /* the value of configuration  设置值*/
unsigned char m1=0;   /* 设置值的最大位数 */
/*延时*/
void delay_ms(unsigned int x)
{
  unsigned int i,j;
  for (i=0;i<x;i++)
    {j=108;
     while (j--);
     };
 }
/*延时*/
/*I2C总线的操作*/
void i2cwait(void)  reentrant 
  {
        _nop_();
   }
void i2cinit(void) /*i2c总线的初始化*/
{ isda=1;
  iscl=1;
  }
void i2cstart(void) /*i2c总线启动,在串行时钟iscl为高电平时,串行数据isda出现一个下降沿*/
{
    isda=1;
    iscl=1;
    i2cwait();
    isda=0;
    i2cwait();
    iscl=0;
 }
void i2cstop(void) /*i2c总线停止,在串行时钟iscl为高电平时,isda出现一个上升沿*/
{
    isda=0;
    i2cwait();
    iscl=1;
    i2cwait();
    isda=1;
    //i2cwait(); /*加两条语句,保证串行时钟iscl为低电平,准备数据,即isda只能在iscl为低电平期间改变*/
    //iscl=0;
  }
unsigned char  i2csentbyte(unsigned char b) /*发送一个字节*/
{
  unsigned char i,ack=1;
  for (i=0;i<8;i++)
    {
      if (b & 0x80)  /*i2c总线,先发送最高位(总共八位),通过&运算测试最高位*/
      isda=1;
      else
      isda=0;
      b<<=1;
      i2cwait();
      iscl=1; /*在串行时钟iscl为高电平期间,串行数据isda线上的数据必须稳定,否则被认为是启停控制信号*/
      i2cwait();
      iscl=0;
      i2cwait();
     };
  isda=1; /*代替接收方发送一个应答位,这种情况出现在CPU发送数据时*/
  i2cwait();
  iscl=1;
  i2cwait();
  ack=isda; 
  iscl=0;
  i2cwait();
  return ack ;
    }
void sendacknowlege(unsigned char ack) /*在每个字节后必须跟一个应答位,由接收方发送*/
  {
   isda=ack;
   iscl=1;
   i2cwait();
   iscl=0;
   i2cwait();
   }
unsigned char  i2creceivebyte(void) /*接收一个字节*/
 {unsigned char i,a=0;
  for (i=0;i<8;i++)
    {
     iscl=1; /*在正常数据传送状态下,iscl的高电平都对应于isda的稳定数据状态*/
     i2cwait();
     a<<=1;
     if (isda==1)
       a|=0x01;  /*通过按位或|和按位与&及循环运算,将数据读出并赋给变量a*/
       else
       a=a&0xfe;
     iscl=0;
     i2cwait();
     };
   return a;
   }
void writecmd7290(unsigned char i,unsigned char k) /*ZLG7290寄存器映象控制*/
   {
          EA=0; /*CPU屏蔽所有的中断申请*/
          delay_ms(1);
          i2cinit();
      i2cstart();
   i2csentbyte(0x70); /*ZLG7290的从地址为70H*/
   i2csentbyte(i);
   i2csentbyte(k);
     i2cstop();
          EA=1;  /*CPU开放所有的中断申请*/
     }
void writedata7290(unsigned char i,unsigned char k)  /*ZLG7290命令解释控制*/
   {
          EA=0;  /*CPU屏蔽所有的中断申请*/
          delay_ms(1);
          i2cinit();
      i2cstart();
   i2csentbyte(0x70);  /*ZLG7290的从地址为70H*/
          i2csentbyte(0x07);  /*命令缓冲区0地址*/
   i2csentbyte(i);  /*写命令缓冲区0*/
   i2csentbyte(k);  /*地址自动增加,写命令缓冲区1*/
     i2cstop();
          EA=1; /*CPU开放所有的中断申请*/
     }
unsigned char read7290(unsigned char i)
    {unsigned char x=0;
      EA=0;  /*CPU屏蔽所有的中断申请*/
      delay_ms(1);
      i2cinit();
      i2cstart();
   i2csentbyte(0x70);  /*ZLG7290的从地址为70H*/
   i2csentbyte(i);
   i2cstart();
   i2csentbyte(0x71);  /*71H ?*/
x=i2creceivebyte();
   sendacknomlege(0x1);
   i2cstop();
   return x;
         // EA=1;  /*中断开放在后边的中断子程序执行完之后才开放*/
     }
/*I2C OPERATION 2*/
/* 5618 operation */
void write5618(unsigned int k)
{unsigned int i,j;
  EA=0; j=k;  /*CPU屏蔽所有的中断申请*/
  P1=P1&0x5f;  /*5618地址,使能芯片*/
   _nop_();
  for (i=0;i<16;i++)  /*发送2字节数据:高四位是编程位,低12位是需要转换的数据*/
   {
    if (j&0x8000)
      sdi=1;
     else
      sdi=0;
    j<<=1;
    sclk=0;
    _nop_();
    sclk=1;
    };
    _nop_();
    _nop_();
  P1=0xff; /*使能结束*/
  EA=1;  /*CPU开放所有的中断申请*/
}
/* 5618 operation */
/*initial COUNTER0*/ 
void init_time0()  /*初始化计数器0*/
{ TMOD=0x85;  /*T0:不受外部引脚控制,外部事件计数方式,工作方式为方式1,16位计数器*/
 TH0=0;  /*加计数寄存器高八位为0*/
 TL0=0;  /*加计数寄存器低八位为0*/
 TCON=0x10;  /*中断控制寄存器:计数器运行控制位TR0=1;外部中断源触发方式控制位IT0=0,电平触发*/
  }
/*initial COUNTER0*/
main()
{ unsigned int temp,t3=0xc100;
  unsigned char i=0;
  IE=0x95;IP=0x01;  /*IE:EA=1中断开放,ES=1允许串口中断,EX1=1,EX0=1外部中断1,0允许*/
      /*IP:PX0=1 外部中断0定义为高优先级中断*/
  P1=0xff;P3=P3|0x30;  /*端口初始化:P1为高电平;P3_5=1读AD7865信号无效,P3_4=1*/
init_time0();
/*initiate 5618*/    
 write5618(0x4000);  /*设置DAC B为输出,选择快速模式*/
 write5618(0xc000);  /*设置DAC A为输出,选择快速模式*/
 /*initiate 5618*/
 /* motor measure start */
  P1=P1&0x3f;            /* triger 555  电机测速使能*/
  _nop_();
  P1=0xff;
 /* motor messure start */
 /*7290*/
  writedata7290(0x65,0);  /*按位下载数据且译码指令:第五位显示'0',不闪烁,小数点不点亮*/
  writedata7290(0x67,0);  /*按位下载数据且译码指令:第七位显示'0',不闪烁,小数点不点亮*/
 /*7290*/
 while(1)
   {
    /*display*/
     if (need==1)  /*初始need=1,被显示的数据更新后need=1,做为显示更新标志need=1*/
     { writedata7290(0x64,display[4]);  /*按位下载数据且译码指令:初始第四位显示'1',不闪烁,小数点不点亮*/
       writedata7290(0x66,display[5]);  /*按位下载数据且译码指令:初始第六位显示'1',不闪烁,小数点不点亮*/
       writecmd7290(0x13,0x0);  /*初始向显示缓存寄存器DpRam3写0,即第三位不点亮*/
       writecmd7290(0x12,0x0);  /*初始向显示缓存寄存器DpRam2写0,即第二位不点亮*/
       writecmd7290(0x11,0x0);  /*初始向显示缓存寄存器DpRam1写0,即第一位不点亮*/
       for (i=0;i<display[6];i++)/*初始第零、一、二显示'0',不闪烁,小数点不点亮*/
          writedata7290((0x60+i),display[i]);
       need=0;
       };
     /*display*/
  /* read speed and temperature and electricity*/
    i=*p;  /*7865状态地址(只读):0x8001 */
    if(!(i&0x08))   /*电机一次测速完成时执行*/
      {
        r1=TH0;r1=(r1<<8)+TL0;  /*将计数器所计的数值赋给r1*/
        r1=(int)(r1*3/10);  /*?*/
        TH0=0;TL0=0;EA=0;  /*将计数器清零,为下次计数做准备;关闭中断*/
        P1=P1&0x3f;   /* triger 555 电机测速使能*/
        P1=0xff;EA=1;  /*测速使能完成;开放中断*/
        if(!(new&0x80))  /*初始new=0*/
          if(num==1)  /*初始num=1*/
               new|=0x01;  /*new=1*/
       };
        if(f1)  /*初始f1=0;设置完温度后 f1=1 */
         {f1=0; r3=(3*r2/2); 
          if(r3>0x0fff)  /*D/A变换器是12位的*/
            r3=0x0fff;
            };
          if ((r2>r1)&&(r3<0x0ff9))
               r3=r3+4;
          if ((r2<r1)&&(r3>0x05))
                r3=r3-4;
            write5618(r3+0x4000);  /*转速控制,设置DAC B为输出,选择快速模式*/
/*update display array*/
   switch(s)  /*初始 s=1*/
     {
 /*测速情况*/
        case 1:display[5]=1;
               if(num==1)  /*num=1  0101――当前电机转速*/
                if (new&0x01)  /*(初始new=0x03;)设定转速后new=0x01*/
                  {new&=0xfe;i=0;  /*将new清零*/
                   display[4]=1;
                   display[0]=0;
                   need=1;  /*数码显示更新标志,下次循环时,将改变数码管显示的值*/
                   temp=r1;
                   while (temp!=0)  /*将个、十……为依次放入数组display[i]的前几位*/
                    {display[i]=temp-(int)(temp/10)*10;
                     temp=(int)(temp/10);i++;
                      };
                   if(i==0) i=1;
                   display[6]=i;  /*数组的第六位代表所存数字的位数*/
                   };
                if (num==2)  /*0102――动态显示设置电机转速的过程*/
                   {if (new&0x08)  /*设置速度时new=0x88*/
                      {need=1;new=0x80;  /*显示更新标志need置1*/
      /*将new置0x80,防止设置间隙时,此段程序继续执行,提高效率*/
                       display[4]=2;
                       display[0]=0x40;  /*?*/
                       temp=bri;i=0;
                       while (temp!=0)
                         {display[i]=temp-((int)(temp/10))*10+0x40;
                          temp=(int)(temp/10);i++;
                           };
                        if(i==0)
                          i=1;
                        display[6]=i;
                        };
                     if (new&0x01)  /*显示设置结果:“确定”显示新设置的值,“取消”显示上次设置的值*/
                      {need=1;new&=0xfe;  /*将new清零,显示更新标志need置1*/
                       display[4]=2;
                       display[0]=0x0;
                       temp=r2;i=0;
                       while (temp!=0)
                         {display[i]=temp-(int)(temp/10)*10;
                          temp=(int)(temp/10);i++;
                           };
                        if(i==0)
                           i=1;
                        display[6]=i;
                        };
                      };
                break;
      };
/*update display array*/
   };
  }
void ext0() interrupt 0 using 3  /*外部中断0中断服务函数:键值处理*/
{
  unsigned char b=0;
   delay_ms(40);
   {
   b=read7290(0x01);  /*读键值寄存器的值*/
   switch(b)
    {/*键盘:电机键*/
     case 33:new=0x01;//new=new&0x67;
            if(s==1)
             {if (num==1)
                num=2;
             else
                num=1;}
             else
              {s=1;num=1;
                };
             break;
     /*键盘:温度键*/
     case 34:new=0x02;//new=new&0x67;
             if (s==2)
               {if (num==1)
                  num=2;
               else
                  num=1;}
              else
                {s=2;
                 num=1;
                  };
             break;
     /*键盘:电量键*/
     case 35:new=0x04;//new=new&0x67;
             if (s!=3)
               {s=3;
                num数: A=K2/K1=4.89
 转速曲线:Vm+  = 0.0077R + 0.87
             VoutB =0.0016R + 0.52
1、转速R与控制电压VoutB关系曲线

2、转速R与电机控制电压Vm关系曲线

实验心得
通过这个实验,使我对测速传感器的工作原理有了一定的了解,并掌握了硬件电路的基本原理,以及软件的设计方法。
 硬件电路中,用到了许多以前没有接触的芯片,如7865,7290,5618等等,对于它们的使用方法,必须从头学起,阅读英文的说明书,虽然颇费一番工夫,但在了解芯片的用法的同时,更提升了我阅读英文参考资料的能力。
 从老师所提供的完整的电路图中,抽取出各个部分的电路图,就是建立在
对实验原理框图的掌握和对芯片的了解的基础上的。
 分析软件电路时,用到了单片机的知识,由于程序均为用C51编程的,这就不得不在温习、学习一下这方面的知识。C51特定的函数,以及一些控制字的写入,中断程序的设定,与外部器件的接口,都必须叫熟练的掌握,为此我在写实验报告时,又参阅、学习了一些单片机的书籍。通过学习使我对单片机的应用有了更深一步的了解。
 最后,将实验测得的数据,用MATLAB语言画出拟合的曲线,从曲线上可以明显看的实验数据的准确与否。
 感谢张老师的指导,老师在讲解实验原理时是那么的清晰、细致,指导实验
时是那么的耐心,这为我完成实验报告、掌握知识,提供了极大的帮助。
 这次实验使我受益匪浅

【实验一转速测量与控制(一)】相关文章:

消防联动控制系统(一)05-11

ADVANTECH喷油泵实验台微机控制系统解决方案05-31

小型热水锅炉单片机温度控制系统(一)08-10

智能控制及其在机电一体化系统中的应用(通用5篇)05-23

城市GPS控制网施测质量控制措施探讨05-28

内部控制审计评价初探06-03

控制税收征管成本的探讨06-01

一物一权原则质疑12-06

刑事侦查权的司法控制05-11

建立内部控制审计与组织效率06-03