已回答假定已回答

AD5934测量阻抗不准确的问题

yueyc 在 2015-6-4 詢問的問題
最後回覆由adi_susan於2015-6-30提供

使用AD5934测量阻抗,电路和软件参照CN-0349设计

使用2点校准:

Low range: μS to mS, R FB = 1 kΩ, R CAL =1 kΩ and 10 kΩ  

     这时测量1k、10k都是准确的,但测量2端和中间的阻值就偏差太大,例如:20k飘向50k+,15k飘向30k左右,12k飘向20k左右,看着这数据心哇凉哇凉的。

High range: mS to S, R FB = 100 Ω, R CAL = 100 Ω and 1 kΩ

     同样是2个校准的OK,其它点都不行

 

AD5934.bmp

///////////////////////////////////Conductivity.h///////////////////////////////////

#ifndef __CONDUCTIVITY_H

#define __CONDUCTIVITY_H

 

 

#include "stm32l1xx.h"

 

 

void TAST_COND(void);

void Cond_Control(void* p);

ErrorStatus SendFrame(u16 ADDR,u8 *buff,u8 len,u8 timeout);

//ErrorStatus SendFrame(u8 *buff,u8 len,u8 timeout);

void Receive_ADG715_AD5934(u8 ADDR,u8 regAddr,u8 *buff,u8 len);

void Set_ADG715_Channel(u8 *Channel);

void Write_AD5934_Register(u8 *Buff,u8 Len);

void AD5934_Init(void);

void Calculation_Gain_Factor(double Gain_Factor);

float Read_Magnitude( void);

void Adjust_AD5933(void);

float Liner_Calbration(float Magnitude,u8 Channel);

//void Change_AdjustChannel(u8 range);

void Mul_Receive_AD5934(u8 ADDR,u8 regAddr,u8 *buff,u8 len);

#endif

 

 

/////////////////////////////////// Conductivity.c///////////////////////////////////

#include  "Conductivity.h"

#include "MB_Core.h"

#include "SystemConfig.h"

#include "i2c.h"

#include "math.h"

#include "uarts.h"

#include "DataHandle.h"

#include "flash_add.h"

 

 

#define STK_COND_SIZE 256

#define I2C_CLOCK_Speed 100000 

#define I2C2_ADDr 0x0001

#define ADG715_ADDr 0x48          //1001 0 00

#define AD5934_ADDr 0x0D       //1010 0000

 

 

/***AD5934寄存器**/

#define Control_Low 0x80

#define Control_High 0x81

#define Start_Frequency_Low 0x82

#define Start_Frequency_Mid 0x83

#define Start_Frequency_High 0x84

#define Frequency_Increment_Low 0x85

#define Frequency_Increment_Mid 0x86

#define Frequency_Increment_High 0x87

#define Num_Increments_Low 0x88

#define Num_Increments_High 0x89

#define Num_TimeCyles_Low 0x8a

#define Num_TimeCyles_High 0x8b

#define Status_Register 0x8f

#define Real_Data_Low 0x95

#define Real_Data_High 0x94

#define Imaginary_Data_Low 0x97

#define Imaginary_Data_High 0x96

 

 

 

 

 

 

#define Range_Quantity 2

 

 

#define Calibration_Range1_High_Set 0x22

#define Calibration_Range1_Low_Set 0x42

#define Calibration_Range2_High_Set 0x11

#define Calibration_Range2_Low_Set 0x21

#define Calibration_Range3_Low_Set 0x00

#define Calibration_Range3_High_Set 0x00

 

 

#define Range1_Measure_Channel 0x02

#define Range2_Measure_Channel 0x01

 

 

#define CalibrationRange1_Low_Conductivity 0.0001  //单位为西门子

#define CalibrationRange1_High_Conductivity 0.001

#define CalibrationRange2_Low_Conductivity 0.001

#define CalibrationRange2_High_Conductivity 0.01

 

 

typedef struct Register_AD5933

{

  u8 Register;

  u8 DATA;

}Register_AD5933_Write;

 

 

typedef struct Calibration_Magnitude

{

  float Magnitude_FirstPoint;

  float Magnitude_SecondPoint;

}Calibration_Magnitude_Read;

 

 

 

 

 

 

typedef struct Calibration_Range_Num

{

  Calibration_Magnitude_Read Magnitude_Range_First;

  Calibration_Magnitude_Read Magnitude_Range_Second;

  Calibration_Magnitude_Read Magnitude_Range_Third;

}Calibration_Range_Magnitude;

 

 

Calibration_Range_Magnitude Calibration_Range;

 

 

Register_AD5933_Write Register_Data[15] =

