This thread has been locked.

If you have a related question, please click the "Ask a related question" button in the top right corner. The newly created question will be automatically linked to this question.

ADS1246: 校准

Part Number: ADS1246

TI工程师,你好:

我在小电流(-20mA~+20mA)测量方案种使用了ADS1246。( VREFP=2.5V,VREFN=0V,AVDD=+2.5V,AVSS=-2.5V,使用75ohm的电阻将电流转换成电压,故最大输入电压为±20mA*75ohm=±1.5V)

因为FSC已经有了出厂设置值,OFS初始值为0,所以我在最初的校准方案中,仅使用了SELFOCAL指令更新了OFS寄存器,运行正常,读数正常。( PGA=1, ODR=10SPS )

我想进一步通过校准减少温度对结果的影响,我看芯片还支持系统偏移校准、系统增益校准。(芯片工作温度是-40~125,是不是不超过这个温度运行,芯片自带的校准功能就可以减少温度的影响?)

现在有几个问题:

1. 这个帖子中你们对三种校准作了解释,同时提到,通常只运行SELFOCAL,所以在我方案中,SYSOCAL和SYSGCAL是否有必要?还是说需要我自己模拟温度和数据之间的关系,另写校准方案?另外我看芯片内部有温度传感器,这个是为了校准使用的吗?

e2echina.ti.com/.../ads1146-ads1146

2. 请问使用SYSOCAL和SYSGCAL指令时,还需要工作人员手动干预输入吗?比如在进行偏移校准前,输入端需要短接? 在进行增益校准前,输入电流需要达到33.33mA?

3. 温度会影响VREF(我理解对吗?),对24位有效数据进行转换时,如电流值=0x13 2f ed * 2500mV / 0x7FFFFF / 75ohm = 4.997mA,这里的2500mV在不同的温度下,实际情况下可能应该是2480mV,这个可以通过校准补偿掉吗?就是我校准后,转换公式中可以乘以2500,还是说我要拿到VREF的实际值,然后带入转换公式中计算呢?

4. 对于得到的24位有效数据你们建议直接平均滤波吗?有必要做去除最大最小值的预处理吗?

