微小电容测量电路研究系列
Leonard
Leonard2019/12/06电子技术仪器仪表 IP:浙江
关键词
微小电容测量电容传感器
AD7745

有人说科创的技术讨论变少了,惭愧了,我好像发了一个小说,这对于技术风气建立而言肯定不算很有利。

于是我补偿一点技术内容吧。

先声明自己不是搞电路的攻城狮,免得自己贻笑大方。

我现在主业做测力传感器的,电容传感器反正公司也没有列入项目,不算泄密,并且,我只发布关于电容测量的电路部分研究进展。一来网上都有,我只是整理归纳,算是拾人牙慧;二来严格说我算是机械工程师,公司看见了也不能说我泄密;三来我整理的也不一定对,希望大家多提提意见,帮助我进步。

ok,我小说写多了,变得啰嗦,抑制一下,开更:


先简介一下电容式测力的原理哈,其实我们每个人手上都有,手机里的加速度传感器就算一种。注意不是陀螺仪哦,不是MEMS,两者区别挺大的。对了,驻极话筒原理也差不多哟。先看下图(纯手绘):

1.png

受力引起间距变化了,电容值自然变化。ok,剩下就是测电容了对不对。

问题来了,这个电容差值很小的话怎么测呢?万用表别想了,nF级别根本不够。pF级别也差强人意。受力传感器的变形不易过大,不然会坏哦。经过我一通有限元分析(安利COMSOL),计算出来要测量到0.01pF左右的变化,才能够保证测量的分辨率不会太低。

分辨率和精度的区别:

举个例子,投飞镖

分辨率相当于你能看的多清楚。

精度相当于你的成绩有多稳定。如果你能保证每一标都是5环,也算精度高哦。


ok,要怎么测电容呢?

有几种常见方法:

  1. 测充电时间,要准备一个参比电容,它的容量已知,被测电容和它并联同时充电,看电压达到阈值时间差异。典型例子:引用一篇文献:基于CDC技术的微小电容测量系统,XXXXXXXXXXXXXXXXXXXXX/XXXXXXXXXXXXXXXml?qq-pf-to=XXXXXXXoup


    1.png

  2. 测LC谐振频率,这个其实不是很准确,温飘严重,我们不用。

  3. 还有一些其他原理的,有参考意义,陈列几条:

    参考文献:微小电容测试电路(人家的毕设)XXXXXXXXXXXXXXXXXXXXXXX/html/2018/0508/XXXXXXXXXXXXtm


    2.png

    3.png

    4.png

主要的思路都是对电容充电,把信号接到放大部分,把信号转换为其他物理量,把信号和时间联系起来。个人浅见,有可能是错的。



接下来介绍一款芯片是如何工作的:AD7745/7746

先暂停,上个AD7745的文件。因为样品还没到,我也要上班啦。

attachment icon AD7745_7746.pdf 410.66KB PDF 245次下载 预览

作为主角,它又是如何测量信号的呢?

虽然前面我们看到很多方法,但从芯片的说明书上看,似乎这些都不是它的方法,来看一下它原话怎么说的:

5.png

这里虽然说起来叫CDC,但和上面提到的一号引用文献里的CDC的原理显然是不同的,而且仔细看也会发现,这款芯片支持接单路电容和两路电容,也就是说可以有参比,也可没有。

然后这里虽然没有提及具体的实现细节,只说了是激励源加到被测电容上,测量电荷的通过情况,具体可能是电压,也可能是电流信号。随后又说到用0和1的序列的疏密度来表示电荷的通过情况。

这里是怎么回事呢?我猜想是这样的:38kHz的激励信号通过电容传输过来,未充满电时,电荷通过很顺利(电容看成一个电压源,没有阻碍),有一个“电荷累计模块”,每一个传输过来的脉冲电流信号转换为用1表示的数字信号,(AD转换为二进制,也就是说明书里所谓的dansity),当电容充的电越多,抵抗充电的电势越大,激励源的电压和电容上的电压的差值就越小,移动的电荷数减少,后面的事情就简单理解了。

如果我是错的(我真是没啥信心),请大神一定要告诉我。

原理部分先到此为止,后面就是等样品到了以后,搭电路实测了,到时在更调试过程。

[修改于 5年0个月前 - 2019/12/06 16:52:52]

来自:电子信息 / 电子技术仪器与装备 / 仪器仪表
15
2
已屏蔽 原因:{{ notice.reason }}已屏蔽
{{notice.noticeContent}}
~~空空如也
3DA502
5年0个月前 IP:北京
867186

最不明白的是,那个delta sigma 的输入级是个什么

引用
评论
1
加载评论中,请稍候...
200字以内,仅用于支线交流,主线讨论请采用回复功能。
折叠评论
Leonard作者
5年0个月前 IP:浙江
867195
引用3DA502发表于1楼的内容
最不明白的是,那个delta sigma 的输入级是个什么

我猜测就是所谓的“电荷累计模块”,其实还是通过电流或者电压来转换的信号。

引用
评论
加载评论中,请稍候...
200字以内,仅用于支线交流,主线讨论请采用回复功能。
折叠评论
3DA502
5年0个月前 IP:北京
867255

