矿石收音机论坛

 找回密码
 加入会员

QQ登录

只需一步,快速开始

搜索
查看: 42586|回复: 115

测1000H和0.0xuH的谐振法测电感

  [复制链接]
     
发表于 2012-10-11 21:54:38 | 显示全部楼层 |阅读模式
本帖最后由 xjw01 于 2012-10-11 23:18 编辑

LC电路.PNG
1、制作
先是试制了网上流行的LM311电路。因手上没有LM311,用LM393代换。虽然只有几个元件,但也焊接了几个小时。
原电路出现以下问题:
1、频率稳定性不好,跳得比较历害
2、测量大电感误差非常大,可达20%
3、测量更大的电感,如10H以上的电感,很多无法测量,不起振。
解决方法:
  用示波器观察,谐振器上面的波形非常差,说明电路Q值太低。
  原电路使用33k电阻反馈(就是那3个100k电阻的并联值),测大电感时,频率低,阻抗大比33k电阻还大, Q值严重下降,造成电路不起振,就算起振了,测值误差也大得惊人。所以改用1兆欧高阻耦合。
  改了之后,可以测到1000H以上的大电感,而且很准。
2、性能
  为了与电桥比对,所以上限频率只做到200kHz,辅助电感是220uH
  零点缓慢漂移,得经常清零,比较讨厌。这是谐振元件温漂害的。
  不过,秒一级的稳定性比较好,读数不会乱跳,因为频率只会跳1个计数值(1计数对应2Hz,计数时间采用0.5秒),所以清零后,及时测量,还是可以准确测量0.x uH电感的。
  从几uH到1H之间实测来看,误差小于1%,1H到几百H,误差可以5%左右估算,一般是偏大。因为本电路测量大电感的电压比较高,不易与电桥比对。铁芯电感的电感量随测量电压升高,电感量略有增加。
3、校准
通过修改程序中的这一句校准:
c0 = 3.12e-9 * c2c(f);
其中3.12e-9表示谐振电容在1kHz频率下是3.12nF。
实测700uH空芯线圈,根据误差大小,调整3.12的值,重新下载,使得测量准确。
本表测量的结果实际上是等效并联电感。
4、电容容量修正
•谐振器的极限谐振频率是200kHz。
•涤纶电容随频率变大而变小,所以程序内建修正表,改正电容的容量误差。
以下是3.12nF电容的真值修正表,其中b数组是容量的修正系数
code float a[5]={100,   1000,  10000, 100000, 200000 }; //频率
code float b[5]={1.004, 1.000, 0.992, 0.975,  0.973  }; //修正量(涤纶原真修正表)
•修正值改进
那个1M欧的耦合电阻,在超声波范围内并不是存阻的。当频率较高时,电阻两端的分布电容及LM393内的信号耦合是不可以忽略的。虽然是电容耦合量很小,但在密勒效应的作用下,会被成百上升倍放大,有效谐振电容变小。频率比较高时,谐振器的阻抗很小,所以反馈系数非常弱,这就造成密勒效应的影响严重,可影响2%以上,为此高频率下,有效谐振电容仅修正系数仅为0.973是不够的。
此外,LM393的延迟也会造成振荡频率变小,引起测值变大。如果谐振器高Q,则影响小。整个回路的Q值只有20左右,所以频率高时,这个影响也是不能忽略的。用排除法证明:表笔接20R电阻测量电路中的那个功率电感,结果输电感量变大了2%,并联串联关系的转换远没有2%变化,谐振电压的变化也远不足以造成2%的变化,而接电阻后谐振阻抗变低,密勒效应更大,应造成电感量测值变小才对。显然,这2%的增加是LM393引起的。
以上因素,结合起来,修正表变为
code float a[5]={100,   1000,  10000, 100000, 150000 };  //频率
code float b[5]={1.004, 1.000, 0.992, 0.960,  0.950  };  //修正量(综合修正表)
•测量100uH以下的电感的改正
测量这种电感,频率大约在150kHz至200kHz
这个范围内频率变化,产生如下效果:
功率电感约有0.5uH的变化,电感量随频率变大而变小,引起电感测值变小。
涤纶电容随频率增加,容量变小,引起电感测值变大。
以及其它方面因素影响,相互补偿,最后结果150kHz以后的电容修正值与200kHz的修正值是一样的。所以电容修正表上限只要做到150kHz即可,大于150kHz的使用150kH的修正值。

