矿石收音机论坛

 找回密码
 加入会员

QQ登录

只需一步,快速开始

搜索
楼主: xjw01

我设计的ESR表(可同时显示中小容量电容)

  [复制链接]
     
发表于 2020-3-24 22:08:27 | 显示全部楼层
支持一下,非常有用!
回复 支持 反对

使用道具 举报

     
发表于 2020-4-26 17:12:12 | 显示全部楼层
感谢许老师,有这么好的作品分享给网友。自己制作和矫正多很顺利,有了这个表才知道原来前段时间买的几个三洋电容可能是假冒,ESR比我换下来的多要大

esr wanc7.jpg esr wanc71.jpg IMG_20200426_114434.jpg IMG_20200426_140213.jpg IMG_20200426_163532.jpg IMG_20200426_163617.jpg IMG_20200426_163626_1.jpg IMG_20200426_163649.jpg IMG_20200426_163820.jpg IMG_20200426_164514.jpg IMG_20200426_163929.jpg
回复 支持 反对

使用道具 举报

     
发表于 2020-5-3 19:53:15 | 显示全部楼层
IMG_20200503_194751.jpg IMG_20200503_194830.jpg
回复 支持 反对

使用道具 举报

     
发表于 2020-10-6 16:08:17 | 显示全部楼层
提示: 作者被禁止或删除 内容自动屏蔽
回复 支持 反对

使用道具 举报

     
发表于 2020-10-7 15:18:19 | 显示全部楼层
提示: 作者被禁止或删除 内容自动屏蔽
回复 支持 反对

使用道具 举报

     
 楼主| 发表于 2022-5-7 13:19:16 | 显示全部楼层
本帖最后由 xjw01 于 2022-5-7 13:30 编辑
矿坛铁粉 发表于 2020-10-7 15:18
许老师你好,关于P点电压也要请教一下:
文档里说在峰值为A的方波驱动下,电容上的波形前后半周对称,符号 ...


十年前设计的,现在忘了。当时设计此电路,花费的时间很少,所以记忆很浅。可能得重新阅计当年的文档,我才能回答。

晶振用18.3MHz的,频率太高了。我自己的ESR表更换为11.0592MHz。当然,相应的程序也须修改。

电路采用正交同步检波,可以在很低的频率下测量出ESR
也可以测量小电感

以下是源程序

a.rar (7.54 KB, 下载次数: 312)

回复 支持 反对

使用道具 举报

发表于 2022-5-13 06:38:12 来自手机 | 显示全部楼层
来晚一步,这么好的帖子2022年5月才看到
回复 支持 反对

使用道具 举报

     
发表于 2022-5-13 07:52:54 来自手机 | 显示全部楼层
我是来学习单片机编程的,许老师的c51很熟,句子也很精劈,没有一句无用的
回复 支持 反对

使用道具 举报

发表于 2022-5-13 10:09:48 | 显示全部楼层
学习了,感谢分享。
回复 支持 反对

使用道具 举报

     
发表于 2022-5-30 09:08:33 | 显示全部楼层
xjw01 发表于 2022-5-7 13:19
十年前设计的,现在忘了。当时设计此电路,花费的时间很少,所以记忆很浅。可能得重新阅计当年的文档, ...

许老师你好,请教一下,若把时钟频率降低后,除了延时函数需要改写外,还有哪些地方也必须修改?
回复 支持 反对

使用道具 举报

     
 楼主| 发表于 2022-5-30 22:30:39 | 显示全部楼层
本帖最后由 xjw01 于 2022-5-30 22:33 编辑

以下代码,与原先代码比对,看看当时改了那些地方。

模拟电路是比较难,当时没有做详细记录,许多细节现在重算有点困难,可以考虑从代码中解读。

程序中的每个参数,几乎都是根据实际元件参数,由理论计算出来的。

以下程序只给出ESR计算、测量部分的代码。不是全部代码,因为我当时做了加密处理,其它的代码发出来没有用。



esr12864-11MHz.png


//==============ESR测量====================
ulong nn = 0; //时序计数器
uchar nn2 = 0;