我推测ad公司在研制通用adc的过程中,发现这种转换前端具有电荷计数的功能,换个说法就是电流adc,所以就在通用adc上加个励激源,做成这个东西

引用
评论
加载评论中,请稍候...
200字以内,仅用于支线交流,主线讨论请采用回复功能。
折叠评论
ZhengYun
5年0个月前 IP:河南
867449

1,实际上,所有的方法中,只有那个桥式电路是最标准、精度最高的。

2,电容是个相当麻烦的物理量。不同频率和不同电压下,电容值都有可能变化。理论上,测量电容值最标准的做法是,施加幅值很小的正弦电压,在不同频率点、不同偏置电压下测量。

3,然而电阻可以做得非常理想。所以压力传感器一般都是电阻应变式的。

4,个人意见,测量电容,AD7745是一种非常受限的方案。它是用方波激励,如果被测元件不是理想电容,就会非常有问题。它的输入要求电容与地完全隔离,应用上非常不便。它的原理决定了会受到输入电阻、串联阻抗、漏电流等因素影响,这些因素很多是不可避免的。

5,不同的场合要求不同。精度有时候很重要,有时候是无所谓的。譬如电磁平衡式电子秤里面,应变传感器只在零点附近工作(应变被电磁力实时补偿),精度无所谓,反而零点附近的噪声、滞回(hysteresis)更重要。如果答主的应用场合也是类似的东西,那么精度很可能是完全无所谓的。


引用
评论
1
加载评论中,请稍候...
200字以内,仅用于支线交流,主线讨论请采用回复功能。
折叠评论
9zhmke
5年0个月前 IP:四川
867472

刚看到标题的时候还想进来发个言说Arduino那边有人做了可以精确到PF级别的,进来一看只好不发言了。先收藏个吧,以后用得着的时候再来向楼主请教。

引用
评论
加载评论中,请稍候...
200字以内,仅用于支线交流,主线讨论请采用回复功能。
折叠评论
Leonard作者
5年0个月前 IP:浙江
867481
引用ZhengYun发表于4楼的内容
1,实际上,所有的方法中,只有那个桥式电路是最标准、精度最高的。2,电容是个相当麻烦的物理量。不同频...

楼上说的东西,让我很受启发。实际上用AD7745也是因为自己在随意查资料导致的。并没有说真要开发电容式传感器就一定要用它。这还不算中美贸易摩擦的影响,我买这个芯片可找了好几家淘宝店,从香港进来的,货源不是那么稳定的,最后找到一个有库存的。


话说AD7745好处在于其集成度高,不需要外设电路。但是精度问题对我来说至关重要。

无论是零飘还是温飘,如果电容式传感器做不到和电阻应变式同等级别,那么这个项目研究的实际价值就不大,(毕竟我不是在科研单位,而是为某力学传感器公司工作,实用价值非常重要)


说一下电容式传感器的好处,如果做得好的话,有些方面还是比电阻式有优势的。

  1. 省电,电阻式有发热影响(常用阻值350Ω、700Ω,电桥电压5V),温飘问题也大,这点我反而觉得是电容式的最大优势。

  2. 无应变计的蠕变问题(这个问题其实影响不大,应变计的蠕变影响在万分之一,并且能够矫正金属弹性体之蠕变)

  3. 响应速率的问题,其实这个和后端采样的电路关系更大,但是电阻式的相应频率上限比较低,电容式则有可能测到更高相应频率。(不过要说测振动的传感器,电容式的测量方式决定它很难和压电式的比)。

  4. 分辨率的问题,很多电子称用的是电容或者磁阻式的,分辨率可以到十万分之一和三十万分之一满量程。当然,这是人家做的,如果用AD7745,估计分辨率做到万分之一满量程就撑死了(够用就好,满足第一点,我觉得就足够和电阻式拼了)

目前看来,电容式做模块化测力元件可行性比电阻式的高。原因之一是电容式的一旦设计好,加工没有太大误差的话,只要组装起来,就是一个模块,而电阻式涉及到多种复杂的补偿工艺(贴片贴歪这事我就不说了吧,技术都在补偿上);原因之二是当需要测三维力,或者6自由度的传感器式,电容式在工艺上优势极大,做模块当然也是非常优秀。做成的话,以后的传感器设计流程就是,弹性体先计算位移量,把电容式模块装上去(当然电容模块本身的强度也要计算一下子的,影响不会特别大),模拟部分的补偿工艺难度较低(数字手段补偿掉了),最后要做到十个人就能设计力学传感器的地步。同时会有一些其它问题,比如楼上说的输入阻抗,漏电流等因素,我补充一下,实测发现寄生电容影响极大,手伸过去就跳动一个pF,金属膜屏蔽也无明显效果,原因不太清楚,我用的是可以贴的铜箔,正反面都导电,但是胶水面有一定电阻,虽然不高,但和纯粹金属比可能还差点味道。