{

  /*{Control_High ,0x10},

 

 

  // Transmit to start frequency register

  // program 30khz start frequency assuming exteral osc of 16Mhz

  {Start_Frequency_High,0x28},

  {Start_Frequency_Mid,0x5c},

  {Start_Frequency_Low,0x0f},

 

  // Transmit to frequency increment register

   // program 1Khz frequency increment assuming exteral osc of 16Mhz

  {Frequency_Increment_High,0xf6},

  {Frequency_Increment_Mid,0xc1},

  {Frequency_Increment_Low,0x00},

 

  // Transmit to NUMBER OF INCREMENTS register

   // program 10 frequency increments

  {Num_Increments_High,0x0A},

  {Num_Increments_Low,0x00},

 

  // Transmit to settling time cycles register

   // program 15 output cycles at each frequency before a adc conversion

  {Num_TimeCyles_High,0x28},

  {Num_TimeCyles_Low,0x00},

 

// {Control_Low,0x11},

 

  // Transmit to CONTROL register

   // place the AD5933 in standby mode

  {Control_Low,0xb0},

 

  // Choose the exteral system clock

  {Control_High,0x08},

 

  // Choose range 1 (2vp-p, 1.6v) PGA = x1 

  {Control_Low,0x03},

 

  // initialise the sensor with contents of start frequency regsister with range 1 (2vp-p, 1.6v) PGA = x1

  {Control_Low,0x10},

 

  // start of frequency sweep  (2vp-p, 1.6v) PGA = x1

  {Control_Low,0x20},*/

 

 

 

 

 

  // Transmit to start frequency register

  // program 30khz start frequency assuming exteral osc of 16Mhz

  {Start_Frequency_High,0x45},

  {Start_Frequency_Mid,0xA6},

  {Start_Frequency_Low,0x0E},

 

  // Transmit to frequency increment register

   // program 1Khz frequency increment assuming exteral osc of 16Mhz

  {Frequency_Increment_High,0x02},

  {Frequency_Increment_Mid,0x7D},

  {Frequency_Increment_Low,0x00},

 

  // Transmit to NUMBER OF INCREMENTS register

   // program 10 frequency increments

  {Num_Increments_High,0x0A},

  {Num_Increments_Low,0x00},

 

  // Transmit to settling time cycles register

   // program 15 output cycles at each frequency before a adc conversion

  {Num_TimeCyles_High,0x0F},

  {Num_TimeCyles_Low,0x00},

 

// {Control_Low,0x11},

 

  // Transmit to CONTROL register

   // place the AD5933 in standby mode

  {Control_Low,0xB0},

 

  // Choose the exteral system clock

  {Control_High,0x00},

 

  // Choose range 1 (2vp-p, 1.6v) PGA = x1 

  {Control_Low,0x01},

 

  // initialise the sensor with contents of start frequency regsister with range 1 (2vp-p, 1.6v) PGA = x1

  {Control_Low,0x10},

 

  // start of frequency sweep  (2vp-p, 1.6v) PGA = x1

  {Control_Low,0x20},

};

 

 

static OS_STK STK_COND[STK_COND_SIZE];

 

 

void TAST_COND(void)

{

  OSTaskCreate(Cond_Control,(void*)0,&STK_COND[STK_COND_SIZE-1],PRIO_TASK_COND);

}

 

 

 

 

//float Conductivity_Measure = 0;

void Cond_Control(void* p)

{

// u8 Buff[2];

// u8 i = 0;

  float Magnitude = 0;

  u8 Buff_ADG715_Channel;

  u8 flag_Led=0;

  u8 startSweep[2] = {0x80, 0x41};

 

// I2C_Comm_Init(I2C2,I2C_CLOCK_Speed,0xa0);  //I2C初始化

  AD5934_Init();

  Adjust_AD5933();

 

// Buff_ADG715_Channel = Calibration_Range1_High_Set;

// Set_ADG715_Channel(&Buff_ADG715_Channel);

 

 

  Buff_ADG715_Channel = Calibration_Range1_High_Set;

  Set_ADG715_Channel(&Buff_ADG715_Channel);

 

  Buff_ADG715_Channel = Range1_Measure_Channel;

// SendFrame(AD5934_ADDr<<1, startSweep, sizeof(startSweep), 50);

// OSTimeDlyHMSM(0,0,0,100);

  while(1)

  {

  Magnitude = Read_Magnitude();

 

  Probe_Value.Conductivity_Measure = Liner_Calbration(Magnitude,Buff_ADG715_Channel);

  if(flag_Led==0)

  {

  GPIO_SetBits(GPIOH,GPIO_Pin_2);

  flag_Led = 1;

  }

  else

  {

  GPIO_ResetBits(GPIOH,GPIO_Pin_2);

  flag_Led = 0;

  }

 

  if(Probe_Value.Conductivity_Measure<=0)

  Probe_Value.Conductivity_Measure = 0;

  OSTimeDlyHMSM(0,0,0,500);

  }

}

 

 