//=====可编程时钟发生器======
//每完成一趟计数,TL0、TL1重装,输出口置反,所以两趟计数才能输了完整方波,共计数2*(256-THx)字
//THx取128,输出方波需2*(256-128)=256计数,即256个时钟周期
uchar XW=0;
void feqInit(){
  WAKE_CLKO |= 0x07; //允许T0 T1 BRT独立发生时钟,以启动运放电源
  TMOD = 0x22;  //T0和T1工作在8位自动重装
  AUXR |= 0x80; //T0工作在1T
  AUXR |= 0x40; //T1工作在1T
  AUXR |= 0x04; //独立波特率发生器工作在1T
  TH0 = 128;    //置T0频率字
  TH1 = 128;    //置T1频率字
  BRT = 206;    //置BTR频率
  TL0 = 0;      //置初相为0
  TL1 = 0;      //置初相为0(TR1启动延时4周期,所以补偿4字)
  AUXR |= 0x10; //启动BRT,P1.0口输出
  TCON |= 0x50; //启动T0和T1,T0和T1分别在P3.4和P3.5输出,同时置1启动.如果用TR0=1,TR1=1,则1T时TL1应补偿4字.
}
void setXW(uchar xw,uchar bc){ //xw为移相参数(360度对应256字),bc补偿字数(72kHz补4字)
  uint m = 256-TH0;            //半周期的计数值
  uint n = (m*xw+64)/128+bc;   //变换为计数偏移量,因TR1比TR0晚启动引入4周期延时,所以事先补偿4字
  XW = xw;
  TR0 = 0, TR1 = 0;     //暂停计数
  pt0 = 0, pt1 = n/m%2; //同相或反相处理
  TL0 = 0, TL1 = n % m; //置相位差
  TCON |= 0x50; //TR0与TR1同时置1启动T0和T1.如果用TR0=1,TR1=1;则1T时bc应补偿4字
}
void setFeq(char k,uchar w){ //设置频率,w是相位
  if(k==5){ //直流电阻测量使用
        P3M1 |= 0x10, P3M0 &= ~0x10; //P3.4置为高阻口
    P1M0 |= 0x40, P1M1 &= ~0x40; //P1.6置为推挽口
        TR0 = TR1 = 0; //停止计数器
    pt1 = 1; //P3.5开路
        DCo = 1; //开启直流源
        return;
  }
  //交流阻抗测量使用
  P1M1 |= 0x40, P1M0 &= ~0x40; //P1.6置为高阻口
  P3M0 |= 0x10, P3M1 &= ~0x10; //P3.4置为推挽口
  if(k==0){ AUXR |=  0x80;  AUXR |=  0x40;  TH0=176, TH1=176; } //1T模式, 置为双69.12kHz
  if(k==1){ AUXR &= ~0x80;  AUXR &= ~0x40;  TH0=192, TH1=192; } //12T模式,置为双7.2kHZ
  if(k==2){ AUXR &= ~0x80;  AUXR &= ~0x40;  TH0=0,   TH1=0;   } //12T模式,置为双1.8kHZ
  if(k==3){ AUXR |=  0x80;  AUXR |=  0x40;  TH0=176, TH1=96;  } //1T模式, 信号源69.12kHz,检波端34.56kHz
  if(k==4){ AUXR |=  0xC0;  TH0=176; TR0=1; TR1=pt1=0; return;} //1T模式, 信号源69.12kHz,检波端0Hz
  setXW(w,0);
}
uint getAD10() { //过采样
//每秒取样速度为2.48万/1.67
int i;
long c = 0;
for(i=0;i<500;i++) c += getAD2();
c = (c+25)/50;
return c;
}
void putCx(float C,char g){ //显示电容,占用LCD屏7字符
  char xs = 0;
  float d=C;
  if(d<0) d=-d;
  if(d<10000) xs = 0;
  if(d<1000)  xs = 1;
  if(d<100)   xs = 2;
  if(d<10)    xs = 3;
  if(g==0 && d>50  ) {lcd_puts1(" OL   "); return; }
  if(g==1 && d>500 ) {lcd_puts1(" OL   "); return; }
  if(g==2 && d>6000) {lcd_puts1(" OL   "); return; }
  lcd_putf1(C,xs,4);
}
void putNx(char *Lb,int a,char n){ //输出整数
  lcd_puts1(Lb);
  lcd_int1(a,n);
}