电容式传感器在国外已经有了较为广泛的运用,但目前还没做到模块化,这和行业有关,称重是工业里面很重要的一环,如果太透明,一大批人(包括我)都吃不上饭了。但我觉得真要是做到模块化也是好的,技术需要进步才对,工程师们用的越方便,生产力才越解放。

PS:之所以这么在乎省电这一点,是因为很多设备的改造需要穿线,原来没有的线路要加上去一般而言都很麻烦,但是做成无线的话,应用性就好了很多。

引用
评论
加载评论中,请稍候...
200字以内,仅用于支线交流,主线讨论请采用回复功能。
折叠评论
言文寺
5年0个月前 IP:北京
867509

我之前考虑过这个问题,,当时想法是连续快速的充放电,测变化量。最终没有实践,也不知可行与否。

引用
评论
加载评论中,请稍候...
200字以内,仅用于支线交流,主线讨论请采用回复功能。
折叠评论
Leonard作者
4年11个月前 修改于 4年11个月前 IP:浙江
867857

今天有时间研究了AD7745的IIC读写问题。


打算用Arduino做单片机这个决定导致我没什么太多资料可以参考。Github上面没有AD7745的库。国内文章搜了一下,罗列了一些资料可以参考:

  1. 51的:XXXXXXXXXXXXXXXXXXXXX/XXXXXXXXXXXXXXXml

  2. STM32的:XXXXXXXXXXXXXXXXXXXXXX/XXXXXXXXp?mod=viewthread&tid=70502

  3. 树莓派的:XXXXXXXXXXXXXXXXXXXX/bbs/XXXXXXXXXXXXXXXml


我一开始尝试用Arduino自带的IIC库,读取不出数据,做了地址扫描,发现有返回值的设备地址是0x48,十进制72,但是返回值也都是固定的数字,对于这个程序信心不高,于是放弃。等会儿上图。


后来根据51那个教程尝试做一个直接控制引脚电平来读取数据的实验,抄写了一会儿,发现它的程序里有点似乎非常非常(可能是故意的)恶心人的一段,随后放弃,并未尝试。有空也会上图。


最后找到一个树莓派的通用c写的AD7746库(7745差不多)

略微一看发现和arduino有惊人的相似之处。随即决定用这套程序,抄写翻译了一遍。

对于它的等待ack信号的处理不甚理解,但是应该不影响,其它时序似乎都对了。

先上程序:

#define CapDacvalue  4.97

#define SCL 21

#define SDA 20



byte SCLState = LOW;     


byte IIC_Flag=0;

byte interval = 1;

int previousMillis = 0; 


void IIC_Init(void)     

{

  /*                                             

        GPIO_InitTypeDef GPIO_InitStructure;

        

        RCC_APB2PeriphClockCmd(        RCC_APB2Periph_GPIOC, ENABLE );       

          

        GPIO_XXXXXXXXXXXXXXXXIO_Pin = GPIO_Pin_12|GPIO_Pin_11;

        GPIO_XXXXXXXXXXXXXXXXIO_Mode = GPIO_Mode_Out_PP ;   

        GPIO_XXXXXXXXXXXXXXXXIO_Speed = GPIO_Speed_50MHz;

        GPIO_Init(GPIOC, &GPIO_InitStructure);

  */

        digitalWrite(SCL,1);//IIC_SCL=1;

        digitalWrite(SDA,1);//IIC_SDA=1;

}


void IIC_Start(void)

{   

        pinMode(SDA, OUTPUT);

        digitalWrite(SDA,1);//IIC_SDA=1;

        digitalWrite(SCL,1);//IIC_SCL=1;

        delayMicroseconds(4);//uS

        digitalWrite(SDA,0);//IIC_SDA=0;

        delayMicroseconds(4);

        digitalWrite(SCL,0);//IIC_SCL=0;

}          


void IIC_Stop(void)

{

        pinMode(SDA, OUTPUT);

        digitalWrite(SCL,0);//IIC_SCL=0;

        digitalWrite(SDA,0);//IIC_SDA=0;

        delayMicroseconds(4);//uS

        digitalWrite(SCL,1);

        digitalWrite(SDA,1);

        delayMicroseconds(4);//uS                                                                 

}


byte IIC_Wait_Ack(void)

{

        byte ucErrTime=0;

        pinMode(SDA, INPUT);     

        digitalWrite(SDA,1);

        delayMicroseconds(1);//uS        

        digitalWrite(SCL,1);

        delayMicroseconds(1);//uS         

        while(digitalRead(SDA))

        {

                ucErrTime++;

                if(ucErrTime>250)

                {

                        IIC_Stop();

                        return 1;

                }

        }

        digitalWrite(SCL,0);//IIC_SCL=0;

        return 0;  

}


void IIC_Ack(void)

{

        digitalWrite(SCL,0);//IIC_SCL=0;

        pinMode(SDA, OUTPUT);//SDA_OUT();

        digitalWrite(SDA,0);//IIC_SDA=0;

        delayMicroseconds(2);//uS    

        digitalWrite(SCL,1);

        delayMicroseconds(2);//uS    

        digitalWrite(SCL,0);

}

              

void IIC_NAck(void)

