ADS1247采集热电偶信号数据不稳,现象如下,请大家帮帮忙解决下,急啊!
热电偶信号需要精确到1℃以内,要求1S中至少要出30个数,现在把采样速率设定在320SPS ,软件10个数求平均一次,误差在0.2mV左右,远远不能满足要求。
把采样速率降到40SPS,滤波数量改为40个,精度能达到20uV,这样能满足精度要求,但是又不能满足一秒钟出30个数,请大家帮帮忙,谢了!
ke yin:
回复 Bruce Wei:
程序如下:
void ADS1247Wakeup(void) { ADS1247PinCs(0); ADS1247TxRxByte(0x00); //reg ADS1247PinCs(1); }
/********************************************************************************** ** 函数名称: ** 功 能: ** 输入参数: ** 输出参数: ** 返 回: ***********************************************************************************/
void ADS1247Sleep(void) { ADS1247PinCs(0); ADS1247TxRxByte(0x02); //reg ADS1247PinCs(1); }
/********************************************************************************** ** 函数名称: ** 功 能: ** 输入参数: ** 输出参数: ** 返 回: ***********************************************************************************/
void ADS1247Sync(void) { ADS1247PinCs(0); ADS1247TxRxByte(0x04); ADS1247TxRxByte(0x04); ADS1247PinCs(1); } /********************************************************************************** ** 函数名称: ** 功 能: ** 输入参数: ** 输出参数: ** 返 回: ***********************************************************************************/
void ADS1247Reset(void) { uint16 i; ADS1247PinCs(0); ADS1247TxRxByte(0x06); ADS1247PinCs(1); for (i=60000; i!=0; i–); ADS1247PinReset(0); for (i=60000; i!=0; i–); ADS1247PinReset(1); for (i=60000; i!=0; i–); }
/********************************************************************************** ** 函数名称: ** 功 能: ** 输入参数: ** 输出参数: ** 返 回: ***********************************************************************************/
uint32 ADS1247RData(void) { uint32 res = 0; ADS1247PinCs(0);
ADS1247TxRxByte(0x12); res = ADS1247TxRxByte(0); res <<= 8; res |= ADS1247TxRxByte(0); res <<= 8; res |= ADS1247TxRxByte(0); ADS1247PinCs(1); return res; }
uint32 ADS1247ReadADC(void) { uint32 res = 0; ADS1247PinCs(0); res = ADS1247TxRxByte(0); res <<= 8; res |= ADS1247TxRxByte(0); res <<= 8; res |= ADS1247TxRxByte(0); ADS1247PinCs(1); return res; }
/********************************************************************************** ** 函数名称: ** 功 能: ** 输入参数: ** 输出参数: ** 返 回: ***********************************************************************************/
void ADS1247RDataC(void) { ADS1247PinCs(0); ADS1247TxRxByte(0x14); ADS1247PinCs(1); }
/********************************************************************************** ** 函数名称: ** 功 能: ** 输入参数: ** 输出参数: ** 返 回: ***********************************************************************************/
void ADS1247SDataC(void) { ADS1247PinCs(0); ADS1247TxRxByte(0x17); ADS1247PinCs(1); }
/********************************************************************************** ** 函数名称: ** 功 能: ** 输入参数: ** 输出参数: ** 返 回: ***********************************************************************************/
void ADS1247SysOCal(void) { ADS1247PinCs(0); ADS1247TxRxByte(0x60); ADS1247PinCs(1); }
/********************************************************************************** ** 函数名称: ** 功 能: ** 输入参数: ** 输出参数: ** 返 回: ***********************************************************************************
/ void ADS1247SysGCal(void) { ADS1247PinCs(0); ADS1247TxRxByte(0x61); ADS1247PinCs(1); }
/********************************************************************************** ** 函数名称: ** 功 能: ** 输入参数: ** 输出参数: ** 返 回: ***********************************************************************************/ void ADS1247SelfOCal(void) { ADS1247PinCs(0); ADS1247TxRxByte(0x62); ADS1247PinCs(1); }
/********************************************************************************** ** 函数名称: ** 功 能: ** 输入参数: ** 输出参数: ** 返 回: ***********************************************************************************/ void ADS1247ReadReg(uint8 reg, uint8 *pcmd, uint8 len) { ADS1247PinCs(0); ADS1247TxRxByte(reg | 0x20); //reg ADS1247TxRxByte(len – 1); //len while (len != 0) { *pcmd = ADS1247TxRxByte(0x00); pcmd++; len–; } ADS1247PinCs(1); }
/********************************************************************************** ** 函数名称: ** 功 能: ** 输入参数: ** 输出参数: ** 返 回: ***********************************************************************************/ void ADS1247WriteReg(uint8 reg, uint8 *pcmd, uint8 len) { ADS1247PinCs(0); ADS1247TxRxByte(reg | 0x40); //reg ADS1247TxRxByte(len – 1); //len while (len != 0) { ADS1247TxRxByte(*pcmd); pcmd++; len–; } ADS1247PinCs(1); }
/********************************************************************************** ** 函数名称: ** 功 能: ** 输入参数: ** 输出参数: ** 返 回: ***********************************************************************************/ static uint8 ADS1247TxRxByte(uint8 dt) { uint8 res = 0; uint8 i; for (i=8; i!=0; i–) { ADS1247PinSdi(((dt & 0x80) != 0) ? 1 : 0); ADS1247PinSclk(1); res <<= 1; if (ADS1247PinSdo() != 0) res |= 0x01; ADS1247PinSclk(0); dt <<= 1; } return res; }
/********************************************************************************** ** 函数名称: ** 功 能: ** 输入参数: ** 输出参数: ** 返 回: ***********************************************************************************/ static void AD1247IOInit(void) { GPIO_InitTypeDef GPIO_InitStructure; /* GPIO 定义 */ GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz; //=========== // GPIOA GPIO_InitStructure.GPIO_Pin = GPIO_Pin_5 | // ADS1247 SCLK GPIO_Pin_7; // ADS1247 SDI GPIO_InitStructure.GPIO_Mode = GPIO_Mode_Out_PP; GPIO_Init(GPIOA, &GPIO_InitStructure); // IN GPIO_InitStructure.GPIO_Pin = GPIO_Pin_6; // ADS1247 SDO GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IPU; GPIO_Init(GPIOA, &GPIO_InitStructure); //=========== // GPIOB GPIO_InitStructure.GPIO_Pin = GPIO_Pin_1 | // ADS1247 RESET GPIO_Pin_0; // ADS1247 START GPIO_InitStructure.GPIO_Mode = GPIO_Mode_Out_PP; GPIO_Init(GPIOB, &GPIO_InitStructure);
//=========== // GPIOC GPIO_InitStructure.GPIO_Pin = GPIO_Pin_5; // ADS1247 CS GPIO_InitStructure.GPIO_Mode = GPIO_Mode_Out_PP; GPIO_Init(GPIOC, &GPIO_InitStructure); //IN GPIO_InitStructure.GPIO_Pin = GPIO_Pin_4; // ADS1247 DRDY GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IPU; GPIO_Init(GPIOC, &GPIO_InitStructure); ADS1247PinReset(1); ADS1247PinCs(1); ADS1247PinStart(1); ADS1247PinSclk(0); }
/********************************************************************************** ** 函数名称: ** 功 能: ** 输入参数: ** 输出参数: ** 返 回: ***********************************************************************************/ static void ADS1247PinSclk(uint8 st) { GPIO_WriteBit(GPIOA, GPIO_Pin_5, (st == 0) ? Bit_RESET : Bit_SET); }
/********************************************************************************** ** 函数名称: ** 功 能: ** 输入参数: ** 输出参数: ** 返 回: ***********************************************************************************/ static void ADS1247PinSdi(uint8 st) { GPIO_WriteBit(GPIOA, GPIO_Pin_7, (st == 0) ? Bit_RESET : Bit_SET); }
/********************************************************************************** ** 函数名称: ** 功 能: ** 输入参数: ** 输出参数: ** 返 回: ***********************************************************************************/ static uint8 ADS1247PinSdo(void) { uint8 res; res = GPIO_ReadInputDataBit(GPIOA, GPIO_Pin_6); return res; }
/********************************************************************************** ** 函数名称: ** 功 能: ** 输入参数: ** 输出参数: ** 返 回: ***********************************************************************************/ static void ADS1247PinReset(uint8 st) { GPIO_WriteBit(GPIOB, GPIO_Pin_1, (st == 0) ? Bit_RESET : Bit_SET); }
/********************************************************************************** ** 函数名称: ** 功 能: ** 输入参数: ** 输出参数: ** 返 回: ***********************************************************************************/ void ADS1247PinStart(uint8 st) { GPIO_WriteBit(GPIOB, GPIO_Pin_0, (st == 0) ? Bit_RESET : Bit_SET); }
/********************************************************************************** ** 函数名称: ** 功 能: ** 输入参数: ** 输出参数: ** 返 回: ***********************************************************************************/ static void ADS1247PinCs(uint8 st) { GPIO_WriteBit(GPIOC, GPIO_Pin_5, (st == 0) ? Bit_RESET : Bit_SET); }
/********************************************************************************** ** 函数名称: ** 功 能: ** 输入参数: ** 输出参数: ** 返 回: ***********************************************************************************/ uint8 ADS1247PinDRdy(void) { uint8 res; res = GPIO_ReadInputDataBit(GPIOC, GPIO_Pin_4); return res; }
程序中调用的是ADS1247ReadADC() 函数读取数据,调用ADS1247RData(void)函数与调用ADS1247RData()函数现象一样
PGA设置为32,与设置成1没有什么明显的改善。原理图上的RDT RDW Rb没有焊接,AIN2,AIN3没有使用
ke yin:
回复 ke yin:
补充一点:采用的是内部基准
初始化程序如下:
void ADS1247Init(void) { uint8 buf[3]; uint8 i;
AD1247IOInit();
// ADS1247Reset();
//Stopreading datacontinuously ADS1247SDataC(); ADS1247Wakeup(); ADS1247SysOCal() ; // MUX0 buf[0] = 0x01| 1<<6; //buf[0]= 0<<5 | 0<<3 | 1<<0 ; ADS1247WriteReg(0x00, buf, 1);
// VBIAS switch( SENSOR_MODE ) { case PT_100: case PT_500: case PT_1000: case PT_10: case BA1: case BA2: case Cu: case Cu_50: case Cu_100: buf[0] = 0x00; break; default: buf[0] = 0x02; break; } // buf[0] = 0x02; ADS1247WriteReg(0x01, buf, 1); switch( SENSOR_MODE ) { case PT_100: case PT_500: case PT_1000: case PT_10: case BA1: case BA2: case Cu: case Cu_50: case Cu_100: // MUX1 buf[0] = (0 << 7) | //internal oscillator (1 << 5) | //Internal referenceis alwayson (0 << 3) | //REF0input pairselected (0 << 0); break; default: // MUX1 buf[0] = (0 << 7) | //internal oscillator (1 << 5) | //Internal referenceis alwayson (2 << 3) | //REF0input pairselected (0 << 0); break; } /* buf[0] = (1 << 5) | //Internal referenceis alwayson (2 << 3) | //REF0input pairselected (0 << 0); */ ADS1247WriteReg(0x02, buf, 1); // SYS0 switch(SENSOR_MODE ) { case PT_100: buf[0] = (Pt100_PGA << 4) | //PGA: These bit sdetermine the gain of the PGA (6 << 0); //DOR: 320SPS break; case PT_1000: buf[0] = (Pt1000_PGA << 4) | //PGA: These bit sdetermine the gain of the PGA (6 << 0); //DOR: 320SPS break; case PT_500: buf[0] = (Pt500_PGA << 4) | //PGA: These bit sdetermine the gain of the PGA (6 << 0); //DOR: 320SPS break; case PT_10: buf[0] = (Pt10_PGA << 4) | //PGA: These bit sdetermine the gain of the PGA (6 << 0); //DOR: 320SPS break; case BA1: buf[0] = (Ba1_PGA << 4) | //PGA: These bit sdetermine the gain of the PGA (6 << 0); //DOR: 320SPS break; case BA2: buf[0] = (Ba2_PGA << 4) | //PGA: These bit sdetermine the gain of the PGA (6 << 0); //DOR: 320SPS break; case Cu_50: buf[0] = (Gu50_PGA << 4) | //PGA: These bit sdetermine the gain of the PGA (6 << 0); //DOR: 320SPS break; case Cu_100: buf[0] = (Gu100_PGA << 4) | //PGA: These bit sdetermine the gain of the PGA (6 << 0); //DOR: 320SPS break; case Cu: buf[0] = (Gu_PGA << 4) | //PGA: These bit sdetermine the gain of the PGA (6 << 0); //DOR: 320SPS break; default: buf[0] = (k_PGA << 4) | //PGA: These bit sdetermine the gain of the PGA (6 << 0); //DOR: 320SPS break; } /* // SYS0 buf[0] = (0 << 4) | //PGA: These bit sdetermine the gain of the PGA (6 << 0); //DOR: 320SPS */ ADS1247WriteReg(0x03, buf, 1);
switch(SENSOR_MODE ) { case PT_100: buf[0] = (0 << 3) | //DRDY MODE: DOUT/DRDYpinfunctions onlyasDataOut (Pt100_SET << 0); //IMAG break; case PT_1000: buf[0] = (0 << 3) | //DRDY MODE: DOUT/DRDYpinfunctions onlyasDataOut (Pt1000_SET << 0); //IMAG break; case PT_500: buf[0] = (0 << 3) | //DRDY MODE: DOUT/DRDYpinfunctions onlyasDataOut (Pt500_SET << 0); //IMAG break; case PT_10: buf[0] = (0 << 3) | //DRDY MODE: DOUT/DRDYpinfunctions onlyasDataOut (7 << 0); //IMAG break; case BA1: buf[0] = (0 << 3) | //DRDY MODE: DOUT/DRDYpinfunctions onlyasDataOut (Ba1_SET << 0); //IMAG break; case BA2: buf[0] = (0 << 3) | //DRDY MODE: DOUT/DRDYpinfunctions onlyasDataOut (Ba2_SET << 0); //IMAG break; case Cu_50: buf[0] = (0 << 3) | //DRDY MODE: DOUT/DRDYpinfunctions onlyasDataOut ( Gu50_SET << 0); //IMAG break; case Cu_100: buf[0] = (0 << 3) | //DRDY MODE: DOUT/DRDYpinfunctions onlyasDataOut ( Gu100_SET << 0); //IMAG break; case Cu: buf[0] = (0 << 3) | //DRDY MODE: DOUT/DRDYpinfunctions onlyasDataOut ( Gu_SET << 0); //IMAG break; default: buf[0] = (0 << 3) | //DRDY MODE: DOUT/DRDYpinfunctions onlyasDataOut (0 << 0); //IMAG break; } /* // IDAC0 buf[0] = (0 << 3) | //DRDY MODE: DOUT/DRDYpinfunctions onlyasDataOut (0 << 0); //IMAG */ ADS1247WriteReg(0x0a, buf, 1); // IDAC1 switch( SENSOR_MODE ) { case PT_100: case PT_500: case PT_1000: case PT_10: case BA1: case BA2: case Cu: case Cu_50: case Cu_100: buf[0] = (0 << 4) | //I1DIR (1 << 0); //I2DIR break; default: buf[0] = (0 << 4) | //I1DIR (0xc << 0); //I2DIR break; } /* // IDAC1 buf[0] = (0x0 << 4) | //I1DIR (0xc << 0); //I2DIR */ ADS1247WriteReg(0x0b, buf, 1);
ADS1247RDataC(); ADS1247PinStart(1);
Johnsin Tao:
回复 ke yin:
Hi
从你描述的现象看应该是ADC转换的精度偏低导致的,很程序没有关系。
你可以参考一下datasheet有效位的参数表: http://www.ti.com.cn/cn/lit/ds/symlink/ads1247.pdf 第十二、十三页。
采样率越低,有效位越高;PGA的设置也是越小,有效位越高。 所以理论上较小PGA是可以降低误差,但是这个取决于你的模拟输入,不易改变。
建议你采用外部参考电压看看,内部参考源的精度是0.5%, 如果选择外部参考电压精度可以是0.1%甚至更高。另外注意一下供电的Noise,以及数模隔离的问题。
ke yin:
回复 Johnsin Tao:
谢谢您的回复
现在我把输入端用线短接,稳定性还不错,加上信号源之后数据有跳变现象,但是信号源应该没有问题,打电话问信号源厂家,精度能达到1uV,是不是由于引线把噪声给引入了啊。还有,就是如果把先双绞处理下会好一些,但是,如果用手握住双绞线数据变化很剧烈。现在这环境干扰都这么大,到现场估计都不能用了,请大虾支支招,我实在没有招了。
ke yin:
回复 ke yin:
我的模拟地与数字地是单点接地,怎么处理更好一些呢?
Johnsin Tao:
回复 ke yin:
Hi
从你描述的现象看确实可能是输入部分有noise导致的。
关于RTD的应用,或许你可以参考这个文档: http://proddms.itg.ti.com/stage/lit/an/sbaa201/sbaa201.pdf 关于输入部分的。
另外数字GND,模拟GND确实是需要端点接各自的GND Plane.
ke yin:
回复 Johnsin Tao:
试了一天,没有什么改善,我看ADS1247内部有滤波器,这个滤波器怎么样啊,这个片子能不嫩做到一秒钟出40个数,精度在10uV以内啊?
ke yin:
回复 Wayne Xu:
谢谢回答,采样速率设定为40SPS以后,好了很多,短接输入时比较稳定,上下波动也就10uV左右,但是用信号源加信号时,波动还是比较大,有时能达到400uV,信号源输出线一米左右,还有一个现象,我输入端短接线使用一根20cm的双绞线做的,当用手触摸双绞线时,信号飘的也很离谱,这种问题怎么解决啊?