int Vx,Vy,Vz,Vw,Vd; //Vd是零点直流漂移
float Vpp=52500,Vbat,Vbat2; //Vpp信号电压,Vbat电池电压
char Ha=0;
void ESRcalc(char jiao, char ha){
const Bn = 3; //时序步数
char n = nn%(Bn*8);
int v,vxc=0,vx,vy,vz,vw,vd;
float R=0,C1=0,C2=0,C3=0,e;
if(n%Bn) return;
n /= Bn;
v = getAD10();
if(n==0){ //测得电源电压
   set_channel(2); delay(6);
   Vpp  = getAD10()*(8.05)*(1+0.001*cs.Vp); //读信号电压
   Vbat2 = getAD2();
   set_channel(7); delay(6);
   Vbat  = (3.3*151/51/1024)*getAD2();  //利用HT7533作为电压基准换算电池电压
   Vbat2 = (1.2/3.3*1024)/(1024-Vbat2)*Vbat; //利用Vpp间接读取口作为电压基准换算电池电压
   Vbat2 += (Vbat2-3.6)*0.065; //Vbat2精度只有正负0.25V
   if(Vbat<3.6 && Vbat2<Vbat){
         Vbat = Vbat2;
   }
   Vbat += 0.1; //加上8550的压降
   set_channel(1);
}
if(ha==0){ //测阻容
   if(n==0){ Vd = v; setFeq(0,  0); return; } //测得零点直流,然后置为69.12kHz,0度
   if(n==1){ Vx = v; setFeq(0,192); return; } //测得x相电压,然后置69.12kHz,270度
   if(n==2){ Vy = v; setFeq(1,192); return; } //测得y相电压,然后置中频,270度
   if(n==3){ Vw = v; setFeq(2,192); return; } //测得y相电压,然后置低频,270度
   if(n==4){ Vz = v; setFeq(3,  0);         } //低频测得y相电压,然后置为非相关频率
   vd = Vd - cs.d0;
   vx = Vx - cs.x0 - vd;
   vy = Vy - cs.y0 - vd;
   vz = Vz - cs.z0 - vd;
   vw = Vw - cs.w0 - vd;
   //Vpp += checkBB(1)*10;
   if(Vy<9700){
     e = 1.0*vy/Vpp; e = e*(1+e*e*1.7);
     C1 = (14.47/8/101/1.015)/e;     //电容量公式 (T/8)/R*(A/vy)
     vxc = vy*(1.333*e + 0.005*cs.J1*e - 0.001*cs.J0);//电阻修正参数,理论系数是1.333,实测采用1.38比较好
     R = 1.030*(vx-vxc)/(Vpp-vx)*104; //电阻计算,Vpp被高估2%左右所以补偿值为1.02
   }
   if(Vw<9700){ //中频测容量
     e = vw/Vpp; e = e*(1+e*e*1.7);
     C2 = (14.47/8/104*9.6/1.015)/e;
   }
   if(Vz<9700){ //低频测容量
     e = vz/Vpp; e = e*(1+e*e*1.7);
     C3 = (14.47/8/104*38.4/1.015)/e;
   }
   {
    //static char checkA=0,check2=0;
        //if     (checkA<10){ if(C2>2.1&&C2<2.3) checkA++; }
        //else if(checkA<20){ if(R>14.4&&R<15.6) checkA++; }
        //else if(checkA<30){ if(R>19.2&&R<20.8) checkA++; }
        //else{ if(!check2){ check2=1; checkAA(2); cs_RW(1); } }
    //R += checkAA(1)*2 - cs.fmm;
    //C2 *= 1+checkAA(1)*2 - cs.fmm;
   }
   
   if(jiao==0){ //阻容显示
    if(Vx>=9700||Vy>=9700){ //主参数溢出(高频溢出)
      lcd_goto(0,0);  lcd_puts2(" !!!!!"); lcd_puts1(" \x8");
      lcd_goto(96,7); lcd_putf0(Vbat,2,-3); lcd_puts0("V"); //输出电阻和电池电压
      lcd_goto(0,4);  lcd_puts0("=====================");
      lcd_goto(0,5);  lcd_puts1("   C < 100nF    ");
      return;
    }
    lcd_goto(0,0);  lcd_putf2(R,2,4); lcd_puts1(" \x8");
    lcd_goto(96,7); lcd_putf0(Vbat,2,-3); lcd_puts0("V"); //输出电阻和电池电压
    lcd_goto(0,4);  lcd_puts0("=====================");
        lcd_goto(0,5);
        if(vy>500){ lcd_puts1("CH"); putCx(C1,1);  putCx(C2,2); } //电容输出
        else      { lcd_puts1("CL"); putCx(C2,1);  putCx(C3,2); } //电容输出
        lcd_puts1("\xa"); lcd_puts1("F"); //输出电容单位
   }
   if(jiao==1) { //过程显示
    lcd_goto(0,0); putNx("D=",cs.d0,4); putNx(" d=",vd,5); //零点直流
    lcd_goto(0,2); putNx("X=",cs.x0,4); putNx(" x=",vx,5); //显示Vx
    lcd_goto(0,4); putNx("Y=",cs.y0,4); putNx(" y=",vy,5); //显示Vy
    lcd_goto(0,6); putNx("Z=",cs.z0,4); putNx(" z=",vz,5); //显示Vz
   }
   //校准显示输出
   if(jiao>=5) { lcd_goto(0,0); lcd_puts1("R=");  lcd_putf1(R,2,4); lcd_puts1("\x8"); } //输出电阻
   if(jiao==5) { lcd_goto(0,2); putNx("Vp=",cs.Vp,5);  }  //Vp校准输出
   if(jiao==6) { lcd_goto(0,2); putNx("J0=",cs.J0,5);  }  //J0校准输出
   if(jiao==7) { lcd_goto(0,2); putNx("J1=",cs.J1,5);  }  //J1校准输出
}
if(ha==1){ //测电感
   if(n==0){ Vd = v; setFeq(5, 0); return; } //测得零点直流,置为72kHz,90度
   if(n==1){ Vx = v; setFeq(0,64); return; } //测直流电阻
   if(n==2){ Vy = v; setFeq(1,64); return; } //测得y相电压,置为中频90度
   if(n==3){ Vw = v; setFeq(2,64); return; } //低频测得y相电压,置为低频90度
   if(n==4){ Vz = v; setFeq(4, 0); return; } //低频测得y相电压,置为非相关频率
   vd = Vd - cs.Ld0;
   vy = Vy - cs.La0 - vd;
   vw = Vw - cs.Lb0 - vd;
   vz = Vz - cs.Lc0 - vd;
   vx = Vx + cs.Ldc0;  if(vx<0) vx = 0; vx = vx*2/3; //得到直流电阻,单位是0.01欧,实际上测得130R与电感直流电阻的并联,因为电感内阻小,130R可忽加略,用vx代替电感内阻

   vy -= cs.La1*(vx/2000.0); //cs.La1是20欧对应的电抗偏移,69.1kHz
   vw -= cs.Lb1*(vx/2000.0); //cs.Lb1是20欧对应的电抗偏移,7.2kHz
   vz -= cs.Lc1*(vx/2000.0); //cs.Lc1是20欧对应的电抗偏移,1.8kHz

   e = (104*14.47/4*1.010)/Vpp; //104*(T/2)/2
   if(jiao==0){ //显示电感量
    lcd_goto(0,0); lcd_puts1("69.1k L="); if(Vy>9700) lcd_puts1("Over    "); else { lcd_putf1(e*vy*(1+0.00020*vx)     , 2,4); lcd_puts1("uH"); } //高频测电感
    lcd_goto(0,2); lcd_puts1("07.2k L="); if(Vw>9700) lcd_puts1("Over    "); else { lcd_putf1(e*vw*(1+0.00017*vx)*9.6 , 1,4); lcd_puts1("uH"); } //中频测电感
    lcd_goto(0,4); lcd_puts1("01.8k L="); if(Vz>9700) lcd_puts1("Over    "); else { lcd_putf1(e*vz*(1+0.00013*vx)*38.4, 0,4); lcd_puts1("uH"); } //低频测电感
   }
   if(jiao==1){ //过程显示
    lcd_goto(0,0); putNx("I=",checkBB(2),4); putNx(" D=",vx,5);
    lcd_goto(0,2); putNx("G=",cs.Ld0,4); putNx(" g=",vd,5); //零点直流
    lcd_goto(0,4); putNx("A=",cs.La0,4); putNx(" a=",vy,5); //显示Va
    lcd_goto(0,6); putNx("B=",cs.Lc0,4); putNx(" b=",vz,5); //显示Vb
   }
}
}