{

        digitalWrite(SCL,0);//IIC_SCL=0;

        pinMode(SDA, OUTPUT);//SDA_OUT();

        digitalWrite(SDA,1);//IIC_SDA=1;

        delayMicroseconds(2);//uS 

        digitalWrite(SCL,1);//IIC_SCL=1;

        delayMicroseconds(2);//uS 

        digitalWrite(SCL,0);//IIC_SCL=0;

}                                                                              

                    

void IIC_Send_Byte(byte txd)

{                        

    byte t;   

    pinMode(SDA, OUTPUT);//SDA_OUT();           

    digitalWrite(SCL,0);//IIC_SCL=0;

    for(t=0;t<8;t++)

    {              

        digitalWrite(SDA,(txd&0x80)>>7);//IIC_SDA=(txd&0x80)>>7;

        txd<<=1;           

                delayMicroseconds(2);//uS  

                digitalWrite(SCL,1);//IIC_SCL=1;

                delayMicroseconds(2);//uS 

                digitalWrite(SCL,0);//IIC_SCL=0;     

                delayMicroseconds(2);//uS 

    }         

}             


u8 IIC_Read_Byte(unsigned char ack)

{

    unsigned char i,receive=0;

    pinMode(SDA, INPUT);

    for(i=0;i<8;i++ )

        {

        digitalWrite(SCL,0);//IIC_SCL=0

        delayMicroseconds(2);//uS 

        digitalWrite(SCL,1);//IIC_SCL=1;

        receive<<=1;

        if(digitalRead(SDA))receive++;   

        delayMicroseconds(1);//delay_us(1);

    }                                         

    if (!ack)

        IIC_NAck();

    else

        IIC_Ack(); 

    return receive;

}

unsigned char IICWatask2(void)  ///????,master wait for the ack, 

{

     unsigned char i=0;

     unsigned char flag=0x01;

     digitalWrite(SCL,0);//IIC_SCL=0;

     delayMicroseconds(2);//uS 

     digitalWrite(SDA,1);//IIC_SDA=1;

     digitalWrite(SCL,1);//IIC_SCL=1;

     delayMicroseconds(6);//delay_us(6);

     while(digitalRead(SDA)&&(i<250))///????while((IIC_SDA==1)&&(i<250)) could just use a delay?

      i++;

      flag=digitalRead(SDA);//flag=IIC_SDA;

      digitalWrite(SCL,0);//IIC_SCL=0;

     return(flag);

}


void IICSendask(void)

{

  digitalWrite(SDA,0);//IIC_SDA=0;

  delayMicroseconds(3);//delay_us(3);

  digitalWrite(SCL,1);//IIC_SCL=1;

  delayMicroseconds(6);//delay_us(6);

  delayMicroseconds(2);//delay_us(2);

  digitalWrite(SCL,0);//IIC_SCL=0;

  digitalWrite(SDA,1);//IIC_SDA=1;

  delayMicroseconds(3);//delay_us(3);

}         

unsigned char IICRECVbyte(void)

{

  unsigned char i;

  unsigned char temp=0;

  digitalWrite(SCL,0);//IIC_SCL=0;

  digitalWrite(SDA,1);//IIC_SDA=1;

  for (i=0;i<8;i++)

    {


          digitalWrite(SCL,1);//IIC_SCL=1;

          delayMicroseconds(5);//delay_us(5);

          temp=temp<<1;

      if(digitalRead(SDA)==1)//IIC_SDA==1

            temp=temp|0x01;

          else

            temp=temp&0xfe;

         digitalWrite(SCL,0);//IIC_SCL=0;

     }

    return(temp);

}



void AD7745_RESET(void)

{

  IIC_Start();

  IIC_Send_Byte(0xBF); // accroding to the reset method

  IIC_Stop();

}


unsigned char SETUP_7745(unsigned char addr,unsigned char value)   

{

unsigned char flag;

flag=0x01;

IIC_Start();

IIC_Send_Byte(0x90);

if(IICWatask2()!=0)

    flag=1;

else

    flag=0;

IIC_Send_Byte(addr);

if(IICWatask2()!=0)

    flag=1;

else

   flag=0;

IIC_Send_Byte(value);

if(IICWatask2()!=0)

    flag=1;

else

    flag=0;

IIC_Stop();

return(flag);

}


void GET7745value(unsigned char *p,unsigned char addr,unsigned char n)// get a series of value

  unsigned char i;

  unsigned char flagw;

  IIC_Start();

  IIC_Send_Byte(0x90);  

  flagw=IICWatask2();

  IIC_Send_Byte(addr); //从 Cap Data H开始读取0x01, addr 自定义开始读取的寄存器地址

  flagw=IICWatask2();

  IIC_Start();

  IIC_Send_Byte(0x91); 

  flagw=IICWatask2();

  for(i=0;i<n;i++)

    { 

      *p=IICRECVbyte();

           if(i!=n-1)

              IICSendask();

           else

              IICSendask();

           p++;

          }

   IIC_Stop();

}



//        #define CapDacvalue  4.

//        capdacreg=(int)((CapDacvalue*0x7F)/17