如果有哪里我表述不准确或不清楚,请指正,谢谢!

  • 您好,

    我稍后会具体看下您的问题

  • 很抱歉回复这么晚!

    ADS1246具有失调和增益校准功能,因为失调和增益会随温度漂移,因此在温度改变后执行失调和增益校准可以提供测量精度。

    1、是否有必要建议您以实际测试结果为准。

    内部温度传感器与校准没有关系,不是为校准使用的。

    2、在SYSGCAL (系统增益校准)过程中,用户需要将相应的最大刻度电压输入器件的选定输入,此电压必须无噪声且稳定。

    SYSOCAL (系统失调校准),它是假定在ADC前端有某种外部电路(可能是一个mux或一个用于信号调节的放大器),在前端这里将输入短接。

    3、是的,温度会影响VREF,VREF存在温漂。这个不能通过校准补偿掉。这个需要拿到VREF的实际值,然后带入转换公式中计算,得到的结果才是真正的结果。因此VREF需要使用温漂小的电压。

    4、这个需要根据您的应用来决定,如果外部因素使得转换结果不准确而通过平均滤波更接近真实值的话,可以使用平均滤波。

    是否去除最大最小值,取决于最大值最小值是怎样产生的,如果是干扰产生的,那么可以去掉,如果最大和最小值是实际测量值,去掉后就失去了测量的意义,那么就不能去掉。

  • 你好,我在做系统失调和增益校准时遇到一些问题,不知道我哪个步骤出现了问题。

    1、发送SELFOCAL命令, 记录OFC、FSC寄存器,分别为0x000009, 0x3FFBC0,启用START进行ADC转换,正常运行

    2、将J2两端短接,然后设置MUXCAL为0x01,发送SYSOCAL命令,记录OFC、FSC寄存器,分别为0x000007, 0x3FFBC0,启用START进行ADC转换

    3、取消J2两端短接,然后设置MUXCAL为0x00,恢复为正常模式,记录OFC、FSC寄存器,分别为0x000013, 0x3FFBC0,启用START进行ADC转换

    我不理解为何恢复为正常模式的时候,OFC数据会发生变化?我第三步并没有发送校准命令。

    另外,校准一般是出厂前做的,在得到偏移和增益系数后,我是不是需要存下来,下次芯片重启时,让OFC自动更新为这个值?

    还有请问您提到的温度变化后执行校准,可以在芯片运行的过程中,一旦发现温度变化过大,就发送自校准命令吗?

    以下是ADC校准涉及的主要代码,供查阅,非常感谢!

    e_CLIState CLI_Start(uint8_t Channel, uint8_t* Data_H, uint8_t* Data_M, uint8_t* Data_L)
    {
    	switch (CLIFlow[Channel])
    	{	
    		case CLI_IDLE:
    		{
    			ADC_SCS_L(Channel);
    			ADC_SCLK_L(Channel);
    			ADC_SDIN_L(Channel);
    			ADC_SADSTR_L(Channel);
    			
    			CLI_WriteData(Channel, 0x4A); // write ID register, address is 0Ah
    			CLI_WriteData(Channel, 0x00); // write 1 byte to the ID
    			CLI_WriteData(Channel, 0x08); // set the bit DRDY
    			
    			CLI_WriteData(Channel, 0x43); // write SYS0 register, address is 03h
    			CLI_WriteData(Channel, 0x00); // write 1 byte to the SYS0
    			CLI_WriteData(Channel, 0x01); // set the PGA and DOR
    			
    			CLI_WriteData(Channel, 0x41); // write VBIAS register, address is 01h
    			CLI_WriteData(Channel, 0x00); // write 1 byte to the VBIAS
    			CLI_WriteData(Channel, 0x00); // set VBIAS
    			
    			CLI_WriteData(Channel, 0x62); // selfocal
    			
    			CLIFlow[Channel] = CLI_WAITDRDY;
    			DRDY_WaitStart[Channel] = HAL_GetTick();
    			break;
    		}
    		case CLI_NORMAL:
    		{
    			CLI_WriteData(Channel, 0x42); // write MUX1 register, address is 02h
    			CLI_WriteData(Channel, 0x00); // write 1 byte to the MUX1
    			CLI_WriteData(Channel, 0x00); // normal operation
    			
    			CLIFlow[Channel] = CLI_WAITDRDY;
    			DRDY_WaitStart[Channel] = HAL_GetTick();
    		}
    		case CLI_SYSOCAL:
    		{
    			CLI_WriteData(Channel, 0x42); // write MUX1 register, address is 02h
    			CLI_WriteData(Channel, 0x00); // write 1 byte to the MUX1
    			CLI_WriteData(Channel, 0x01); // offset calibration
    			CLI_WriteData(Channel, 0x60); // sysocal
    			
    			CLIFlow[Channel] = CLI_WAITDRDY;
    			DRDY_WaitStart[Channel] = HAL_GetTick();
    			break;
    		}
    		case CLI_SYSGCAL:
    		{
    			CLI_WriteData(Channel, 0x42); // write MUX1 register, address is 02h
    			CLI_WriteData(Channel, 0x00); // write 1 byte to the MUX1
    			CLI_WriteData(Channel, 0x02); // gain calibration
    			CLI_WriteData(Channel, 0x61); // sysgcal
    			
    			CLIFlow[Channel] = CLI_WAITDRDY;
    			DRDY_WaitStart[Channel] = HAL_GetTick();
    			break;
    		}
    		case CLI_RESET:
    		{
    			CLI_WriteData(Channel,0x06); // reset command
    			USER_Delay_ms(1); // SPI communication can be only be started 0.6ms after the reset command is issued
    			
    			*Data_H = 0xFF;
    			*Data_M = 0xFF;
    			*Data_L = 0xFF;
    			CLIFlow[Channel] = CLI_IDLE;
    			break;
    		}
    		case CLI_WAITDRDY:
    		{
    			CLIWaitTime = HAL_GetTick() - DRDY_WaitStart[Channel];
    			
    			if (CLIWaitTime > 2000) 
    			{
    				CLIFlow[Channel] = CLI_RESET;//no response in 2s, need to reset
    				return CLI_ADERROR;
    			}
    
    			ADC_SADSTR_H(Channel);
    			
    			if (HAL_GPIO_ReadPin(PORT_CLI[Channel],ADC_SDOUT_Pin[Channel]) == GPIO_PIN_RESET) 
    			{
    				CLIFlow[Channel] = CLI_READDATA;
    			}
    			break;
    		}
    		case CLI_READDATA:
    		{		
    			CLI_WriteData(Channel, 0x12); //RDATA command
    
    			*Data_H = CLI_ReceiveData(Channel, 0xFF); //NOP
    			*Data_M = CLI_ReceiveData(Channel, 0xFF); //NOP
    			*Data_L = CLI_ReceiveData(Channel, 0xFF); //NOP
    			
    			/*
    			NOP or any other command that does not load the data output register is needed to be sent,
    			then DOUT/DRDY can be polled for a '0' instead of waiting for a falling edge.
    			*/
    			
    			//test start				
    			CLI_WriteData(Channel, 0x24); // read OFC register, address is 04h
    			CLI_WriteData(Channel, 0x02); // read 3 byte to the OFC
    			OFC0 = CLI_ReadData(Channel);
    			OFC1 = CLI_ReadData(Channel);
    			OFC2 = CLI_ReadData(Channel);
    			
    			CLI_WriteData(Channel, 0x27); // read FSC register, address is 07h
    			CLI_WriteData(Channel, 0x02); // read 3 byte to the FSC
    			FSC0 = CLI_ReadData(Channel);
    			FSC1 = CLI_ReadData(Channel);
    			FSC2 = CLI_ReadData(Channel);
    			//test end
    			
    			CLI_WriteData(Channel, 0xFF); //NOP
    			
    			CLIFlow[Channel] = CLI_WAITDRDY;
    			DRDY_WaitStart[Channel] = HAL_GetTick();
    			return CLI_OK;
    		}
    		default:
    		{
    			CLIFlow[Channel] = CLI_RESET;
    			return CLI_ADERROR;
    		}
    	}
    	return CLI_PROCESS;
    }

  • 我不理解为何恢复为正常模式的时候,OFC数据会发生变化?我第三步并没有发送校准命令。

    每次都这样吗?SPI通信是否收到了干扰?

    另外,校准一般是出厂前做的,在得到偏移和增益系数后,我是不是需要存下来,下次芯片重启时,让OFC自动更新为这个值?

    我觉着没必要存下来,因为出厂校准时的温度不一定与工作环境温度一样,温度发生变化时,offset失调和增益会随温度漂移。

  • TI建议在上电后、温度或增益发生变化后和通道发生改变后执行校准:

  • 每次都这样。而且我发现在正常运行的过程中,增益也会发生变化,比如从0x3FFBC0到0x23FBC0,稍一会儿又恢复到0x3FFBC0,按您的解释,这是受环境温度的影响?所以当我监测到增益发生变化或温度变化1°C的时候,需要重新执行自校准是吗?

  • 谢谢您的回答!我还是有些疑惑,出厂后装置不再进行校准,如果数据不存下来,gain应该是多少呢?我理解的是,非人工介入的话,装置只能执行自校准吧,那只调整了offset,并没有调整gain呀?

  • 很抱歉今天没有来得及看您的问题,明天我会具体看下您的问题。

  • 谢谢,我昨天试了一下在运行过程中,当增益发生变化就重新进行自校准,发现增益很不稳定,几乎每隔几次采样就会发生波动,请问这是正常的吗?

  • 很抱歉现在才回复您!

    每次都这样。而且我发现在正常运行的过程中,增益也会发生变化,比如从0x3FFBC0到0x23FBC0,稍一会儿又恢复到0x3FFBC0,按您的解释,这是受环境温度的影响?

    您的意思是说FSC[2:0]寄存器值在不执行增益校准和不改变增益的的情况下,寄存器值会改变?如果是这种现象的话,那么是不正常的。您需要确认寄存器读取时序是否正常或SPI通信波形是否收到了干扰?或读多次取其他寄存器值是否是期望值?

    如果您执行了增益校准或者改变了增益设置,FSC[2:0]寄存器值有可能会变。

    所以当我监测到增益发生变化或温度变化1°C的时候,需要重新执行自校准是吗?

    如上截图所示,在温度或增益发生变化后TI是建议执行校准的。在进行增益校准之前,应先执行offset校准。

  • 谢谢您的回答!我还是有些疑惑,出厂后装置不再进行校准,如果数据不存下来,gain应该是多少呢?我理解的是,非人工介入的话,装置只能执行自校准吧,那只调整了offset,并没有调整gain呀?

    在ADS124x上,该器件已为每个PGA设置提供出厂调整的FSC值,可提供准确的结果。如果您决定执行板级增益校准,则必须将相应的满刻度信号应用到设备的选定输入,此电压必须准确稳定。大多数用户依赖默认或出厂调整的FSC重置值。FSC重置值在出厂时已调整,可能因设备和PGA设置而异。因此我认为使用在不同工作环境中的增益校准参数是不准确的,还不如直接使用出厂调整的FSC值。

    当用户在不同通道上执行不同的测量时,或当用户每次更改通道时可能无法等待所需的校准延迟时,可以将保存的校准值直接写入OFC和FSC寄存器。用户可以在开始时对每个通道/设置执行一次校准;将OFC寄存器值存储在微处理器内存中,然后在重新配置设备时重新写入相应的校准值,而无需等待所需的校准延迟。更改OFC或FSC寄存器值将影响ADS1246/7/8的输出代码。

  • 我昨天试了一下在运行过程中,当增益发生变化就重新进行自校准,发现增益很不稳定,几乎每隔几次采样就会发生波动,请问这是正常的吗?

    您这里还是说FSC[2:0]寄存器值不稳定吗?我在内网发现了有客户与您有同样的问题,这好像与读取寄存器值的时机不对,我将帖子截图发您邮箱,您细看下。

  • 非常感谢您的回答,我测试下来没有问题了,谢谢!!