char nCls = 127;
void shortCls(){ //短路清零
if(nCls<127) nCls++; //延时计数器步增,等待键盘放开
if(nCls==1){ lcd_cls(); lcd_puts1("Clear...."); delay2(100); }
if(nCls!=50) return;

if(Ha&&Vx>2500&&Vx<3000){ //电感测量的电阻残余清零,接入标准20R电阻后进行清零
  uchar i;
  cs.La1 = Vy-cs.La0;
  cs.Lb1 = Vw-cs.Lb0;
  cs.Lc1 = Vz-cs.Lc0;
  lcd_cls(); lcd_puts1("Check AD zeor");
  setFeq(5,0);
  DCo=0, cs.Ldc0=0;
  for(i=0;i<200;i++){ //每循环约1ms时间
    DCo = ~DCo;        delay(60); //生成占空比为1:10的方波
    DCo = ~DCo;        delay(540);
        if(i>=190) cs.Ldc0 += getAD2(); //读电压,仅在最后5%时间读电压,电容上的电压还有一定的保持作用,因此getAD2()占用的时间虽然影响占空比,但对读值准确性影响很小
  }
  DCo=1, cs.Ldc0 = 275 - cs.Ldc0; //每1欧150字,20//220=18.3,1/10即为1.83欧对应275字
  lcd_goto(0,2); putNx("c1=",cs.Ldc0,4);
  cs_RW(1); //保存
  lcd_goto(0,2); lcd_puts1("Ind cleared.");
  delay2(200);
  return;
}
if(Ha){ //电感零点参数
  cs.Ld0 = Vd, //直流零点
  cs.La0 = Vy, //90度高频残余
  cs.Lb0 = Vw, //90度中频残余
  cs.Lc0 = Vz; //90度低频残余
}
else{ //阻容测量
  cs.d0 = Vd;
  cs.y0 = Vy; //90度高频残余
  cs.w0 = Vw; //90度中频残余
  cs.z0 = Vz; //90度低频残余
  cs.x0 = Vx; //0度高频残余
}
cs_RW(1); //保存
lcd_cls(); lcd_puts0("Zero... OK");
delay2(200);
//Ha = (Ha+1)%2;
}
回复 支持 反对