//  capdacreg=0x80|capdacre

//  AD7745_RESET(

//  SETUP_7745(0x07,0x80

//  SETUP_7745(0x09,0x2B

//  SETUP_7745(0x0A,0xA1

//  SETUP_7745(0x0B,capdacreg); 

//        GET7745value(MRD,3);    


void setup() {

  XXXXXXXXXgin(9600);

  // initialize digital pin  as an output.

  pinMode(SCL, OUTPUT);

  AD7745_RESET();

  delay(100);

  XXXXXXXXXintln("Reset");

  //SETUP_7745(0x07,0x80);

  //SETUP_7745(0x09,0x2B);

  //SETUP_7745(0x0A,0xA1);

  //int capdacreg=(int)((CapDacvalue*0x7F)/17);

  //capdacreg=0x80|capdacreg;

  //SETUP_7745(0x0B,capdacreg); 

  XXXXXXXXXintln("Setup done");

}

// the loop function runs over and over again forever

void loop() {

   byte n=18;//先取1个字节试试

   byte buff[17];//*p指向的缓存区,准备1个字节的空间

   unsigned char addr;

   addr=0x01;

   GET7745value(buff,addr,n);

   for(byte j=0;j<n;j++)

   {

    XXXXXXXXXint(j);//从地址开始的位置为0

    XXXXXXXXXint("   ");

    XXXXXXXXXintln(buff[j],HEX);

   }

   delay(5000);

}


attachment icon IIC-try2.ino 7.09KB INO 52次下载 更新了一下程序。

上机测试,数据是读出来了没错。因为IIC如果不读出来,会出现卡住的现象,什么都显示不出来。可是现在我收到的结果是:

10.png

对应于AD7745寄存器的:

11.png

怀疑是Rest的问题,陷入窘境。

上一张连线图(应该不是这个问题):

12.jpg

使用中我还是比较注意静电防护的,手拿电路板的时候,我用下面这层气泡袋防护一下。


引用
评论
加载评论中,请稍候...
200字以内,仅用于支线交流,主线讨论请采用回复功能。
折叠评论
Leonard作者
4年11个月前 修改于 4年11个月前 IP:浙江
867991

今天经过测试,前面那份程序终于调通了一个字节的读写。

连续读取还没整明白。

上程序:

#define CapDacvalue  4.97

#define SCL 21

#define SDA 20



byte SCLState = LOW;     


byte IIC_Flag=0;

byte interval = 1;

int previousMillis = 0; 


void IIC_Init(void)     

{

  /*                                             

        GPIO_InitTypeDef GPIO_InitStructure;

        

        RCC_APB2PeriphClockCmd(        RCC_APB2Periph_GPIOC, ENABLE );       

          

        GPIO_XXXXXXXXXXXXXXXXIO_Pin = GPIO_Pin_12|GPIO_Pin_11;

        GPIO_XXXXXXXXXXXXXXXXIO_Mode = GPIO_Mode_Out_PP ;   

        GPIO_XXXXXXXXXXXXXXXXIO_Speed = GPIO_Speed_50MHz;

        GPIO_Init(GPIOC, &GPIO_InitStructure);

  */

        digitalWrite(SCL,1);//IIC_SCL=1;

        digitalWrite(SDA,1);//IIC_SDA=1;

}


void IIC_Start(void)

{   

        pinMode(SDA, OUTPUT);

        digitalWrite(SDA,1);//IIC_SDA=1;

        digitalWrite(SCL,1);//IIC_SCL=1;

        delayMicroseconds(40);//uS

        digitalWrite(SDA,0);//IIC_SDA=0;

        delayMicroseconds(40);

        digitalWrite(SCL,0);//IIC_SCL=0;

}          


void IIC_Stop(void)

{

        pinMode(SDA, OUTPUT);

        digitalWrite(SCL,0);//IIC_SCL=0;

        digitalWrite(SDA,0);//IIC_SDA=0;

        delayMicroseconds(40);//uS

        digitalWrite(SCL,1);

        digitalWrite(SDA,1);

        delayMicroseconds(40);//uS                                                                 

}


byte IIC_Wait_Ack(void)

{

        byte ucErrTime=0;

        pinMode(SDA, OUTPUT);    

        digitalWrite(SDA,1);

        delayMicroseconds(10);//uS        

        digitalWrite(SCL,1);

        delayMicroseconds(10);//uS   

        pinMode(SDA, INPUT); 

        digitalWrite(SDA,1);      

        while(digitalRead(SDA))

        {

                ucErrTime++;

                delayMicroseconds(10);//uS   

                if(ucErrTime>250)

                {

                        IIC_Stop();

                        //XXXXXXXXXintln("No ACK");

                        return 1;

                }

        }

        digitalWrite(SCL,0);//IIC_SCL=0;

        return 0;  

}


void IIC_Ack(void)

{

        digitalWrite(SCL,0);//IIC_SCL=0;

        pinMode(SDA, OUTPUT);//SDA_OUT();

        digitalWrite(SDA,0);//IIC_SDA=0;

        delayMicroseconds(20);//uS    

        digitalWrite(SCL,1);

        delayMicroseconds(20);//uS    

        digitalWrite(SCL,0);

}

              

