压电陶瓷换能器导纳圆图示仪的制作方法

文档序号:6999738阅读:691来源:国知局
专利名称:压电陶瓷换能器导纳圆图示仪的制作方法
技术领域
本发明是一种涉及物理学中声学领域的、有关压电陶瓷换能器导纳测量的装置。
压电陶瓷换能器是声学领域用于产生和接收声的一类晶体物质。在使用压电陶瓷换能器之前需要知道其主要参数才可以实施应用,其参数主要包括共振点频率、静电容(C0)、动态阻抗(R1、C1、L1)、机电耦合系数、等效频宽、机械品质因素Q、温度稳定性等。如果能够测出压电陶瓷换能器的在共振点附近的一段频率范围内的导纳值,就可以分析提取出以上所需的参数。由于在这一段频率范围内的导纳值在导纳复数坐标上形成一个近似的圆,故称之为导纳圆。
压电陶瓷换能器导纳圆图示仪是用于对压电陶瓷换能器的导纳特性进行分析,从而获取其主要的参数的仪器。它主要用于指导压电陶瓷换能器的检测和使用,是对压电陶瓷换能器进行有效的测量、分析或合格/不合格测试的综合性解决方案。
目前关于压电陶瓷换能器的导纳圆检测一般由两种方法,一是采用从美国进口的、通用的阻抗分析仪来做压电陶瓷换能器的导纳圆检测。例如Agilent4192A(原为HP4192A),但是其价格非常昂贵,大约在2-3万美元左右,国内拥有此仪器的不多。而且它没有和PC机相连接,需要自己开发和计算机的接口和以及专门用于压电陶瓷换能器的程序,用于对换能器的参数进行分析、提取、打印输出。Agilent4192A的应用面较广(做压电陶瓷换能器的导纳检测只是其一部分功能),所以其性能指标也很高,导致检测装置复杂,成本很高,而且做压电陶瓷换能器的参数分析提取也不方便。
另外一种方法是采用通用的波形发生器进行逐点扫描,并用示波器记录读数,将其导纳圆描绘出来,然后得到压电陶瓷换能器的参数,此方法不仅费时费力,而且精度不高。
微电子技术的发展,使得获得频率可精确控制的信号源成为可能。随着个人电脑的普及应用,在PC上开发应用程序,将硬件和软件结合起来,开发一种成本相对较低的、专门用于压电陶瓷换能器导纳圆测定的仪器,便可以解决以上矛盾。
由于电流值不容易检测到,解决方法是在支路中串联一个电阻,由于电阻上的电压值和电流值成正比,所以检测到电阻上的电压值就能得到支路电流值。由于针对不同用途的换能器,其动态阻抗R1的范围很宽,从几欧姆到几千欧姆,因此为了保证检测的精度,所串联的电阻值需要可调节,以避免电阻上的电压太大或太小,以致于难以检测。其原理电路如图2所示,其中Us为正弦激励信号、R为电源内阻、RM为支路串联电阻、L为压电陶瓷换能器。由图2可知换能器的阻抗Z为Z=uA-uBuB/RM=RM|uAuB-1|]]>(uA为支路两端电压、uB为电阻RM两端电压)设uA=KAejwt,uB=KBej(ωt+)可得UAMUBM=KAKB]]>(UAM为uA的峰值、UBM为uB的峰值)则 式中 (R为阻抗的实部) 1) (X为阻抗的虚部) 2)换能器的导纳Y为Y=1Z=RR2+X2+jXR2+X2=G+jB]]>(G为导纳的实部、B为导纳的虚部)由式1)与2)可知,换能器的导纳是复数,只要测出不同频率下的UAM、UBM、Cos的数值,然后知道RM大小,就可以得到换能器的导纳特征。
2.硬件设计硬件部分通过普通的九针串行口与计算机通信。硬件分为三部分1)信号发生电路在实际应用中需要产生分辨率为1Hz的正弦信号,频率的稳定度在1Hz以内,频带范围为1Hz~0.5MHz。采用模拟方式难以满足要求,因此采用直接数字合成(DDS)的方式得到正弦信号。其特点是频率精度高、容易精确控制。向DDS芯片发送频率控制字,就可以输出相应频率的正弦波信号。美国Analog Device公司推出的DDS系列芯片如AD7008、AD9850均可以实现直接数字合成频率的功能。
下面简单介绍AD7008的结构和性能AD7008是Analog Device公司采用先进的直接数字合成(DDS)技术,推出的高集成度频率合成器。它内部包括32位相位累加器、余弦/正弦表、高性能10位DAC、与微机的串行和并行接口以及控制电路等,能实现全数字编程控制式的频率合成。接上精密时钟源,AD7008即可产生一个频率和相位都可编程控制的正弦波。AD7008在20MHz的晶振下工作时,其输出频率分辨率可达0.047Hz,最大输出频率可达5MHz。
AD7008接口控制比较简单,可以用8位或16位并行口或单行口直接输入频率、相位、以及调幅幅度等控制数据。这里采用串行的SPI口和AT89C51连接,指需要将AD7008的SDATA、SCLK、LOAD接到单片机的输出口上便可以实现对AD7008输出频率的编程控制。AT89C51只要以串行方式输入32位的相位累加器值ΔPhase就可以改变频率,相位累加器值和频率的关系如下f=ΔPhase×fCLOCK232(0≤ΔPhase≤232).]]>其中fCLOCK为晶振频率。AD7008输出的正弦信号需通过运放进行放大,主要目的是为了提高其带负载的能力。在用于测量较高阻抗的换能器的时候,用普通的运放就可以了,比如NE5534、NE5532、AD818都可以。如果涉及测量较低阻抗的换能器,就需要使用功率较大的运放,即可以输出较大电流的运放,如National Semiconductor公司的LM3875、LM3886等等。在使用LM3875、LM3886的时候,其闭环放大倍数必须大于10,系统才能够稳定。
这里只能通过增强运放的带负载能力、而不能通过增大支路串联电阻的方法来避免运放过载,其原理如下如果将串联电阻加大,可以避免运放过载,但是在很多情况下,会导致测量的误差非常大,甚至出现无法检测出频率变化时的导纳变化情况。
2)运算和数据采集电路由于压电陶瓷换能器的等效电路中含有电容和电感,因此在不同正弦信号的激励下,会呈现出不同的导纳特性。为了能够检测到其导纳特性,需要将电路中体现出其导纳特性的因素通过运算电路转换成可检测到的电压量,然后通过A/D变换电路采集获得。运算电路分为两部分峰值检测电路和相位检测电路。峰值检测电路用于检测动态变化的正弦信号的峰值电压。相位检测电路用于检测两路正弦波的相位差值,相位差在-90°~+90°的范围内变化,需要将其转化为0~5V的电压量。转换成电压量之后,就可以通过12位的A/D变换器采集获得。运算电路请参考图3。
ux与uy的相位差用高精度模拟乘法器检测。模拟乘法器的输出为 用低通滤波器将上式中的二倍频项滤去,即可得 于是可以得到 ,由于ux、uy的峰值UXM、UYM可用峰值检波器求得(峰值检波电路请参考图4),据上式就可以得到相位差的余弦。
在实际电路设计中,采用美国Analog Device公司的集成四象限模拟乘法器AD633、AD534、AD734或者Texas Instrument公司的MPY634均可以实现求相位差的功能。
峰值检波电路如图4所示,电路中需要用到两个运放,第一个运放IC1必须是高速运放,要求增益带宽积大于50M、电压摆率大于500V/μs。AnalogDevice公司的AD818或者National Semiconductor公司的LM6171、LM6161均可以满足要求。运放IC2采用低速运放即可,普通的National Semiconductor公司的LF411就可以满足要求。D1、D2为快恢复二极管,可以选用1N4148或者肖特基二极管。C2和R2确定峰值电压的保持时间,C1可以取0.1μF,R2可以取10MΩ。R1可以取2KΩ,C1和R3用于调整精度,可根据实际电路调节其大小。
A/D变换器可以选择Texas Instrument公司的TLC2543,或者Maxim公司的MAX147。它们通过SPI总线和处理器连接,能较好地满足本系统中的数据采集工作。TLC2543可以用MAXIM的REF02作为电压基准源,REF02其输出为+5V,稳定稳定性为3ppm/℃。
3)通信电路电路中由单片机(下位机)负责与PC(上位机)的通信。通过计算机软件向下位机发送指令,单片机执行指令后,将采集到的电压量发送给上位机。在工作的过程中,上位机发送频率命令给下位机,下位机控制产生相应的频率信号,同时将这个频率下的、用来表征压电陶瓷换能器导纳特性的三路电压量采集并反馈给上位机。系统采用美国ATMEL公司的AT89C51作为下位机,通过AT89C51的串行口和上位机通信。由于计算机串行口用的是RS232电平,而AT89C51则是CMOS电平,中间需要用美国MAXIM公司的MAX232实现其电平转换功能。MAX232只需要+5V单电源工作,使用方便。
下位机和上位机的波特率必须一致才能够通信,由于数据量不大,因此采用典型传输速率9600bps就可以。AT89C51的波特率通过其内部的定时器设定,其外部晶振频率使用11.0592MHz(9600的整数倍),设置寄存器TH1=0xFD就可以设置波特率为9600bps。
3.软件设计本发明的软件部分由Microsoft Visual C++6.0编写。在window2000或更高的版本上运行。软件按功能可以分为三部分1)数据通信功能将操作者的命令发送给下位机,同时从下位机接受反馈回来的数据。命令通过计算机的串行口(COM1、COM2、COM3、COM4)发送给下位机。在Visual C++中,通过Windows API函数完成与下位机的通信。其主要所用的函数介绍如下CreateFile打开串行口 SetCommState设置串口波特率PurgeComm清空串行口的缓冲区 WriteFile 向下位机发送数据ReadFile从下位机接收数据。
上位机和下位机以主从方式工作,上位机发送命令,下位机反馈数据。上位机发送频率命令,命令的结尾以“H”为标志,当下位机接收到“H”后,执行命令,即输出相应频率正弦信号,然后等待0.5秒后,采集A/D变换的结果并发送给上位机,其结果为12个字符的字符串,分别代表着三个电压值(每四个字符代表一个电压值)。所有的数据均以ASCII码的形式传输,即把频率和电压均按位转换成ASCII码之后才发送出去。因此在上位机和下位机上,都有ASCII码与二进制码之间进行互相转换的子程序。
2)用户界面用户可以在软件上选择支路串联电阻的大小,以及扫描的起始频率,扫描的终止频率,扫描时的频率步进等等。用户界面还包括图形显示窗口,数据保存和图形打印输出的人机操作接口,以及测量结果的显示等等。用户界面请参考图5。
用户首先选择与设备相连接的计算机串行口号,点击 然后从键盘输入输出频率扫描的起始频率、终止频率、频率步进, 再点击 系统即开始进行扫描,并以每点0.6秒的速度,在左边的G-B坐标上,从原点开始,按顺时针方向绘出所测量压电陶瓷换能器的导纳圆。同时在右边的坐标上作出G-F图和B-F图。(G导纳实部,单位为ms;B导纳虚部,单位为ms;F频率,单位为Hz)。扫描过程中可以点击“停止”来终止扫描。扫描过程中的频率值、相位差、导纳实部、导纳虚部这些数据均在屏幕上实时显示出来,并同时保存在一个类成员变量中。
扫描完毕后,用户可以点击屏幕坐标系上的任一点,程序自动读出并显示所点击处的坐标值。
程序分析得出的参数结果显示在屏幕的右上角。
3)数据处理功能包括作图、数据分析、参数提取、打印输出、数据保存等等功能。在检测的过程中,实时地将数据在G-B坐标和G-F、B-F坐标上显示出来,由于坐标大小不能改变,因此程序会对所测数据作归一化处理,即根据实测到的导纳值自动选取坐标刻度。
当所有的数据检测完毕后,通过寻优算法将所获得的图形拟合成一个规则的圆,然后就可以分析出压电陶瓷换能器的参数。作图完毕之后,软件会根据有关压电陶瓷换能器导纳圆的理论,计算出换能器的各项参数,例如共振点频率、静电容(C0)、动态阻抗(R1、C1、L1)、机电耦合系数、等效频宽、机械品质因素Q等等。
本发明所述的技术方案针对压电陶瓷换能器导纳圆的检测有很多优势精度高、针对性强,使用简单、快捷;而且连接上笔记本式电脑就可以可以直接应用于工业现场的检测;更重要的是和进口仪器相比其成本非常低廉,具有很大的价格优势。