使用道具 举报

     
 楼主| 发表于 2022-5-30 22:35:11 | 显示全部楼层
降低频率后,ESR表受表笔长度影响变小。同时,可以准确显示2000uF以内的容量
回复 支持 反对

使用道具 举报

     
发表于 2022-5-31 10:04:46 | 显示全部楼层
xjw01 发表于 2022-5-30 22:35
降低频率后,ESR表受表笔长度影响变小。同时,可以准确显示2000uF以内的容量

谢谢,知道了。
回复 支持 反对

使用道具 举报

     
发表于 2022-9-16 16:26:12 | 显示全部楼层
这个电路中,P1.3的6kHz方波起什么作用?
好像程序代码中也没有涉及
回复 支持 反对

使用道具 举报

     
 楼主| 发表于 2022-9-21 17:35:01 | 显示全部楼层
abbey_tom 发表于 2022-9-16 16:26
这个电路中,P1.3的6kHz方波起什么作用?
好像程序代码中也没有涉及

过采样用的。
可以使分辨率提升。
因此,ADC 10bit,过采样处理后,实际达到11bit至12bit之间。
回复 支持 反对

使用道具 举报

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

本版积分规则

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

蒙公网安备 15040402000005号

GMT+8, 2025-4-29 17:13

Powered by Discuz! X3.4

© 2001-2023 Discuz! Team.

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