评分

4

查看全部评分

     
 楼主| 发表于 2012-10-11 21:57:57 | 显示全部楼层

大模式编译
  1. //==========================================================================
  2. //  LC表驱动程序 V1.0
  3. //  许剑伟 于莆田 2012.10
  4. //==========================================================================
  5. //==========================================================================
  6. #define uchar unsigned char
  7. #define uint  unsigned int
  8. #define ulong  unsigned long
  9. #include <reg52.h>

  10. //==========================================================================
  11. // 项目:LCD1602 四线驱动程序
  12. // 设计要点:
  13. //     LCD1602 的运行速度慢,而单片机运行的速度快,因此容易因为速度不
  14. //     匹配造成调试失败。因此,调试之前应准确测试lcd_delay() 延时函数
  15. //     准确的延时量,如果不能满足注释中的要求,则应调整循次数。每步操
  16. //     作所需的延时量,按照数据手册指标指行,同时留下足够的时间余量。
  17. // 硬件连接:
  18. //     至少需要9条线,电源线2条,7条信号线。信号线详见程序中的接口定义。
  19. //     清注意对LCD1602比对的调节,否则无显示。
  20. // 设计:许剑伟,于莆田,2010.12
  21. //==========================================================================
  22. sbit lcd_RS = P0^1; //数据命令控制位,0命令1数据
  23. sbit lcd_RW = P0^2; //读写位,0写1读
  24. sbit lcd_EN = P0^3; //使能位,下降沿触发
  25. sbit lcd_D4 = P0^7; //数据端口D4
  26. sbit lcd_D5 = P0^6; //数据端口D5
  27. sbit lcd_D6 = P0^5; //数据端口D6
  28. sbit lcd_D7 = P0^4; //数据端口D7
  29. //==========================================================================
  30. void lcd_delay(int n){ //LCD专用延时函数
  31.   //32MHz钟频下,约循环3000次延迟1毫秒
  32.   int i,j;
  33.   if(n<0)    { for(i=0;i< 20;i++); return; } //10us
  34.   if(n== 0)  { for(i=0;i<100;i++); return; } //50us
  35.   for(;n;n--){ for(j=0;j<2000;j++);        } //n毫秒
  36. }
  37. //==========================================================================
  38. void lcd_B(char f, uchar c, char t){ //控制四线式接口LCD的7个脚
  39.   //f=0写命令字, f=1写RAM数据, f=2读地址(或读忙), f=3读RAM数据
  40.   lcd_EN = 0;
  41.   lcd_RS = f%2;
  42.   lcd_RW = f/2%2;
  43.   //移入高四位
  44.   lcd_D4 = c & 16;
  45.   lcd_D5 = c & 32;
  46.   lcd_D6 = c & 64;
  47.   lcd_D7 = c & 128;
  48.   lcd_EN = 1;  lcd_delay(-1);  lcd_EN = 0; //使能脉冲
  49.   if(f==4) { lcd_delay(t); return; }
  50.   //移入低四位
  51.   lcd_D4 = c & 1;
  52.   lcd_D5 = c & 2;
  53.   lcd_D6 = c & 4;
  54.   lcd_D7 = c & 8;
  55.   lcd_EN = 1;  lcd_delay(-1);  lcd_EN = 0; //使能脉冲
  56.   lcd_delay(t);  //不同的命令,响应时间不同,清零命令需要2ms
  57. }
  58. //==========================================================================
  59. void lcd_init(){ //LCD1602 初始化
  60.   //启动四线模式须势行9个步骤,初始化所须耗时较长,约65ms,时限不可减
  61.   lcd_delay(20); //启动lcd之前须延时大于15ms,直到VDD大于4.5V
  62.   lcd_B(4, 0x30, 9); //置8线模式,须延时大于4.1ms
  63.   lcd_B(4, 0x30, 5); //置8线模式,须延时大于100us
  64.   lcd_B(4, 0x30, 5); //置8线模式,手册中未指定延时
  65.   lcd_B(4, 0x20, 5); //进入四线模式
  66.   lcd_B(0, 0x28, 5); //四线模式双行显示
  67.   lcd_B(0, 0x0C, 5); //打开显示器
  68.   lcd_B(0, 0x80, 5); //RAM指针定位
  69.   lcd_B(0, 0x01, 5); //启动清屏命初始化LCD
  70. }
  71. //==========================================================================
  72. //=========================几个功能常用函数=================================
  73. void lcd_cls()         { lcd_B(0, 0x01+0, 2);  } //清屏
  74. void lcd_cur0()        { lcd_B(0, 0x0C+0, 0);  } //隐藏光标
  75. void lcd_goto1(uchar x){ lcd_B(0, 0x80+x, 0);  } //设置DDRAM地址,第1行x位
  76. void lcd_goto2(uchar x){ lcd_B(0, 0xC0+x, 0);  } //设置DDRAM地址,第2行x位
  77. void lcd_putc(uchar d) { lcd_B(1, 0x00+d, 0);  } //字符输出
  78. void lcd_puts(uchar *s){ for(; *s; s++) lcd_B(1,*s,0); } //字串输出
  79. //==============字符显示函数====================
  80. #define digW 4 //数字显示位数宏
  81. void lcd_puti(long a,char w){ //定宽显示正整数
  82.   char i=0, s[10]={32,32,32,32,32,32,32,32,32,32};
  83.   if(a<0) { a=-a; lcd_puts("-"); }
  84.   else    lcd_puts(" ");
  85.   do{
  86.    s[i++] = a%10+48;
  87.    a /= 10;
  88.   }while(a);
  89.   for(;w;w--) lcd_putc(s[w-1]);
  90. }
  91. void lcd_putf(float a,char n,char w){ //浮点输出,n是保留小数的位数,w是数字宽度
  92. char i,g,fi=0;
  93. long b,c=1;
  94. if(a<0) { lcd_putc('-'); a = -a; }
  95. else    { lcd_putc(' '); }
  96. for(i=0;i<n;i++) a *= 10;
  97. for(i=1;i<w;i++) c *= 10;
  98. b = a;
  99. for(i=0;i<w;i++){
  100.   g = b/c;
  101.   b -= g*c;
  102.   c /= 10;
  103.   if(g>9||g<0) g='*'-48;
  104.   if(i == w-n ) lcd_putc('.');
  105.   if(!g && !fi && i<w-n-1) { lcd_putc(' '); continue; }
  106.   lcd_putc(g+48);
  107.   fi = 1;
  108. }
  109. if(!n) lcd_putc(' '); //无小数点的补足显示宽度
  110. }

  111. //==========================================================================
  112. //===============================延时函数===================================
  113. void delay(uint loop) { uint i; for(i=0;i<loop;i++); } //延时函数
  114. void delay2(uint k)   { for(;k>0;k--) delay(10000);  } //长延时,k=100大约对应1秒

  115. //==========================================================================
  116. //=================================AD转换===================================
  117. /*
  118. sfr P1ASF = 0x9D;     //将P1置为模拟口寄存器(使能),各位中为1的有效
  119. sfr ADC_CONTR = 0xBC; //A/D转换控制寄存器
  120. sfr ADC_res   = 0xBD; //A/D转换结果寄存器
  121. sfr ADC_resl  = 0xBE; //A/D转换结果寄存器

  122. void set_channel(char channel){
  123. P1ASF = 1<<channel;
  124. ADC_CONTR = channel+128; //最高位是电源开关,低3位通道选择
  125. delay(1); //首次打开电源应延迟,使输入稳定
  126. }
  127. ulong getAD10(){
  128. uchar i;
  129. uint a=0,b=0;
  130. for(i=0;i<200;i++){
  131.   ADC_CONTR |= 0x08;             //00001000,置ADC_START=1启动A/D 转换
  132.   while ( !(ADC_CONTR & 0x10) ); //等待A/D转换结束(ADC_FLAG==0)
  133.   ADC_CONTR &= 0xE7;             //11100111,置ADC_FLAG=0清除结束标记, 置ADC_START=0关闭A/D 转换
  134.   a += ADC_res;
  135.   b += ADC_resl;
  136. }
  137. return a*4L + b;
  138. }

  139. uint getAD2(){
  140. ADC_CONTR |= 0x08;             //00001000,置ADC_START=1启动A/D 转换
  141. while ( !(ADC_CONTR & 0x10) ); //等待A/D转换结束(ADC_FLAG==0)
  142. ADC_CONTR &= 0xE7;             //11100111,置ADC_FLAG=0清除结束标记, 置ADC_START=0关闭A/D 转换
  143. return ADC_res*4 + ADC_resl;
  144. }
  145. */
  146. /*
  147. uchar get_AD(){
  148. ADC_CONTR |= 0x08;             //00001000,置ADC_START=1启动A/D 转换
  149. while( !(ADC_CONTR & 0x10) );  //等待A/D转换结束(ADC_FLAG==0)
  150. ADC_CONTR &= 0xE7;             //11100111,置ADC_FLAG=0清除结束标记, 置ADC_START=0关闭A/D 转换
  151. return ADC_res;
  152. }
  153. */


  154. //==========================================================================
  155. //==================================EEPROW偏程==============================
  156. sfr IAP_data  = 0xC2;
  157. sfr IAP_addrH = 0xC3;
  158. sfr IAP_addrL = 0xC4;
  159. sfr IAP_cmd   = 0xC5;
  160. sfr IAP_trig  = 0xC6;
  161. sfr IAP_contr = 0xC7;
  162. /********************
  163. 写字节时,可以将原有数据中的1改为0,无法将0改为1,只能使用擦除命令将0改为1
  164. 应注意,擦除命令会将整个扇区擦除
  165. *********************/
  166. int eepEn = 0;
  167. void saEEP(){ //触发并EEP保护
  168. if(eepEn==12345) IAP_trig = 0x5A;  //先送5A
  169. if(eepEn==12345) IAP_trig = 0xA5;  //先送5A再送A5立即触发
  170. IAP_cmd = 0;      //关闭令,保护
  171. IAP_contr = 0;    //关EEPROM,保护
  172. IAP_trig = 0;
  173. IAP_addrL = 255; //设置读取地址的低字节,地址改变才需要设置
  174. IAP_addrH = 255; //设置读取地址的高字节,地址改变才需要设置
  175. }
  176. uchar readEEP(uint k){ //读取
  177. IAP_addrL = k;    //设置读取地址的低字节,地址改变才需要设置
  178. IAP_addrH = k>>8; //设置读取地址的高字节,地址改变才需要设置
  179. IAP_contr = 0x82; //设置等待时间,1MHz以下取7,2M以下取6,3M取5,6M取4,12M取3,20M取2,24M取1,30M取0,前导1表示许档IAP
  180. IAP_cmd = 1;      //读取值1,写取2,擦除取3,擦除时按所在字节整个扇区撺除
  181. saEEP(); //触发并保护
  182. return IAP_data;
  183. }
  184. void writeEEP(uint k, uchar da){ //写入
  185. IAP_data = da;    //传入数据
  186. IAP_addrL = k;    //设置读取地址的低字节,地址改变才需要设置
  187. IAP_addrH = k>>8; //设置读取地址的高字节,地址改变才需要设置
  188. IAP_contr = 0x82; //设置等待时间,1MHz以下取7,2M以下取6,3M取5,6M取4,12M取3,20M取2,24M取1,30M取0,前导1表示许档IAP
  189. IAP_cmd = 2;      //读取值1,写取2,擦除取3,擦除时按所在字节整个扇区撺除
  190. saEEP(); //触发并保护
  191. }
  192. void eraseEEP(uint k){ //擦除
  193. IAP_addrL = k;    //设置读取地址的低字节,地址改变才需要设置
  194. IAP_addrH = k>>8; //设置读取地址的高字节,地址改变才需要设置
  195. IAP_contr = 0x82; //设置等待时间,1MHz以下取7,2M以下取6,3M取5,6M取4,12M取3,20M取2,24M取1,30M取0,前导1表示许档IAP
  196. IAP_cmd = 3;      //读取值1,写取2,擦除取3,擦除时按所在字节整个扇区撺除
  197. saEEP(); //触发并保护
  198. }


  199. xdata struct Ida{
  200. float L0;
  201. float C0;
  202. } cs;

  203. void cs_RW(char rw){
  204. uchar i,*p = &cs;
  205. const int offs=512;
  206. if(rw){
  207.   eraseEEP(offs);
  208.   for(i=0;i<sizeof(cs);i++) writeEEP(i+offs,p[i]);
  209. }else{
  210.   for(i=0;i<sizeof(cs);i++) p[i]=readEEP(i+offs);
  211. }
  212. }


  213. //==========================================================================
  214. //================================电感表主程序==============================
  215. //==========================================================================
  216. sfr P1M1=0x91; //P1端口设置寄存器
  217. sfr P1M0=0x92; //P1端口设置寄存器
  218. sfr P0M1=0x93; //P0端口设置寄存器
  219. sfr P0M0=0x94; //P0端口设置寄存器
  220. sfr P2M1=0x95; //P2端口设置寄存器
  221. sfr P2M0=0x96; //P2端口设置寄存器
  222. sfr P3M1=0xB1; //P3端口设置寄存器
  223. sfr P3M0=0xB2; //P3端口设置寄存器
  224. sfr WAKE_CLKO = 0x8F;
  225. sfr AUXR = 0x8E;
  226. sfr BRT = 0x9C;


  227. sbit K1=P3^7;  //清零键

  228. long feq=0;
  229. char Tk=0,Tkm=12,fa=0;
  230. void timerInter1(void) interrupt 3 {//T1中断
  231. fa++;
  232. }
  233. void timerInter0(void) interrupt 1 {//T0中断
  234.   uchar a,b,c;
  235.   if(++Tk>=Tkm){ //读取计数值
  236.         Tk = 0;
  237.     TR1 = 0; //暂停计数
  238.         a = fa, b = TH1, c = TL1;
  239.         fa = TH1 = TL1 = 0;
  240.         TR1 = 1;
  241.         feq = (a*256L*256L + b*256L+c) * (24/Tkm);
  242.     if(feq<=5) feq = 0;; //去除本频率(通常有1Hz)
  243.     if(feq<300&&feq>10) Tkm = 24; //低频(小于10视为不起振)
  244.         else                Tkm = 12; //频率较高时,闸门时间减小一些,加快测量速度
  245.   }
  246. }
  247. void putLx(float L){
  248.   if(L<1e-4) { L*=1e6; lcd_putf(L,2,4); lcd_puts(" uH"); return; }
  249.   if(L<1e-3) { L*=1e6; lcd_putf(L,1,4); lcd_puts(" uH"); return; }
  250.   if(L<1e-2) { L*=1e3; lcd_putf(L,3,4); lcd_puts(" mH"); return; }
  251.   if(L<1e-1) { L*=1e3; lcd_putf(L,2,4); lcd_puts(" mH"); return; }
  252.   if(L<1e+0) { L*=1e3; lcd_putf(L,1,4); lcd_puts(" mH"); return; }
  253.   if(L<1e+1) {         lcd_putf(L,3,4); lcd_puts("  H"); return; }
  254.   if(L<1e+2) {         lcd_putf(L,1,4); lcd_puts("  H"); return; }
  255.   if(L<1e+5) {         lcd_puti(L,5);   lcd_puts("  H"); return; }
  256.   lcd_puts("Overflow.");
  257. }
  258. float c2c(float f){ //针对涤纶电容修正
  259. code float a[5]={100,   1000,  10000, 100000, 150000 };  //频率
  260. code float b[5]={1.004, 1.000, 0.992, 0.960,  0.950  };  //修正量(综合修正表)
  261. //code float a[5]={100,   1000,  10000, 100000, 200000 }; //频率
  262. //code float b[5]={1.004, 1.000, 0.992, 0.975,  0.973  }; //修正量(涤纶原真修正表)
  263. char i;
  264. if(f<a[0]) return b[0];
  265. if(f>a[4]) return b[4];
  266. for(i=0;i<4;i++){
  267.   if( f>=a[i] && f<a[i+1]) return b[i] + (b[i+1]-b[i]) * (f-a[i]) / (a[i+1]-a[i]);
  268. }
  269. }
  270. float Lx=0;
  271. void calcL(){ //电感计算
  272. float f,w,c0;
  273. f = feq/1.024;
  274. c0 = 3.12e-9 * c2c(f);
  275. w = 2*3.1415926*f;
  276. if(w) Lx = 1/(w*w*c0);
  277. else  Lx = 1e20;
  278. lcd_goto1(0); putLx(Lx-cs.L0);
  279. lcd_goto2(0); lcd_puts("F="); lcd_puti(f,6); lcd_puts("Hz");
  280. }

  281. main(){
  282. uchar kn=0;
  283. eepEn = 12345;
  284. //端口初始化
  285. P3M0 = 0x00;    //00000000
  286. P3M1 = 0x20;    //00100000 P3.5置为高阻口

  287. delay2(5);    //等待升压电源电压上升
  288. lcd_init();   //初始化LCD
  289. lcd_cur0();   lcd_puts("LC 1.0");   //隐藏光标并显示片本
  290. lcd_goto2(0); lcd_puts("XJW Putian,2012"); //显示作者
  291. delay2(200);  lcd_cls(); //启动延时
  292. eepEn = 12345;
  293. cs_RW(0);   //读EEPROM

  294. AUXR |= 0x40;
  295. TMOD =  0x51;  //T1置为16位计数器,T2置为16位定时器
  296. TR0 = TR1 = 1; //起动计数
  297. ET0 = ET1 = 1; //开定时器中断
  298. EA = 1;        //开总中断

  299. while(1){
  300.   calcL();
  301.   if(!K1 && kn <255) kn++;
  302.   if(K1) kn=0;
  303.   if(kn==3){ //键按下
  304.     lcd_cls();
  305.     if(!feq) { cs.L0 = 0; lcd_puts("Removed."); }
  306.         else     { cs.L0 = Lx; lcd_puts("Cleared."); }
  307.         cs_RW(1);
  308.         delay2(50);
  309.   }

  310.   delay(20000);
  311. }

  312. }
  313. //==========================================================================