图1(a)是压电陶瓷换能器的符号,图1(b)是压电陶瓷换能器共振频率附近集总等效电路。C0为静态电容,L1为动态电感,C1为动态电容,R1为动态电阻。
图2是检测电路的基本原理示意图。R为电源内阻,uA为正弦信号源电压,uB为支路串联电阻电压,RM为支路串联电阻,L为压电陶瓷换能器换能器,Us为正弦信号源。
图3是信号运算电路原理示意图。其中uA为激励电源电压,uB为支路串联电阻电压,RM为支路串联电阻;UAM为uA的峰值,UBM为uB的峰值,Uxm为uX的峰值,Uym为uy的峰值;Ka、Kb、Km、Ko为比例系数;Uo为uxy放大Ko倍之后低通滤波后的电压值。
图4是正弦信号峰值检波电路,用于检测出正弦信号的正峰值电压。其中IC1、IC2为运算放大器。
图5是程序的用户界面,界面上面部分的左边是用户操作部分;界面上面部分的右边是参数显示部分;界面的下边是图形显示部分。
图6是电路的原理图,有关电路技术方案的具体细节都体现在图中。
图7是电路的PCB图(印刷电路图),图上的元件符号与图6的原理图一致。
图8是根据本技术方案设计的样机对一个压电陶瓷换能器的导纳圆测量结果。
图9是进口仪器HP4192A对图8中所测的换能器的测量结果。
方案的实施分为四个部分电路原理图、电路PCB(印刷电路板)图、单片机(下位机)程序、PC机(上位机)程序。
1.电路原理图
原理图请参考图6,IC1为单片机AT89C51,IC2为AD7008AP20。AT89C51通过P0.0、P0.1、P0.2三个口控制AD7008 AP20。AD7008AP20为工业级,外接晶振最大为20MHz,由于晶振直接影响到其输出频率的精度,因此要使用精度比较高的晶振,最好是恒温晶振。
AD7008输出的正弦信号的幅度由R1、R2、R3三个电阻决定,其满幅度输出电流的计算公式如下IOUTFULL-SCALE=6233×VREFR3]]>其中VREF=1.27V(内部参考电压)当取RSET=390Ω、R1=R2=39.9Ω时,其输出信号的幅值约为1V。其输出电压经过运放差分(IC10/NE5534)放大之后,其输出电压幅值为5V。由于NE5534的内阻较大,不能用于功率较大的输出,如果需要较大功率,需要使用功率运放,例如LM3886等。
IC17(NE5534)、IC12(LM6171)、IC13(LF411)用于测量uA的峰值;IC18(NE5534)、IC14(LM6171)、IC15(LF411)用于测量uB(uA、uB的定义请参考图2或图3)的峰值。R9、R34、R35和开关SW1、SW2用于调节换能器支路串联电阻的大小。IC17、IC18为正向放大电路,其中IC17放大倍数Ka=1.5,IC18放大倍数Kb=2(Ka、Kb的定义请参考图3)。
IC3为四象限模拟乘法器AD633,其输出对输入的运算公式为W=(X1-X2)(Y1-Y2)10V+Z]]>这里X2=Y2=Z=0,Km=1/10。IC16(NE5534)为正向放大电路,其放大倍数Ko=5(Km、Ko的定义请参考图3)。放大后的电压经过低通滤波后得到直流分量,采用RC滤波方式,时间常数取0.01秒(R=100Ω、C=100μF)。
根据图3,Uxm,Uym,Uo三部分电压经过A/D变换器TLC2543采集进来,换能器的阻抗或导纳的计算公式如下(其中R10=3K、R11=2K)UAMUBM=UxmUym·KbKa·R10+R11R11=UxmUym·103]]> 将上式 和Cos代入到下面两式中,就可以得到换能器在当前频率下阻抗的实部和虚部 (RM为换能器支路串联电阻值,对应图6中R9、R34、R35) 将R值和X值代入到下式中,就可得到换能器在当前频率下导纳的实部G和虚部BY=1Z=RR2+X2+jXR2+X2=G+jB]]>串行通信中用MAX232作RS-232电平与CMOS电平之间的转换,串行通信只需要三条线和PC的九针串口连接就可以进行全双工通信,分别是TXD、RXD、GND。
电路板的电源由变压器提供,因为需要有两路电源,分别提供正电压和负电压,因此选用带中间抽头的双15V变压器,变压器的输出端经过1A600V的整流桥堆后变成直流,然后用1000μF/50V的电容滤波,出来的电压再经过三端稳压器7815、7915、7805之后就可以给芯片供电。
系统中涉及到模拟放大电路的,其相关电阻都需要使用精密电阻,才可以保证放大的倍数是准确的。系统中需要用0.1%精度的电阻有R5、R6、R7、R8、R9、R10、R11、R13、R14、R16、R17、R31、R32、R34、R35;系统中需要用0.5%精度的精密电阻有R1、R2、R3。
2.电路印刷电路图(PCB图)PCB图请参考图7,其中深色的线条为顶层走线(TopLayer),浅色的线条为底层走线(BottomLayer)。除了AD7008外所有的芯片均采用双列直插式封装。AD7008为PLCC44封装,为了便于调试,采用了PLCC插座。
PCB图分为三个部分,最上面为电源部分,包括三个三端稳压器和一个整流桥堆及相关的滤波电容,所有的三端稳压器都需要加散热片。电源部分下面的左边是数字电路部分,右边是模拟电路部分,PCB图设计采用了数字模拟分区布线的方式,其中AD7008和TLC2543既涉及到模拟电路,又涉及到数字电路,因此将它们放置在模拟部分和数字部分的交界处,这样做可以尽可能地减少干扰。由于电路中既有模拟电路,也有数字电路,为提高抗干扰能力,需要避免数字回路和模拟回路的叠加。
3.单片机程序AT89C51使用8051内核,并在此基础上扩展了FLASH程序存贮器。程序用Franklin C51编译,其主程序如下,注释请参考程序右边
<pre listing-type="program-listing">#include″reg51.h″/*编译器提供的寄存器定义头文件*/unsigned char recieve;unsigned char buffer[8];unsigned char buffer_pointer=0;char send_buffer[12];unsigned char send_buf_pointer=0;unsigned long ad7008_reg;#include″delay.h″#include″ad70082.h″ /*和AD7008操作相关的头文件*/#include″ad.h″ /*和TLC2543操作相关的头文件*/#include″math.h″bit flag1=0;unsigned long freq=0;unsigned int ad_channel1;unsigned int ad_channel2;unsigned int ad_channel3;sbit red_led=P0^5;void delay_time(unsigned int n); /*延时子程序*/void convert_char_to_freq();/*将表示频率的ASCII码转换成二进制数的子程序*/void convert_ad_result_to_char(); /*将AD变换的二进制结果转换成ASCII码的子程序*/void main() /*主程序*/{int s;red_led=0;SCON=0x50; /*方式1,允许接受*/TMOD=0x20;/*定时器1定时方式,方式2(具有自动再装入的8位定时器*/TH1=0xFD;ET1=0; /*定时器1溢出中断禁止*/TR1=1;/*启动定时器*/ES=1;/*串行口中断允许*/EA=1; /*总允许中断*/AD_CS=1;while(1){if(flag1){ flag1=0; convert_char_to_freq(); /*将接收的的频率字符串转换成二进制数*/ output_ad7008(freq); /*输出频率*/ delay_time(50); /*延时0.5秒*/ ad_channel1=0; tlc2543(); for(s=0;s<3;s++){ /*采集第一路电压量*/ delay_time(3); ad_out_byte=0; tlc2543(); ad_channel1+=ad_result;}&lt;dp n="d10"/&gt;ad_channel1/=3; /*变换三次求平均值*/ad_channel2=0;ad_out_byte=0x10;tlc2543();for(s=0;s<3;s++){ /*采集第二路电压量*/ delay_time(3); ad_out_byte=0x10; tlc2543(); ad_channel2+=ad_result; } ad_channel2/=3; /*变换三次求平均值*/ ad_channel3=0; ad_out_byte=0x20; tlc2543(); for(s=0;s<3;s++){ /*采集第三路电压量*/ delay_time(3); ad_out_byte=0x20; tlc2543(); ad_channel3+=ad_result; } ad_channel3/=3; /*变换三次求平均值*/ convert_ad_result_to_char();/*将AD变化后的二进制数转换成ASCII码字符串*/ SBUF=send_buffer[send_buf_pointer++];/*向上位机发送AD变换后的数据*/ } }}void serial(void)interrupt 4 /*串行口接收与发送数据子程序*/{ if(TI){TI=0;if(send_buf_pointer<12)SBUF=send_buffer[send_buf_pointer++];/*发送12位字符串数据*/return; } if(RI){ RI=0; recieve=SBUF; /*接受频率控制字*/ if(recieve!=′H′)buffer[buffer_pointer++]=recieve;/*字符串以‘H’结束*/ elseflag1=l; return;}}void delay_time(unsigned int n) /*延时子程序,延时0.01×n秒*/{unsigned int i;unsigned int s=711*n;for(i=0;i<s;i++){}&lt;dp n="d11"/&gt;}void convert_char_to_freq()/*将表示频率的ASC码转换成二进制数的子程序*/{inti;freq=0;for(i=buffer_pointer-1;i>=0;i--){ freq+=((buffer[i]-48)*pow(10,buffer_pointer-1-i));}buffer_pointer=0;}void convert_ad_result_to_char() /*将AD变换的二进制结果转换成ASCII码的子程序*/{send_buf_pointer=0;send_buffer
=ad_channel1/1000+48;/*第一路电压量转换*/send_buffer[1]=(ad_channel1%1000)/100+48;send_buffer[2]=(ad_channel1%100)/10+48;send_buffer[3]=ad_channel1%10+48;send_buffer[4]=ad_channel2/1000+48;/*第二路电压量转换*/send_buffer[5]=(ad_channel2%1000)/100+48;send_buffer[6]=(ad_channel2%100)/10+48; send_buffer[7]=ad_channel2%10+48;send buffer[8]=ad_channel3/1000+48;/*第三路电压量转换*/send_buffer[9]=(ad_channel3%1000)/100+48;send_buffer[10]=(ad_channel3%100)/10+48;send_buffer[11]=ad_channel3%10+48;}</pre>4.上位机程序系统上位机程序编译环境为Microsoft Visual C++6.0。程序在MFC的Dialog结构框架下编写。由于MFC自动生成的文件比较多,因此只介绍程序的核心部分,程序注释请参考程序右边“/* */”内文字。
打开串口的程序如下(串口设置为9600bps、8位数据、1位停止位、无校验位)<pre listing-type="program-listing">void CSerialDlg∷OnOpenSerialPort(){//TODOAdd your control notification handler code hereCSerialDlg∷UpdateData(1);switch(m_port_com_select){/*串口打开程序*/case 0hCom=CreateFile(″COM1″,GENERIC_READ|GENERIC_WRITE,0,NULL,OPEN_EXISTING,FILE_ATTRIBUTE_NORMAL,NULL);if(hCom=INVALID_HANDLE_VALUE)MessageBox(″串口1打开错误!″);else m_is_serial_port_open=1;break;case1hCom=CreateFile(″COM2″,GENERIC_READ|GENERIC_WRITE, 0,NULL,OPEN_EXISTING,FILE_ATTRIBUTE_NORMAL,NULL);&lt;dp n="d12"/&gt;if(hCom=INVALID_HANDLE_VALUE)MessageBox(″串口2打开错误!″);else m_is_serial_port_open=1;break;case2hCom=CreateFile(″COM3″,GENERIC_READ|GENERIC_WRITE,0,NULL,OPEN_EXISTING,FILE_ATTRIBUTE_NORMAL,NULL);if(hCom=INVALID_HANDLE_VALUE)MessageBox(″串口3打开错误!″);else m_is_serial_port_open=1;break;case 3hCom=CreateFile(″COM4″,GENERIC_READ|GENERIC_WRITE,0,NULL,OPEN_EXISTINGFILE_ATTRIBUTE_NORMAL,NULL);if(hCom=INVALID_HANDLE_VALUE)MessageBox(″串口4打开错误!″);else m_is_serial_port_open=1;break;}DCB dcb; /*以下均为串口设置程序*/BOOL m_error;m_error=GetCommState(hCom,&amp;amp;dcb);if(!m_error)MessageBox(″Get Comm State Error!″);dcb.BaudRate=CBR_9600;dcb.ByteSize=8;dcb.Parit=NOPARITY;dcb.StopBits=ONESTOPBIT;m_error=SetCommState(hCom,&amp;amp;dcb);if(!m_error)MessageBox(″Set Comm State Error!″);m_error=SetCommMask(hCom,EV_RXCHAR|EV_TXEMPTY);if(!m_error)MessageBox(″Set Comm Mask Error!″);m_error=SetupComm(hCom,0,0);if(!m_error)MessageBox(″Setup Comm Error!″);m_error=PurgeComm(hCom,PURGE_TXCLEAR|PURGE_RXCLEAR);if(!m_error)MessageBox(″Purge Comm Error!″);COMMTIMEOUTS m_com_time;m_com_time.ReadIntervalTimeout=1000;m_com_time.ReadTotalTimeoutConstant=0;m_com_time.ReadTotalTimeoutMultiplier=0;m_com_time.WriteTotalTimeoutConstant=2;m_com_time.WriteTotalTimeoutMultiplier=25;m_error=SetCommTimeouts(hCom,&amp;amp;m_com_time);if(!m_error)MessageBox(″Set Comm Timeouts Error!″);}</pre> 按钮的工作程序如下<pre listing-type="program-listing">void CSerialDlg∷OnStartWork(){//TODOAdd your control notification handler code hereCSerialDlg∷UpdateData(1);/*从人机界面获取输入值*/&lt;dp n="d13"/&gt;if(m_is_serial_port_open=0){MessageBox(″目前没有可用的串口,请打开一个串口!″);return;}if(m_ceramic_select!=0&amp;amp;&amp;amp;m_ceramic_select!=1){MessageBox(″请选择测量仪器档位!″);return;}if(m_frequency_start=″″){MessageBox(″请设定起始频率!″);return;}if(m_frequency_end==″″){MessageBox(″请设定终止频率!″);return;}if(m_frequency_grads=0){MessageBox(″请选择频率步距!″);return;}if(m_ceramic_select=0){/*确定坐标系刻度*/switch(m_coordinate_scale){case 0m_gain_value=100; break;case 1m_gain_value=50;break;case 2m_gain_value=20;break;}}if(m_ceramic_select=1){switch(m_coordinate_scale){case 0m_gain_value=10;break;case 1m_gain_value=5; break;case 2m_gain_value=2; break;}}m_output_frequency=m_frequency_start;int length;int i;length=m_frequency_start.GetLength();m_output_freq_low_long=0;for(i=0;i<length;i++){ /*将频率的ASCII码转换成二进制数*/m_output_freq_low_long+=(m_frequency_start[i]-48)*pow(10,length-1-i);}m_frequency_start_long=m_output_freq_low_long;length=m_frequency_end.GetLength();m_output_freq_high_long=0;for(i=0;i<length;i++){m_output_freq_high_long+=(m_frequency_end[i]-48) *pow(10,length-1-i);}m_last_cos_fi=0; /*一些量的初始化*/m_cos_fi=0;m_flag1=1; /*标识导纳虚部的符号变化*/m_max_cos_fi=0;m_data_pointer=0;m_frequency_add_times=0;CSerialDlg∷OnClearScreen();pain_pic();CDC*pdc;pdc=GetDlgItem(IDC_GRAPH)->GetDC();&lt;dp n="d14"/&gt;pdc->TextOut(302,134,m_frequency_start);/*在坐标上显示频率起始和终止值*/pdc->TextOut(660,134,m_frequency_end);float ss=(m_output_freq_high_long-m_output_freq_low_long) /m_ frequency_grads;m_x_axis_nterval=400/ss;SetTimer(ID_CLOCK_TIMER,600,NULL);/*设定程序开始扫描的定时器*/}</pre>程序进行频率扫描绘图的工作程序如下(程序扫描的时间间隔由定时器产生)<pre listing-type="program-listing">void CSerialDlg∷OnTimer(UINT nIDEvent){//TODOAdd your message handler code here and/or call defaultif(nIDEvent=ID_INIT_TIMER){/*有关程序启动画面的,与扫描无关*/ KillTimer(ID_INIT_TIMER); m_init_dlg.EndDialog(1); return;}char lpBuffer[20];int i;DWORD lpNumberOfBytesRead;DWORD dwbyteswritten;for(i=0;i<10;i++)lpBuffer[i]=0;unsigned int m_number;CString send=m_output_frequency;m_frequency_now=m_output_frequency;CString end(″H″);int length=m_output_frequency.GetLength();PurgeComm(hCom,PURGE_TXCLEAR|PURGE_RXCLEAR);/*清空串口缓冲区*/WriteFile(hCom,send,length,&amp;amp;dwbyteswritten,NULL);/*向串口发送频率控制字*/WriteFile(hCom,end,1,&amp;amp;dwbyteswritten,NULL);/*向串口发送频率控制字结束字符*/ReadFile(hCom,&amp;amp;lpBuffer,12,&amp;amp;lpNumberOfBytesRead,NULL);/*读取串口数据*/PurgeComm(hCom,PURGE_TXCLEAR|PURGE_RXCLEAR);/*清空串口缓冲区*/m_number=(lpBuffer
-48)*1000+(lpBuffer[1]-48)*100+ /*计算三路电压值*/(lpBuffer[2]-48)*10+(lpBuffer[3]-48);m_voltage1=((float)m_number/4095)*5.003;m_number=(lpBuffer[4]-48)*1000+(lpBuffer[5]-48)*100+(lpBuffer[6]-48)*10+(lpBuffer[7]-48);m_voltage2=((float)m_number/4095)*5.003;m_number=(lpBuffer[8]-48)*1000+(lpBuffer[9]-48)*100+(lpBuffer[10]-48)*10+(lpBuffer[11]-48);m_voltage3=((float)m_number/4095)*5.003;if(m_ceramic_select=0){ /*计算100欧姆支路电阻的阻抗值和导纳值*/m_last_cos_fi=m_cos_fi;m_cos_fi=4*m_voltage1/(m_voltage2*m_voltage3);m_uam_ubm=(m_voltage3*10)/(3*m_voltage2);if(m_cos_fi>1)m_cos_fi=1;m_R=100*(m_uam_ubm*m_cos_fi-1);m_X=100*m_uam_ubm*sqrt(1-(m_cos_fi*m_cos_fi));&lt;dp n="d15"/&gt;m_G=1000*m R/(m_R*m_R+m_X*m_X);m_B=1000*m_X/(m_R*m_R+m_X*m_X);} else{m_last_cos_fi=m_cos_fi;/*计算150欧姆支路电阻的阻抗值和导纳值*/m_cos_fi=4*m_voltage1/(m_voltage2*m_voltage3);m_uam_ubm=(m_voltage3*10)/(9*m_voltage2);/*计算公式与100欧姆有些区别*/if(m_cos_fi>1)m_cos_fi=1;m_R=150*(m_uam_ubm*m_cos_fi-1);m_X=150*m_uam_ubm*sqrt(1-(m_cos_fi*m_cos_fi));m_G=1000*m_R/(m_R*m_R+m_X*m_X);m_B=1000*m_X/(m_R*m_R+m_X*m_X);}if(m_cos_fi>m_max_cos_fi){m_max_cos_fi=m_cos_fi;m_syntonic_b=m_B;m_syntonic_g=m_G;m_syntonic_r=m_R;m_syntonic_x=m_X;m_syntonic_freq=m_frequency_now;}if(m_flag1){ /*确定导纳虚部的符号*/if(m_cos_fi<m_last_cos_fi&amp;amp;&amp;amp;m_cos_fi>=0.9){m_B=-m_B;m_flag1=0;}}else m_B=-m_B;m_data[m_data_pointer].m_frequency=m_utput_frequency; /*将数据存到数据类成员变量中*/m_data[m_data_pointer].m_voltage1=m_voltage1;m_data[m_data_pointer].m_voltage2=m_voltage2;m_data[m_data_pointer].m_voltage3=m_voltage3;m_data[m_data_pointer].m_cos_fi=m_cos_fi;m_data[m_data_pointer].m_uam_ubm=m_uam_ubm;m_data[m_data_pointer].m_R=m_R;m_data[m_data_pointer].m_X=m_X;m_data[m_data_pointer].m_G=m_G;m_data[m_data_pointer].m_B=m_B;m_data_pointer++;CDC*pdc;pdc=GetDlgItem(IDC_GRAPH)->GetDC();/*以下均为绘图程序*/if(m_ceramic_select==0){pdc->SetPixel((int)(m_gain_value*m_G+10)-1,(int)(130-m_gain_value*m_B)+1,RGB(255,0,255));pdc->SetPixel((int)(m_gain_value*m_G+10)-1,(int)(130-m_gain_value*m_B),RGB(255,0,255));pdc->SetPixel((int)(m_gain_value*m_G+10)-1,(int)(130-m_gain_value*m_B)-1,RGB(255,0,255));pdc->SetPixel((int)(m_gain_value*m_G+10),(int)(130-m_gain_value*m_B)+1,RGB(255,0,255));pdc->SetPixel((int)(m_gain_value*m_G+10),(int)(130-m_gain_value*m_B),RGB(255,0,255));pdc->SetPixel((int)(m_gain_value*m_G+10),(int)(130-m_gain_value*m_B)-1,RGB(255,0,255));pdc->SetPixel((int)(m_gain_value*m_G+10)+1,(int)(130-m_gain_value*m_B)+1,RGB(255,0,255));&lt;dp n="d16"/&gt;pdc->SetPixel((int)(m_gain_value*m_G+10)+1,(int)(130-m_gain_value*m_B),RGB(255,0,25&lt;br/&gt;5));pdc->SetPixel((int)(m_gain_value*m_G+10)+1,(int)(130-m_gain_value* m_B)-1,RGB(255,0,2&lt;br/&gt;55));pdc->SetPixel((int)(300+m_x_axis_interval*m_frequency_add_times)-1,(int)(130-m_gain_value*m_G/2)-1,RGB(255,0,0));pdc->SetPixel((int)(300+m_x_axis_interval*m_frequency_add_times)-1,(int)(130-m_gain_va1ue*m_G/2),RGB(255,0,0));pdc->SetPixel((int)(300+m_x_axis_interval*m_frequency_add_times)-l,(int)(130-m_gain_value*m_G/2)+1,RGB(255,0,0));pdc->SetPixel((int)(300+m_x_axis_interval*m_frequency_add_times),(int)(130-m_gain_value*m_G/2)-1,RGB(255,0,0));pdc->SetPixel((int)(300+m_x_axis_interval*m_frequency_add_times),(int)(130-m_gain_value*m_G/2),RGB(255,0,0));pdc->SetPixel((int)(300+m_x_axis_interval*m_frequency_add_times),(int)(130-m_gain_value*m_G/2)+1,RGB(255,0,0));pdc->SetPixel((int)(300+m_x_axis_interval*m_frequency_add_times)+1,(int)(130-m_gain_value*m_G/2)-1,RGB(255,0,0));pdc->SetPixel((int)(300+m_x_axis_interval*m_frequency_add_times)+l,(int)(130-m_gain_value*m_G/2),RGB(255,0,0));pdc->SetPixel((int)(300+m_x_axis_interval*m_frequency_add_times)+1,(int)(130-m_gain_value*m_G/2)+1,RGB(255,0,0));pdc->SetPixel((int)(300+m_x_axis_interval*m_frequency_add_times)-1,(int)(130-m_gain_value*m_B/2)-1,RGB(0,0,255));pdc->SetPixel((int)(300+m_x_axis_interval*m_frequency_add_times)-1,(int)(130-m_gain_value*m_B/2),RGB(0,0,255));pdc->SetPixel((int)(300+m_x_axis_interval*m_frequency_add_times)-1,(int)(130-m_gain_value*m_B/2)+1,RGB(0,0,255));pdc->SetPixel((int)(300+m_x_axis_interval*m_frequency_add_times),(int)(130-m_gain_value*m_B/2)-1,RGB(0,0,255));pdc->SetPixel((int)(300+m_x_axis_interval*m_frequency_add_times),(int)(130-m_gain_value*m_B/2),RGB(0,0,255));pdc->SetPixel((int)(300+m_x_axis_interval*m_frequency_add_times),(int)(130-m_gain_value*m_B/2)+1,RGB(0,0,255));pdc->SetPixel((int)(300+m_x_axis_interval*m_frequency_add_times)+1,(int)(130-m_gain_value*m_B/2)-1,RGB(0,0,255));pdc->SetPixel((int)(300+m_x_axis_interval*m_frequency_add_times)+1,(int)(130-m_gain_value*m_B/2),RGB(0,0,255));pdc->SetPixel((int)(300+m_x_axis_interval*m_frequency_add_times)+1,(int)(130-m_gain_value*m_B/2)+1,RGB(0,0,255));}else{pdc->SetPixel((int)(m_gain_value*m_G+10)-1,(int)(130-m_gain_value*m_B)+1,RGB(255,0,255));pdc->SetPixel((int)(m_gain_value*m_G+10)-1,(int)(130-m_gain_value*m_B),RGB(255,0,255));pdc->SetPixel((int)(m_gain_value*m_G+10)-1,(int)(130-m_gain_value*m_B)-1,RGB(255,0,255));pdc->SetPixel((int)(m_gain_value*m_G+10),(int)(130-m_gain_value* m_B)+1,RGB(255,0,255));pdc->SetPixel((int)(m_gain_value*m_G+10),(int)(130-m_gain_value*m_B),RGB(255,0,255));pdc->SetPixel((int)(m_gain_value*m_G+10),(int)(130-m_gain_value*m_B)-1,RGB(255,0,255));pdc->SetPixel((int)(m_gain_value*m_G+10)+1,(int)(130-m_gain_value*m_B)+1,RGB(255,0,255));pdc->SetPixel((int)(m_gain_value*m_G+10)+1,(int)(130-m_gain_value*m_B),RGB(255,0,255));pdc->SetPixel((int)(m_gain_value*m_G+10)+1,(int)(130-m_gain_value*m_B)-1,RGB(255,0,255));pdc->SetPixel((int)(300+m_x_axis_interval*m_frequency_add_times)-1,(int)(130-m_gain_val&lt;dp n="d17"/&gt;ue*m_G/2)-1,RGB(255,0,0));pdc->SetPixel((int)(300+m_x_axis_interval*m_frequency_add_times)-1,(int)(130-m_gain_val&lt;br/&gt;ue*m_G/2),RGB(255,0,0));pdc->SetPixel((int)(300+m_x_axis_interval*m_frequency_add_timgs)-1,(int)(130-m_gain_val&lt;br/&gt;ue*m_G/2)+1,RGB(255,0,0));pdc->SetPixel((int)(300+m_x_axis_interval*m_frequency_add_times),(int)(130-m_gain_value&lt;br/&gt;*m_G/2)-1,RGB(255,0,0));pdc->SetPixel((int)(300+m_x_axis_interval*m_fequency_add_times),(int)(130-m_gain_value*m_G/2),RGB(255,0,0));pdc->SetPixel((int)(300+m_x_axis_interval*m_fequency_add_times),(int)(130-m_gain_value*m_G/2)+1,RGB(255,0,0));pdc->SetPixel((int)(300+m_x_axis_interval*m_frequency_add_times)+1,(int)(130-m_gain_value*m_G/2)-1,RGB(255,0,0));pdc->SetPixel((int)(300+m_x_axis_interval*m_frequency_add_times)+1,(int)(130-m_gain_value*m_G/2),RGB(255,0,0));pdc->SetPixel((int)(300+m_x_axis_interval*m_frequency_add_times)+1,(int)(130-m_gain_value*m_G/2)+1,RGB(255,0,0));pdc->SetPixel((int)(300+m_x_axis_interval*m_frequency_add_times)-1,(int)(130-m_gain_value*m_B/2)-1,RGB(0,0,255));pdc->SetPixel((int)(300+m_x_axis_interval*m_frequency_add_times)-1,(int)(130-m_gain_value*m_B/2),RGB(0,0,255));pdc->SetPixel((int)(300+m_x_axis_interval*m_frequency_add_times)-1,(int)(130-m_gain_alue*m_B/2)+1,RGB(0,0,255));pdc->SetPixel((int)(300+m_x_axis_interval*m_fequency_add_times),(int)(130-m_gain_value*m_B/2)-1,RGB(0,0,255));pdc->SetPixel((int)(300+m_x_axis_interval*m_fequency_add_times),(int)(130-m_gain_value*m_B/2),RGB(0,0,255));pdc->SetPixel((int)(300+m_x_axis_interval*m_frequency_add_times),(int)(130-m_gain_value*m_B/2)+1,RGB(0,0,255));pdc->SetPixel((int)(300+m_x_axis_interval*m_frequency_add_times)+1,(int)(130-m_gain_value*m_B/2)-1,RGB(0,0,255));pdc->SetPixel((int)(300+m_x_axis_interval*m_frequency_add_times)+1,(int)(130-m_gain_value*m_B/2),RGB(0,0,255));pdc->SetPixel((int)(300+m_x_axis_interval*m_frequency_add_times)+1,(int)(130-m_gain_value*m_B/2)+1,RGB(0,0,255));} /*绘图程序到此为止*/CSerialDlg∷UpdateData(0);m_output_freq_low_ong+=m_frequency_grads;m_frequency_add_times++;if(m_output_feq_low_long>m_output_freq_high_long)KillTimer(ID_CLOCK_TIMER);/*判断扫描是否结束*/char cc[6];for(i=0;i<8;i++)cc[i]=0; /*计算下次扫描过程中的下一个点的频率*/cc
=m_output_freq_low_long/100000+48;cc[1]=m_output_freq_low_long%100000/10000+48;cc[2]=m_output_freq_low_long%10000/1000+48;cc[3]=m_output_freq_low_long%1000/100+48;cc[4]=m_output_freq_low_long%100/10+48;cc[5]=m_output_freq_low_long%10+48;while(cc
==′0′){for(i=1;i<6;i++){ cc[i-1]=cc[i];}cc[i-1]=0;}m_output_frequency=cc;CDialog∷OnTimer(nIDEvent);&lt;dp n="d18"/&gt;}</pre>程序中进行数据保存的程序如下<pre listing-type="program-listing">void CSerialDlg∷OnSaveData(){//TODOAdd your control notification handler code hereCString path,name;CString save_data=″frequency(Hz)\tCos(fi)\tG(ms)\t\tB(ms)\t\tR(ohm)\t\tX(ohm)\n″;/*数据表格的类目*/CString tmp;if(m_data_pointer!=0){ /*将扫描中的所有数据存到字符串中*/for(inti=0;i<m_data_pointer;i++){ save_data+=m_data[i].m_frequency; save_data+=″\t\t″; tmp.Format(″%f″,m_data[i].m_cos_fi); save_data+=tmp; save_data+=″\t″; tmp.Format(″%f″,m_data[i].m_G); save_data+=tmp; save_data+=″\t″; tmp.Format(″%f″,m_data[i].m_B); save_data+=tmp; save_data+=″\t″; tmp.Format(″%f″,m_data[i].m_R); save_data+=tmp; save_data+=″\t″; tmp.Format(″%f″,m_data[i].m_X); save_data+=tmp; save_data+=″\n″;}}save_data+=″\n″;tmp=″Syntonic F(Hz) Cos(fi) G(ms) B(ms) R(ohm) X(ohm)\n″;/*谐振点数据的表格类目*/save_data+=tmp; /*以下为谐振点的数据*/save_data+=m_syntonic_freq;save_data+=″ \t″;tmp.Format(″%f″,m_max_cos_fi);save_data+=tmp;save_data+=″\t″;tmp.Format(″%f″,m_syntonic_g);save_data+=tmp;save_data+=″\t″;tmp.Format(″%f″,m_syntonic_b);save_data+=tmp;save_data+=″\t″;tmp.Format(″%f″,m_syntonic_r);save_data+=tmp;save_data+=″\t″;tmp.Format(″%f″,m_syntonic_x);&lt;dp n="d19"/&gt;save_data+=tmp;save_data+=″\n″;CFileDialog_dlg(true,″RTF″,NULL,OFN_OVERWRITEPROMPT,NULL,NULL);/*打开程序保存对话框,将数据保存到一个文件中*/if(dlg.DoModal()=IDOK){ path=dlg.GetPathName(); name=dlg.GetFileName(); FILE*FileHandlele=fopen(path.GetBuffer(0),″wb″); fwrite(save_data.GetBuffer(0),save_data.GetLength(),1,FileHandle); fclose(FileHandle);}}</pre>将鼠标点击处的坐标值显示出来的子程序如下<pre listing-type="program-listing">void CSerialDlg∷OnMouseMove(UINT nFlags,CPoint point){//TODOAdd your message handler code here and/or call defaultif((nFlags&amp;amp;MK_LBUTTON)=MK_LBUTTON){ if(m_ceramic_select==0){/*测量档位1*/ if(point.x<303){/*鼠标点击处为坐标左半部分*/ m_pointer_g=((float)point.x-13)/m_gain_value; m_pointer_b=(375-(float)point.y)/m_gain_value; m_pointer_f=0;}if(point.x>303){ /*鼠标点击处为坐标右半部分*/ m_pointer_g=(375-(float)point.y)*2/m_gain_value; m_pointer_b=(375-(float)point.y)*2/m_gain_value; float_qq=(float)(m_frequency_grads*(point.x-303)) /m_x_axis_interval; m_pointer_f=(int)qq+m_frequency_start_long;}}else{if(point.x<303){/*测量档位2,鼠标点击处为坐标左半部分*/ m_pointer_g=((float)point.x-13)/m_gain_value; m_pointer_b=(375-(float)point.y)/m_gain_value;} if(point.x>303){/*鼠标点击处为坐标右半部分*/ m_pointer_g=(375-(float)point.y)*2/m_gain_value; m_pointer_b=(375-(375-(float)point.y)*2/m_gain_value; float_pp=(float)(m_frequency_grads*(point.x-303))/m_x_axis_interval; m_pointer_f=(int)pp+m_frequency_start_long;}}CSerialDlg∷UpdateData(0);}}</pre>
权利要求
1.一种针对压电陶瓷换能器的导纳圆测量装置;其特征在于将硬件和PC机软件结合起来,由硬件部分完成换能器导纳数据采集功能,由软件部分完成绘图与数据分析功能,两部分通过计算机串行口互相通信。
2.如权利要求1所述的、压电陶瓷换能器导纳圆图示仪中导纳测量的基本原理;其特征在于将压电陶瓷换能器与可变电阻串联,通过可变电阻上的电压值取得支路电流值,从而根据以下导纳计算公式推导出导纳值。换能器阻抗Z=uA-uBuB/RM=RM|uAuB-1|]]>(uA为换能器与电阻RM串联支路两端电压、uB为电阻RM两端电压)设uA=KAejwt,uB=KBej(ωt+)可得UAMUBM=KAKB]]>(UAM为uA的峰值、UBM为uB的峰值)则 式中 (R为阻抗的实部) (X为阻抗的虚部)换能器的导纳Y为Y=1Z=RR2+X2+jXR2+X2=G+jB]]>(G为导纳的实部、B为导纳的虚部)
3.如权利要求1中所述的、压电陶瓷换能器导纳圆图示仪中硬件部分的、频率精确可控而且稳定的正弦信号源的设计;其特征在于以直接数字合成(DDS)技术为基础,以单片机做频率控制,以功率运放对信号进行放大获得所需信号源。
4.如权利要求1中所述的、压电陶瓷换能器导纳圆图示仪中硬件部分的运算电路的设计;其特征在于通过检测支路电压和串联电阻上的电压的方式获取换能器的导纳数据,通过模拟乘法器获得两路信号的相位差,以峰值检波电路获得其电压的峰值。
5.如权利要求1中所述的、压电陶瓷换能器导纳圆图示仪中软件的程序用户界面的设计;其特征在于用户在软件上实现对硬件的控制,包括扫描频率的起始值、终止值、频率步进,导纳圆显示在屏幕下方,所得参数显示在屏幕右上方,通过鼠标点击导纳圆图可获得图形上任意一点的坐标值。
全文摘要
本发明是一种涉及物理学中声学领域的、有关压电陶瓷换能器导纳圆测量的装置。压电陶瓷换能器是声学领域内产生和接收声的一种装置。在使用压电陶瓷换能器之前需要测出其导纳圆以获得其主要参数,才可以指导其应用。本发明是针对压电陶瓷换能器导纳圆测定的、将硬件和PC机软件分析结合起来的综合性技术方案,此方案具有精度高、成本低、使用方便、针对性强的特点。其硬件部分主要完成导纳圆数据采集功能,软件部分主要完成数据分析功能,它们之间通过计算机串行口进行通信。硬件部分主要由信号发生电路、运算与采集电路、数据通信三部分电路构成。软件部分主要由数据通信、用户界面、数据处理三部分构成。
文档编号H01L41/00GK1439884SQ0310512
公开日2003年9月3日 申请日期2003年3月5日 优先权日2003年3月5日
发明者姚成刚 申请人:姚成刚
网友询问留言 已有0条留言
  • 还没有人留言评论。精彩留言会获得点赞!
1