void IIC_NAck(void)

{

        digitalWrite(SCL,0);//IIC_SCL=0;

        pinMode(SDA, OUTPUT);//SDA_OUT();

        digitalWrite(SDA,1);//IIC_SDA=1;

        delayMicroseconds(20);//uS 

        digitalWrite(SCL,1);//IIC_SCL=1;

        delayMicroseconds(20);//uS 

        digitalWrite(SCL,0);//IIC_SCL=0;

}                                                                              

                    

void IIC_Send_Byte(byte txd)

{                        

    byte t;   

    pinMode(SDA, OUTPUT);//SDA_OUT();           

    digitalWrite(SCL,0);//IIC_SCL=0;

    for(t=0;t<8;t++)

    {              

        digitalWrite(SDA,(txd&0x80)>>7);//IIC_SDA=(txd&0x80)>>7;

        txd<<=1;           

                delayMicroseconds(20);//uS  

                digitalWrite(SCL,1);//IIC_SCL=1;

                delayMicroseconds(20);//uS 

                digitalWrite(SCL,0);//IIC_SCL=0;     

                delayMicroseconds(20);//uS 

    }         

}             


unsigned char IIC_Read_Byte(unsigned char ack)

{

    unsigned char i,receive=0;

    pinMode(SDA, INPUT);

    digitalWrite(SCL,0);//IIC_SCL=0;

    digitalWrite(SDA,1);//IIC_SDA=1;

    // XXXXXXXXXintln("IIC Reading Byte");

    for(i=0;i<8;i++)

        {

        digitalWrite(SCL,0);//IIC_SCL=0

        delayMicroseconds(20);//uS 

        digitalWrite(SCL,1);//IIC_SCL=1;

        receive<<=1;

        //XXXXXXXXXintln(receive,HEX);

        if(digitalRead(SDA))

        receive++;   

        delayMicroseconds(10);//delay_us(1);

    }                                         

    if (!ack)

        IIC_NAck();

    else

        IIC_Ack(); 

    return(receive);

}

unsigned char IICWatask2(void)  ///????,master wait for the ack, 

{

     unsigned char i=0;

     unsigned char flag=0x01;

     pinMode(SDA, OUTPUT);

     digitalWrite(SCL,0);//IIC_SCL=0;

     delayMicroseconds(20);//uS 

     digitalWrite(SDA,1);//IIC_SDA=1;

     digitalWrite(SCL,1);//IIC_SCL=1;

     delayMicroseconds(60);//delay_us(6);

     pinMode(SDA, INPUT);

     while(digitalRead(SDA)&&(i<250))///????while((IIC_SDA==1)&&(i<250)) could just use a delay?

      {

        i++;

        delayMicroseconds(20);//uS 

      }

      flag=digitalRead(SDA);//flag=IIC_SDA;

      digitalWrite(SCL,0);//IIC_SCL=0;

     return(flag);// 如果flag返回为0,主机没动过SDA电平,那只能是总线上有从机动了SDA意味着有反馈信号。

}


void IICSendask(void)

{

  pinMode(SDA, OUTPUT);

  digitalWrite(SDA,0);//IIC_SDA=0;

  delayMicroseconds(30);//delay_us(3);

  digitalWrite(SCL,1);//IIC_SCL=1;

  delayMicroseconds(60);//delay_us(6);

  delayMicroseconds(20);//delay_us(2);

  digitalWrite(SCL,0);//IIC_SCL=0;

  digitalWrite(SDA,1);//IIC_SDA=1;

  delayMicroseconds(30);//delay_us(3);

}         

unsigned char IICRECVbyte(void)

{

  unsigned char i;

  unsigned char temp=0;

  pinMode(SDA, OUTPUT);

  digitalWrite(SCL,0);//IIC_SCL=0;

  digitalWrite(SDA,1);//IIC_SDA=1;

  pinMode(SDA, INPUT);

  for(i=0;i<8;i++)

    {

      digitalWrite(SCL,1);//IIC_SCL=1;

      delayMicroseconds(50);//delay_us(5);

      temp=temp<<1;

      if(digitalRead(SDA)==1)//IIC_SDA==1

      {

          temp=temp|0x01;

          XXXXXXXXXintln(temp);

      }

      else

      {

          temp=temp&0xfe;

          XXXXXXXXXintln(temp);

      }

      digitalWrite(SCL,0);//IIC_SCL=0;

     }

    return(temp);

}



void AD7745_RESET(void)

{

  IIC_Start();

  IIC_Send_Byte(0xBF); // accroding to the reset method

  IIC_Stop();

}


unsigned char SETUP_7745(unsigned char addr,unsigned char value)   