复制代码
回复 支持 反对

使用道具 举报

     
 楼主| 发表于 2012-10-11 22:10:04 | 显示全部楼层
201210111876.jpg
201210111877.jpg
回复 支持 反对

使用道具 举报

     
发表于 2012-10-11 22:31:07 | 显示全部楼层
做过谐振法测试LC, 误差比较大, 只是粗略判断下电容电感, 没许兄深入细致的研究, 对不同频率做修正.

评分

1

查看全部评分

回复 支持 反对

使用道具 举报

     
发表于 2012-10-11 23:02:07 | 显示全部楼层
学习
回复 支持 反对

使用道具 举报

     
发表于 2012-10-12 08:45:23 | 显示全部楼层
认真学习
回复 支持 反对

使用道具 举报

     
发表于 2012-10-12 09:28:36 | 显示全部楼层
学习
回复 支持 反对

使用道具 举报

发表于 2012-10-12 09:37:03 | 显示全部楼层
学                      习
回复 支持 反对

使用道具 举报

     
发表于 2012-10-12 09:38:38 | 显示全部楼层
前排就坐,许老师高产啊
回复 支持 反对

使用道具 举报

发表于 2012-10-12 09:40:47 | 显示全部楼层
搞个电感表对比测好
回复 支持 反对

使用道具 举报

发表于 2012-10-12 10:02:59 | 显示全部楼层
前排就座。
回复 支持 反对

使用道具 举报

     
发表于 2012-10-12 12:40:49 | 显示全部楼层
徐老师可以综合起来出个套件了
回复 支持 反对

使用道具 举报

发表于 2012-10-12 19:58:51 | 显示全部楼层
许老师,393周围的元件误差范围有要求吗?
回复 支持 反对

使用道具 举报

     
发表于 2012-10-12 23:32:01 | 显示全部楼层
跟许老师学习。
回复 支持 反对

使用道具 举报

发表于 2012-10-13 00:14:31 | 显示全部楼层
LM393高阻型 是什么意思?
回复 支持 反对

使用道具 举报

您需要登录后才可以回帖 登录 | 加入会员

本版积分规则

小黑屋|手机版|矿石收音机 ( 蒙ICP备05000029号-1 )

蒙公网安备 15040402000005号

GMT+8, 2025-4-28 06:05

Powered by Discuz! X3.4

© 2001-2023 Discuz! Team.

快速回复 返回顶部 返回列表