void Adjust_AD5933(void)

{

  u8 Range = 0;

// u8 i;

  u8 Buff_ADG715_Channel;

 

 

  for(Range = 1;Range <= Range_Quantity;Range++)

  {

  switch(Range)

  {

  case 1:

  Buff_ADG715_Channel = Calibration_Range1_Low_Set;

  Set_ADG715_Channel(&Buff_ADG715_Channel);

 

// SendFrame(AD5934_ADDr<<1, startSweep, sizeof(startSweep), 50);

// OSTimeDlyHMSM(0,0,2,0);

  Calibration_Range.Magnitude_Range_First.Magnitude_FirstPoint = Read_Magnitude();

 

 

  Buff_ADG715_Channel = Calibration_Range1_High_Set;

  Set_ADG715_Channel(&Buff_ADG715_Channel);

 

// SendFrame(AD5934_ADDr<<1, startSweep, sizeof(startSweep), 50);

// OSTimeDlyHMSM(0,0,2,0);

  Calibration_Range.Magnitude_Range_First.Magnitude_SecondPoint = Read_Magnitude();

 

  break;

 

  case 2:

  Buff_ADG715_Channel = Calibration_Range2_Low_Set;

  Set_ADG715_Channel(&Buff_ADG715_Channel);

 

// SendFrame(AD5934_ADDr<<1, startSweep, sizeof(startSweep), 50);

// OSTimeDlyHMSM(0,0,2,0);

  Calibration_Range.Magnitude_Range_Second.Magnitude_FirstPoint = Read_Magnitude();

 

 

  Buff_ADG715_Channel = Calibration_Range2_High_Set;

  Set_ADG715_Channel(&Buff_ADG715_Channel);

 

// SendFrame(AD5934_ADDr<<1, startSweep, sizeof(startSweep), 50);

// OSTimeDlyHMSM(0,0,2,0);

  Calibration_Range.Magnitude_Range_Second.Magnitude_SecondPoint = Read_Magnitude();

 

  break;

 

  case 3:

  Buff_ADG715_Channel = Calibration_Range3_Low_Set;

  Set_ADG715_Channel(&Buff_ADG715_Channel);

  Calibration_Range.Magnitude_Range_Third.Magnitude_FirstPoint = Read_Magnitude();

 

  Buff_ADG715_Channel = Calibration_Range3_High_Set;

  Set_ADG715_Channel(&Buff_ADG715_Channel);

  Calibration_Range.Magnitude_Range_Third.Magnitude_SecondPoint = Read_Magnitude();

  break;

  }

  }

  Updata_System_Parameter();

}

 

 

u8 Buff_AD5933_Receive[4] ;

float Read_Magnitude( void)

{

  float MagnitudeArray = 0;

  s16 Real_High;

  s16 Real_Low;

  s16 Image_High;

  s16 Image_Low;

 

  u8 startSweep[2] = {0x80, 0x41};

 

 

  static u8 Read_Status = 0;

 

 

  if(Read_Status == 0)

  {

  SendFrame(AD5934_ADDr<<1, startSweep, sizeof(startSweep), 50);

  OSTimeDlyHMSM(0,0,0,500);

  Read_Status = 1;

  }

 

 

 

 

  Receive_ADG715_AD5934(AD5934_ADDr<<1,Status_Register, Buff_AD5933_Receive,1);

  if(((Buff_AD5933_Receive[0] & 0x02) | 0xfd) == 0xff)

  {

  Receive_ADG715_AD5934(AD5934_ADDr<<1,Status_Register, Buff_AD5933_Receive,1);

  if((Buff_AD5933_Receive[0] & 0xfb) != 0xff)

  {

  Receive_ADG715_AD5934(AD5934_ADDr<<1,Real_Data_Low,   Buff_AD5933_Receive,1);

  Receive_ADG715_AD5934(AD5934_ADDr<<1,Real_Data_Low+1, Buff_AD5933_Receive+1,1);

  Receive_ADG715_AD5934(AD5934_ADDr<<1,Real_Data_Low+2, Buff_AD5933_Receive+2,1);

  Receive_ADG715_AD5934(AD5934_ADDr<<1,Real_Data_Low+3, Buff_AD5933_Receive+3,1);

 

  Real_Low = Buff_AD5933_Receive[0];

 

  Real_High = Buff_AD5933_Receive[1];

 

  Image_Low = Buff_AD5933_Receive[2];

 

  Image_High = Buff_AD5933_Receive[3];

 

  MagnitudeArray = sqrt( pow((((Real_High<<8)& 0xff00) | Real_Low) ,2) + pow((((Image_High<<8)& 0xff00) | Image_Low) ,2) );

 

  Read_Status = 0;

  }

  }

 

  return MagnitudeArray;

}

 

 

float GF_Value1 = 0;