{

unsigned char flag;

flag=0x01;

IIC_Start();

IIC_Send_Byte(0x90);

if(IIC_Wait_Ack()!=0)//(IICWatask2()!=0)

    {

      flag=1;

      //XXXXXXXXXint("NoAck");

      return(flag);

    }

else

    {

      flag=0;

      //XXXXXXXXXint("Acked");

    }

IIC_Send_Byte(addr);

if(IIC_Wait_Ack()!=0)

    {

      flag=1;

      //XXXXXXXXXint("NoAck");

      return(flag);

    }

else

    {

      flag=0;

      //XXXXXXXXXint("Acked");

    }

IIC_Send_Byte(value);

if(IIC_Wait_Ack()!=0)

    {

      flag=1;

      //XXXXXXXXXint("NoAck");

      return(flag);

    }

else

    {

      flag=0;

      //XXXXXXXXXint("Acked");

    }

IIC_Stop();

return(flag);

}


void GET7745value(unsigned char *p,unsigned char addr,unsigned char n)// get a series of value

  unsigned char i;

  unsigned char flagw;

  IIC_Start();

  IIC_Send_Byte(0x90);  

  flagw=IIC_Wait_Ack();

  if(flagw==1)return 0;

  else XXXXXXXXXint(flagw);

  IIC_Send_Byte(addr); //从 Cap Data H开始读取0x01, addr 自定义开始读取的寄存器地址

  flagw=IIC_Wait_Ack();

  if(flagw==1)return 0;

  else XXXXXXXXXint(flagw);

  IIC_Start();

  IIC_Send_Byte(0x91); 

  flagw==IIC_Wait_Ack();

  if(flagw==1)return 0;

  else XXXXXXXXXint(flagw);

  for(i=0;i<n;i++)

    { 

       *p=IIC_Read_Byte(1);//指针指向buffer

       if(i!=n-1)

          IICSendask();

       else

          IICSendask();

       p++;

     }

   IIC_Stop();

}



//        #define CapDacvalue  4.

//        capdacreg=(int)((CapDacvalue*0x7F)/17

//  capdacreg=0x80|capdacre

//  AD7745_RESET(

//  SETUP_7745(0x07,0x80

//  SETUP_7745(0x09,0x2B

//  SETUP_7745(0x0A,0xA1

//  SETUP_7745(0x0B,capdacreg); 

//        GET7745value(MRD,3);    


void setup() {

  XXXXXXXXXgin(9600);

  // initialize digital pin  as an output.

  pinMode(SCL, OUTPUT);

  AD7745_RESET();

  delay(1000);

  XXXXXXXXXintln("Reset");

  SETUP_7745(0x07,0x80);

  SETUP_7745(0x08,0x00);

  SETUP_7745(0x09,0x2B);

  SETUP_7745(0x0A,0xA2);

  //int capdacreg=(int)((CapDacvalue*0x7F)/17);

  //capdacreg=0x80|capdacreg;

  //SETUP_7745(0x0B,capdacreg); 

  SETUP_7745(0x0B,0x7E); 

  SETUP_7745(0x0C,0x7F);

  SETUP_7745(0x0D,0x80);

  SETUP_7745(0x0E,0x00);

  //SETUP_7745(0x0F,0x00);// factory calibrated capacitive gain calibration high byte

  //SETUP_7745(0x10,0x00);// factory calibrated capacitive gain calibration low byte

  //SETUP_7745(0x11,0x00);// factory calibrated votage gain calibration high byte 

  //SETUP_7745(0x12,0x00);// factory calibrated votage gain calibration low byte 

  XXXXXXXXXintln("Setup done");

}

// the loop function runs over and over again forever

void loop() {

   byte n=1;//先取1个字节试试

   byte buff[0];//*p指向的缓存区,准备1个字节的空间

   for(byte j=0;j<n;j++)

   {

    buff[j]=0;//清洗缓存区,以免干扰

   }

   unsigned char addr;

   addr=0x01;

   //SETUP_7745(0x0B,0x11);

   GET7745value(buff,addr,n);

   for(byte j=0;j<n;j++)

   {

    XXXXXXXXXint(addr,HEX);//从地址开始的位置为0

    XXXXXXXXXint("   ");

    XXXXXXXXXintln(buff[j],HEX);

    addr++;

   }

   delay(500000);

}

免打字版本:

attachment icon IIC-try3.ino 8.93KB INO 48次下载

18.png

电压给到5V才动起来的,之前给3.3V,总是不对


引用
评论
加载评论中,请稍候...
200字以内,仅用于支线交流,主线讨论请采用回复功能。
折叠评论
Leonard作者
4年11个月前 IP:浙江
867996

今天很顺利,风水好

哈哈,电容值也顺利读取出来了。

attachment icon IIC-try4.ino 9.18KB INO 91次下载

数据转换做的比较粗糙,也不知对不对。

19.png

20.jpg

庆祝一下!然后这个专题就可以截稿了,后面再有什么发现也不能发出来了。

引用
评论
加载评论中,请稍候...
200字以内,仅用于支线交流,主线讨论请采用回复功能。
折叠评论
LED
4年11个月前 IP:四川
868016

电容式和应变式都要利用材料形变,不确定度应该是同一量级的,但是电容式的驱动复杂很多。

引用
评论
加载评论中,请稍候...
200字以内,仅用于支线交流,主线讨论请采用回复功能。
折叠评论
Leonard作者
4年11个月前 修改于 4年11个月前 IP:浙江
868019
引用LED发表于11楼的内容
电容式和应变式都要利用材料形变,不确定度应该是同一量级的,但是电容式的驱动复杂很多。

nono,不是这样的哦,应变式目前精度可以做到很高,C10都能做到,这个级别用电容式的话,非常难达到,但是再高也很少见了,而电容式在更高精度上却是有例子的;不确定度,也就是我们讲的精度,影响因素很多,各种补偿方法也是核心技术,电阻应变式胜在成熟稳定;这时候单讨论材料形变的不确定性,意义不大。

但是总体来讲的话,电容式提升精度和降生产成本的潜力更大,这是工艺复杂性上决定的事情,电阻式有胶水固化,组桥走线,温补零补等各种工序(误差项);而电容式则基本上只有装配精度一项误差项,因为温度变化这些可以被芯片内置温度传感器用数字补偿掉。

引用
评论
加载评论中,请稍候...
200字以内,仅用于支线交流,主线讨论请采用回复功能。
折叠评论
xiaoxiaobaiyu52
4年11个月前 IP:广东
868408

楼主是搞机械的,可能对电子不太了解


列几个点比楼主参考,

1、电容卖得比电阻贵

2、电阻1%精度的很容易买,没人买10%精度的,但电容普遍5%起步,20%也常见

3、同一范围内,电阻可选的值比电容多。

4、电容的品种比电阻多


为什么呢,因为电容比电容难做,寄生电阻很容易做到高阻,但寄生电容到处都有,很难排除

楼主举例胶水固化,组桥走线,温补零补,电容全都有,还多了好几项,比如湿度,震动,电磁干扰,运动干扰


比如人的手,属于导体,和大地构成电容,还自带生物电干扰,还有引入工频,射频干扰。

人的手摸一摸触摸屏,这里能填进一货车的博士进去做算法


距离相等≠电容相等,我以前有0.3pf的应用,AD的这套芯片,我基本全部类型的都用了一遍,已经按最理想去考虑,但最后还是被算法难死了




引用
评论
加载评论中,请稍候...
200字以内,仅用于支线交流,主线讨论请采用回复功能。
折叠评论
Leonard作者
4年11个月前 修改于 4年11个月前 IP:浙江
868419
引用xiaoxiaobaiyu52发表于13楼的内容
楼主是搞机械的,可能对电子不太了解列几个点比楼主参考,1、电容卖得比电阻贵2、电阻1%精度的很容易买...

感受到了,芯片玩通了之后,发现很多现象,尤其是干扰,放金属腔里面都无法完全屏蔽掉,我还奇怪是咋回事呢,物理书上不是这么说的啊,后来想,因为出线口那里还是有小的口,电场还能通过,所以也不能算完全理想的模型。这个东西玩差不多了就不想玩了,算是技术储备,公司也没立项,我的兴趣也已经转移了,三分钟热度。


PS:AD7745芯片还是好东西,我站远点看,数据是不会自己往下掉的,这个和我之前说买的那个淘宝上的175块钱的号称0.01pf电容测量表相比,优点就是数据自己不会向下掉,电路上的误差小了。这么说起来,咱也能做这个微小电容测量表的生意哈。


引用
评论
加载评论中,请稍候...
200字以内,仅用于支线交流,主线讨论请采用回复功能。
折叠评论

想参与大家的讨论?现在就 登录 或者 注册

Leonard
进士 机友 笔友
文章
7
回复
173
学术分
0
2019/11/04注册,6个月6天前活动

自制YBCO中

主体类型:个人
所属领域:无
认证方式:手机号
IP归属地:浙江
文件下载
加载中...
{{errorInfo}}
{{downloadWarning}}
你在 {{downloadTime}} 下载过当前文件。
文件名称:{{resource.defaultFile.name}}
下载次数:{{resource.hits}}
上传用户:{{uploader.username}}
所需积分:{{costScores}},{{holdScores}}下载当前附件免费{{description}}
积分不足,去充值
文件已丢失

当前账号的附件下载数量限制如下:
时段 个数
{{f.startingTime}}点 - {{f.endTime}}点 {{f.fileCount}}
视频暂不能访问,请登录试试
仅供内部学术交流或培训使用,请先保存到本地。本内容不代表科创观点,未经原作者同意,请勿转载。
音频暂不能访问,请登录试试
支持的图片格式:jpg, jpeg, png
插入公式
评论控制
加载中...
文号:{{pid}}
投诉或举报
加载中...
{{tip}}
请选择违规类型:
{{reason.type}}

空空如也

加载中...
详情
详情
推送到专栏从专栏移除
设为匿名取消匿名
查看作者
回复
只看作者
加入收藏取消收藏
收藏
取消收藏
折叠回复
置顶取消置顶
评学术分
鼓励
设为精选取消精选
管理提醒
编辑
通过审核
评论控制
退修或删除
历史版本
违规记录
投诉或举报
加入黑名单移除黑名单
查看IP
{{format('YYYY/MM/DD HH:mm:ss', toc)}}