float Nos_Value1 = 0;

float GF_Value2 = 0;

float Nos_Value2 = 0;

float Liner_Calbration(float Magnitude,u8 Channel)

{

 

 

  float Conductivity = 0;

  float Y_H_Coordinate = 0;

  float Y_L_Coordinate = 0;

  float N_H_Coordinate = 0;

  float N_L_Coordinate = 0;

  switch(Channel)

  {

  case Range1_Measure_Channel :

  Y_L_Coordinate = CalibrationRange1_Low_Conductivity;

  Y_H_Coordinate = CalibrationRange1_High_Conductivity;

  N_L_Coordinate = Calibration_Range.Magnitude_Range_First.Magnitude_FirstPoint;

  N_H_Coordinate = Calibration_Range.Magnitude_Range_First.Magnitude_SecondPoint;

  GF_Value1 = (Y_H_Coordinate -Y_L_Coordinate)  / (N_H_Coordinate - N_L_Coordinate);

  Nos_Value1 = N_H_Coordinate - (Y_H_Coordinate/GF_Value1);

  Conductivity = ( Magnitude - Nos_Value1) * GF_Value1;

  break;

 

  case Range2_Measure_Channel:

  Y_L_Coordinate = CalibrationRange2_Low_Conductivity;

  Y_H_Coordinate = CalibrationRange2_High_Conductivity;

  N_L_Coordinate = Calibration_Range.Magnitude_Range_Second.Magnitude_FirstPoint;

  N_H_Coordinate = Calibration_Range.Magnitude_Range_Second.Magnitude_SecondPoint;

  GF_Value2 = (Y_H_Coordinate - Y_L_Coordinate) / (N_H_Coordinate - N_L_Coordinate);

  Nos_Value2 = N_H_Coordinate - (Y_H_Coordinate/GF_Value2);

  Conductivity = ( Magnitude - Nos_Value2) * GF_Value2;

  break;

  }

 

  Conductivity = 1/Conductivity;

  return Conductivity;

}

 

 

//u8 ADG5934_Read_Register(u8 Register_Address)

//{

// u8 Buff_AD5933_Receive[1] ;

// //Receive_ADG715_AD5934(Real_Data_Low,Buff_AD5933_Receive,sizeof(Buff_AD5933_Receive));

// return Buff_AD5933_Receive[0];

//}

 

 

void Set_ADG715_Channel(u8 *Channel)

{

  SendFrame(ADG715_ADDr<<1,Channel,1,50);

}

 

 

void Receive_ADG715_AD5934(u8 ADDR,u8 regAddr,u8 *buff,u8 len)

{

  //ErrorStatus err;

  //u8 timeout = 50;

  u8 regBuf[2];

  regBuf[0] = 0xB0;

  regBuf[1] = regAddr;

  SendFrame(ADDR, regBuf, 2, 50);

  I2C_ReadByte(ADDR, buff, len);

}

 

 

void Mul_Receive_AD5934(u8 ADDR,u8 regAddr,u8 *buff,u8 len)

{

  u8 regBuf[2];

  u8 RegBuf_Re[2];

  regBuf[0] = 0xB0;

  regBuf[1] = regAddr;

  SendFrame(ADDR, regBuf, 2, 50);

  RegBuf_Re[0] = 0xb1;

  RegBuf_Re[1] = 4;

  SendFrame(ADDR, RegBuf_Re, 2, 50);

// I2C_MutiRead(ADDR, RegBuf_Re,buff, len);

}

 

 

ErrorStatus SendFrame(u16 ADDR,u8 *buff,u8 len,u8 timeout)

{

  ErrorStatus err = 0;

 

  I2C_WriteByte(ADDR, buff, len);

 

#if 0

  I2C_Comm_MasterWrite(I2C2,ADDR,0xffffffff,buff,len);

  while(timeout)

  {

  if (MasterTransitionComplete==1)

  {

  err = SUCCESS;

  break;

  }

  else

  {

  OSTimeDlyHMSM(0,0,0,200);

  timeout--;

  }

  }

  if (0==timeout)

  {

  err=ERROR;

  }

  OSTimeDlyHMSM(0,0,0,200);

 

#endif

 

  return err;

 

}

 

 

void AD5934_Init(void)

{

  u8 i;

  u8 Register_Write[2];

  for(i=0; i<(sizeof(Register_Data) /sizeof(Register_Data[0])) ;i++)

  {

  Register_Write[0] = Register_Data[i].Register;

  Register_Write[1] = Register_Data[i].DATA;

  Write_AD5934_Register(Register_Write,sizeof(Register_Write));

  OSTimeDlyHMSM(0,0,0,10);

  }

}

 

 

void Write_AD5934_Register(u8 *Buff,u8 Len)

{

  SendFrame(AD5934_ADDr<<1,Buff,Len,50);

}

結果