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.

[参考译文] AM3358:使用 ADC 读取时的信号漂移

Guru**** 2798555 points
请注意,本文内容源自机器翻译,可能存在语法或其它翻译错误,仅供参考。如需获取准确内容,请参阅链接中的英语原文或自行翻译。

https://e2e.ti.com/support/microcontrollers/arm-based-microcontrollers-group/arm-based-microcontrollers/f/arm-based-microcontrollers-forum/1618202/am3358-signal-drift-when-reading-with-adc

部件号: AM3358

(这与之前的查询有关,我想我已链接到它,但更新系统没有明确说明我是这样做的。) 这次我有不同的问题。
对于背景、此传感器由 BeagleBone Black 在 Linux 下使用 pru0 使用 C 代码读取。   我们的问题仍然是、当启用 ADC 阶跃时、信号会出现 1030mV 漂移。  我将在下面发布我们的代码、但首先这里是简单的传感器电路。   

circuit.png

基本上、当光触发 CR1 时、TO_AINx 上的电压输出)... 接近于零。  当光线受阻时、TO_AINx 上的电压输出会上升至 1.6V。  该电路是我们系统的基础、在我们的应用中表现良好。  更改它目前不是一个选项。

问题在于、当我们通过单位增益电压跟随器在示波器上监测 TO_AINx 时、当光线到达 CR1 时、信号接近于零(例如 5mV)、直到我们开始使用 BeagleBone 通过 AM3558 的 ADC 读取信号。   然后、信号漂移在 1030mV 之间。

该信号当前进入 ADC 上的 AIN0。  我们还使用 AIN5 作为读取另一个传感器的第二步。  我们只启用了两个步骤。   它们处于单次触发模式。  同样、我将在下面发布设置代码。

关于这一点、我有一些建议、希望在请进行更改之前获得 TI 的意见。

1) 有人建议 AIN5-AIN7 由于其电荷耦合方式、实现这一目的的可能性较小。  我们可以尝试使用 AIN6、而无需在板上进行过多的黑客攻击。  (但该信号将通过上述单位增益电压跟随器电路,合并这两项更改。)


a) 此建议是否有效?

B) 如果有效、我是否必须切断与 AIN0 的连接以消除电流影响、即使我禁用 AIN0 也是如此?

2) 建议将所有未使用的 AIN 输入接地。 这对解决这个问题是否有价值?

3) 是否有任何可减少漂移问题的通道配置选项?   目前、我们在环路中以尽可能快的速度读取输入。

4) AIN5 中的信号似乎不存在该漂移问题。  但是、在这种情况下、信号通过自定义电流环路到模拟转换器输出级上的运算放大器。  在我看来、这使我相信具有漂移的部分可能有漏电流。

以下是涉及的两个 PRU 代码例程。

static void ADCConfigure(void)
{
	unsigned int i, count, data;
// // Actual sensor name as been replaced with "SENSOR WITH DRIFT" to mask a bit of our proprietary process.
	/* Enable ADC module clock */
	HWREG(SOC_CM_WKUP_REGS + CM_WKUP_ADC_TSC_CLKCTRL) = 0x02;

	/* Disable ADC module for configuration */
	HWREG(SOC_ADC_TSC_0_REGS + TSC_ADC_SS_CTRL) &= ~0x01;

	/* fs = 24MHz / ((CLKDIV+1)*2*Channels*(OpenDly+Average*(14+SampleDly)))
	 *    = 53.57kHz
	 * CLKDIV = 0
	 * Channels = 1
	 * Average = 16
	 * OpenDly = 0
	 * SampleDly = 0
	 */
	HWREG(SOC_ADC_TSC_0_REGS + TSC_ADC_SS_ADC_CLKDIV) = 0;

	HWREG(SOC_ADC_TSC_0_REGS + TSC_ADC_SS_ADCRANGE) = 0xFFF << 16;

	/* Disable all steps for now */
	HWREG(SOC_ADC_TSC_0_REGS + TSC_ADC_SS_STEPENABLE) &= 0xFF;

	/* Unlock step configuration */
	HWREG(SOC_ADC_TSC_0_REGS + TSC_ADC_SS_CTRL) |= 0x04;


	//Step 0 config: SW mode, one shot mode, fifo 0, channel 0, AIN0 on the Beaglebone Black, 4 samples averaged
	//SENSOR WITH DRIFT
	HWREG(SOC_ADC_TSC_0_REGS + TSC_ADC_SS_STEPCONFIG(0)) = 0x00000008;
	
	//Step 1 config: SW mode, one shot mode, fifo 0, channel 1, AIN1 on the Beaglebone Black, 4 samples averaged
	//FLOW METER
//	HWREG(SOC_ADC_TSC_0_REGS + TSC_ADC_SS_STEPCONFIG(1)) = 0x00080000; //no averaging
//	HWREG(SOC_ADC_TSC_0_REGS + TSC_ADC_SS_STEPCONFIG(1)) = 0x00080004; //averages 2 samples
	HWREG(SOC_ADC_TSC_0_REGS + TSC_ADC_SS_STEPCONFIG(1)) = 0x00080008; //averages 4 samples
//	HWREG(SOC_ADC_TSC_0_REGS + TSC_ADC_SS_STEPCONFIG(1)) = 0x0008000C; //averages 8 samples	
//	HWREG(SOC_ADC_TSC_0_REGS + TSC_ADC_SS_STEPCONFIG(1)) = 0x00080010; //averages 16 samples	
	
	//Step 2 config: SW mode, one shot mode, fifo 0, channel 4, AIN4 on the Beaglebone Black, 4 samples averaged
	//UNUSED
	//HWREG(SOC_ADC_TSC_0_REGS + TSC_ADC_SS_STEPCONFIG(2)) = 0x00200008;  //averages 4 samples
	
	//Step 2 config: SW mode, one shot mode, fifo 0, channel 5, AIN5 on the Beaglebone Black, 4 samples averaged
	//UNUSED
	//HWREG(SOC_ADC_TSC_0_REGS + TSC_ADC_SS_STEPCONFIG(2)) = 0x00280008;  //averages 4 samples 

	
	HWREG(SOC_ADC_TSC_0_REGS + TSC_ADC_SS_STEPDELAY(0)) = 0xFF000000;   //255
	HWREG(SOC_ADC_TSC_0_REGS + TSC_ADC_SS_STEPDELAY(1)) = 0xFF000000;	//255
//	HWREG(SOC_ADC_TSC_0_REGS + TSC_ADC_SS_STEPDELAY(0)) = 0xC8000000;	//200
//	HWREG(SOC_ADC_TSC_0_REGS + TSC_ADC_SS_STEPDELAY(1)) = 0xC8000000;	//200
//	HWREG(SOC_ADC_TSC_0_REGS + TSC_ADC_SS_STEPDELAY(0)) = 0xAF000000;	//175
//	HWREG(SOC_ADC_TSC_0_REGS + TSC_ADC_SS_STEPDELAY(1)) = 0xAF000000;	//175
//	HWREG(SOC_ADC_TSC_0_REGS + TSC_ADC_SS_STEPDELAY(2)) = 0xFF000000;
	
	/* Enable channel ID tag */
	HWREG(SOC_ADC_TSC_0_REGS + TSC_ADC_SS_CTRL) |= 0x02;

	/* Clear end-of-sequence interrupt */
	HWREG(SOC_ADC_TSC_0_REGS + TSC_ADC_SS_IRQSTATUS) = 0x02;

	/* Enable end-of-sequence interrupt */
	HWREG(SOC_ADC_TSC_0_REGS + TSC_ADC_SS_IRQENABLE_SET) = 0x02;

	/* Lock step configuration */
	HWREG(SOC_ADC_TSC_0_REGS + TSC_ADC_SS_CTRL) &= ~0x04;

	/* Empty FIFO 0 */
	count = HWREG(SOC_ADC_TSC_0_REGS + TSC_ADC_SS_FIFOCOUNT(0));
	for (i = 0; i < count; i++) {
		data = HWREG(SOC_ADC_TSC_0_REGS + TSC_ADC_SS_FIFODATA(0));
	}

	/* Enable ADC module */
	HWREG(SOC_ADC_TSC_0_REGS + TSC_ADC_SS_CTRL) |= 0x01;
}
static void ReadSensorValues()
// Actual sensor name as been replaced with "Drifting Sensor" to mask a bit of our proprietary process.
//This procedure reads the current values from the Sensor with Drift and the Flow Sensor.
//(The Flow Sensor value returned is actually calculated by average the last 10 Flow Sensor values. - NOT TRUE CURRENTLY)
{
	int i;
	unsigned int count;
	unsigned int StepRead;  // the step that was read
	unsigned int RawAnalog; //bottom detector data 	
//	const unsigned int Flow_Sensor_Array_Size = 10;
//	static unsigned int Flow_Sensor_Array[10];
//	static unsigned int Flow_Sensor_Sum;
//	static unsigned int Flow_Sensor_Avg;
//	static unsigned int fspnr;
	
	// Start step 
	HWREG(SOC_ADC_TSC_0_REGS + TSC_ADC_SS_STEPENABLE) = 0xE; // enables steps 1,2 and 3.  TSC Charge is not enabled (bit 0)
		
	// Wait for interrupt
	while (!(HWREG(SOC_ADC_TSC_0_REGS + TSC_ADC_SS_IRQSTATUS)&0x02));
			
	// Clear interrupt 
	HWREG(SOC_ADC_TSC_0_REGS + TSC_ADC_SS_IRQSTATUS) = 0x02;
					
	Data = 0xFFFFFFFF;
												
	count = HWREG(SOC_ADC_TSC_0_REGS + TSC_ADC_SS_FIFOCOUNT(0));


// #PRAGMA MUST_ITERATE	
	for (i = 0; i < count; i++)	// count is the number of readings 
								// in the ADC FIFO buffer
	{
		Data = HWREG(SOC_ADC_TSC_0_REGS + TSC_ADC_SS_FIFODATA(0));
		StepRead = (Data >> 16) & 0xF;
		RawAnalog = Data & 0xFFF;
							
		switch (StepRead)
		{
			case 0:  //DRIFTING SENSOR
				DriftingSensor_Voltage = RawAnalog;
				break;
					
			case 1:  //FLOW SENSOR
				Curr_FlowSensorValue = RawAnalog;
				if ((CALIBRATE_PID) && (GelPrimed) && (MaxFSVReached == 0))
				{
					ReadsToMaxFSV++;
					if ((Curr_FlowSensorValue > Max_FSV) || (Curr_FlowSensorValue < 114))
					//FSV still increasing or FSV is not above .05v yet
					{
						Max_FSV = Curr_FlowSensorValue;
						ReadsSince_FSV_Increase = 0;
					}
					else
					{
						ReadsSince_FSV_Increase++;
						if (ReadsSince_FSV_Increase > 900) //assume MaxFSVReached  (4000 = 500 ms not increasing)
						{
							MaxFSVReached = 1;
	//						SavedMax = Max_FSV;
//							__R30 |= SignalToSM;  // set signal line to Singulator Module high
//							SM_Signal_On = 1;
//							SM_Read_Count = 0;
						}
					}
				}

//				if (Curr_FlowSensorValue > Max_FSV)
//					Max_FSV = Curr_FlowSensorValue;
				break;
				
//			case 2:
//				break;
						
			default:  // flash red LED indicating a problem
//				for (j=0;j<20;j++)
//				{
//					FlashPanelLEDs(1,0,0,0,0,1,10);
//				}
				break;
		} //end of Switch statement
										
	}	//  bottom of for (i = 0; i < count; i++) loop	
		// finished loop reading all values from ADC FIFO buffer
}
  • 请注意,本文内容源自机器翻译,可能存在语法或其它翻译错误,仅供参考。如需获取准确内容,请参阅链接中的英语原文或自行翻译。

    您好 Walter、  

    感谢您联系我们!  请允许我花些时间来了解一下、我将通过星期五 2/20 更新您的想法。

    此致、
    Karam

  • 请注意,本文内容源自机器翻译,可能存在语法或其它翻译错误,仅供参考。如需获取准确内容,请参阅链接中的英语原文或自行翻译。

     Karam Haddad 感谢您的观看。  我知道我提供了很多信息。  我已继续进行故障排除、下面是我所做的一些更改、我认为这些更改有所帮助。   我也会稍微重点介绍一下。

    我想我已经说过、传感器输出直接连接到 AIN0。  它还进入单位增益缓冲运算放大器、其输出之前未连接到 AM3558/BeagleBone ADC。  我现在已将其直接连接到 AIN6。  然后、我们使用此语句更改了 ADCConfigure 中的步骤 1

    HWREG(SOC_ADC_TSC_0_REGS + TSC_ADC_SS_STEPCONFIG(0)) = 0x00370008

    我们的流程可以随着这一变化正常运行、并且存在一些初始漂移、然后稳定回接近正常值。  我们将继续对此进行测试。

    我眼前的问题是这个->

    我是否应该切断将 SEED 传感器输出直接连接到 AIN0 的布线以进一步减少该连接可能导致的任何问题?

  • 请注意,本文内容源自机器翻译,可能存在语法或其它翻译错误,仅供参考。如需获取准确内容,请参阅链接中的英语原文或自行翻译。

    您好 Walter、

    在您的原理图中、TO_AINx 似乎可能是高阻抗传感器节点。 使用 AM335x ADC 时、采样会干扰高阻抗节点、因为该输入是多路复用的、并通过采样电容器进行采样。

    您已经提到、AIN5 中的信号不存在漂移问题、它通过运算放大器发出。 这强烈表明另一个通道上的漂移与传感器节点为高阻抗相关。 运算放大器路径在 ADC 输入端显示低阻抗、因此 ADC 采样操作不太可能发生节点电压变化。

    我需要确认以下几点:

    • 请提供 R1 和任何其他元件的值、以便我们可以了解 ADC 输入端的源阻抗。
    • 请确认电路中显示的 1.8V 电压轨的来源。 是同一电源轨馈送 VDDA_ADC/VREF 还是单独的 1.8V 电源?

    需要注意/避免的一些事项:

    • 请确认您的 ADC 时钟、采样率等 超出限值运行可能会导致您看到的问题: AM335x 数据表表表 表 5-16。 TSC_ADC 电气参数 
      • ADC 时钟频率最小值:1MHz 、最大值:3MHz
      • 最大采样率:200KSPS 等
    • 当源阻抗较高时、应避免采集窗口较短。 AM335x 勘误表 公告 1.0.32 提到“如果需要更高的 Rseries_max 值、可能需要通过增加 SampleDelay 来增加采样时间、以便为输入电容提供更多的充电时间。“
    • 避免将未使用的 AIN 引脚保持悬空。 请参阅此处的“TSC ADC AIN 端子未使用“指南: AM335x 勘误表 公告 1.0.32

    此致、
    Karam  

  • 请注意,本文内容源自机器翻译,可能存在语法或其它翻译错误,仅供参考。如需获取准确内容,请参阅链接中的英语原文或自行翻译。

     Karam Haddad  感谢您的答复。   

    请务必查看下面的问题。  我认为我们走在正确的轨道上。

    R1 为 1 兆欧。

    该 1.8V 来自我们定制电路板上的 1.8V 线性稳压器、因此它与馈送 VDDA_ADC/VREF 的电源轨是分开的。  我们也使用 1.8V 稳压器为运算放大器供电、这是避免将超过 1.8V 的电压驱动到 ADC 中而使其烧坏的一种方法。

    接地在整个过程中是共用的。

    我想您已经打了指甲。

    我已经通过单位增益缓冲运算放大器将信号连接到 AIN6、我们正在读取该信号。  我们仍然看到一些漂移、但没有那么糟糕。

    以下是我的问题:

    1) 我可以切断从传感器到 AIN0 的布线(原始连接不会通过运算放大器。) 这似乎是正确的一步。  请确认、因为切割容易、但维修不方便。

    2) 指向避免将未使用的 AIN 引脚悬空的指南的链接没有检索任何内容。  我需要将它们连接为高电平还是低电平?

    3) 我必须得到一个将回来星期一的人的时钟频率和采样率。  是否通过软件为 ADC 设置了这些值?

    4) 一旦我们降低输入阻抗,我们可以保持一个高采集窗口吗?

  • 请注意,本文内容源自机器翻译,可能存在语法或其它翻译错误,仅供参考。如需获取准确内容,请参阅链接中的英语原文或自行翻译。

    请务必查看下面的问题。  我认为我们走在正确的轨道上。

    R1 为 1 兆欧。

    该 1.8V 来自我们定制电路板上的 1.8V 线性稳压器、因此它与馈送 VDDA_ADC/VREF 的电源轨是分开的。  我们也使用 1.8V 稳压器为运算放大器供电、这是避免将超过 1.8V 的电压驱动到 ADC 中而使其烧坏的一种方法。

    接地在整个过程中是共用的。

    我想您已经打了指甲。

    我已经通过单位增益缓冲运算放大器将信号连接到 AIN6、我们正在读取该信号。  我们仍然看到一些漂移、但没有那么糟糕。

    以下是我的问题:

    1) 我可以切断从传感器到 AIN0 的布线(原始连接不会通过运算放大器。) 这似乎是正确的一步。  请确认、因为切割容易、但维修不方便。

    2) 指向避免将未使用的 AIN 引脚悬空的指南的链接没有检索任何内容。  我需要将它们连接为高电平还是低电平?

    3) 我必须得到一个将回来星期一的人的时钟频率和采样率。  是否通过软件为 ADC 设置了这些值?

    4) 一旦我们降低输入阻抗,我们可以保持一个高采集窗口吗?

  • 请注意,本文内容源自机器翻译,可能存在语法或其它翻译错误,仅供参考。如需获取准确内容,请参阅链接中的英语原文或自行翻译。

     Karam Haddad 

    我相信周期为 5ns、因此时钟速度为 200MHz。 这不是我们配置的。 这些数据来源于 BeagleBone Black Rev C 的文档、其中表明 PRU 可以在 200MHz 下运行。  

    我们每毫秒采集 10 个样本。  这应该是 10kHz 的采样率。  

  • 请注意,本文内容源自机器翻译,可能存在语法或其它翻译错误,仅供参考。如需获取准确内容,请参阅链接中的英语原文或自行翻译。

    您好 Walter、

    谢谢你的信息,我很抱歉与先前附加的链接的错误. 我在这个答复中再次附上它。 R1 的高阻抗可能是导致出现症状的因素。

    关于您的问题:

    1 和 2。 请勿将未使用的 AIN 连接至高电平。 如果未使用 AIN0、勘误表建议您通过 500Ω 电阻将每个未使用的 AIN 连接到 VSSA_ADC、或使未使用的 AIN 保持断开状态、且无 PCB 布线。 我再次将其链接在此处: AM335x 器件勘误表 公告 1.0.32“TSC  ADC AIN 端子未使用“。

    200MHz 时钟是 PRU 时钟、而不是 ADC 时钟。 ADC 时钟来自 TSC ADC 时钟输入 ADC_clk、并由 ADC_CLKDIV 寄存器分频、该寄存器通过软件完成。  有关更多信息、请参阅 AM335x TRM:12.2.2 TSC_ADC 时钟和复位管理、请参阅 12.5.1.13 ADC_CLKDIV 寄存器部分。

    4.保持或更改采集窗口取决于您的应用要求。 较低的源阻抗通常可缩短采集时间、但如果采样率有裕度、则可以保持较长的时间。

    请告诉我,如果这有帮助!

    此致、
    Karam

  • 请注意,本文内容源自机器翻译,可能存在语法或其它翻译错误,仅供参考。如需获取准确内容,请参阅链接中的英语原文或自行翻译。

     Karam Haddad 感谢您提供此信息。  这次我能够访问勘误表、并查看其中提到了优先选择通过 500 Ω 电阻器将未使用的 AIN 连接到 VSSA_ADC、但也提到未将引脚连接到 PCB 布线的情况。   因此、首先、我将切断布线、使传感器不再长直接连接到 AIN0。  在该 PCB 上的输入和 VSSA_ADC 之间放置一个 500 欧姆电阻很难、但我可以在下一次迭代中这样做。

    至于时钟、在配置 ADC 时、我们得到了直接来自 TI 示例的这条线路。  基于我的理解、他们提供此功能是为了展示器件的卓越性能。

    HWREG(SOC_ADC_TSC_0_REGS + TSC_ADC_SS_ADC_CLKDIV) = 0;

    我们正在将其改为此。

    HWREG(SOC_ADC_TSC_0_REGS + TSC_ADC_SS_ADC_CLKDIV) = 7;
    

    我会让你知道它是如何进行的。

  • 请注意,本文内容源自机器翻译,可能存在语法或其它翻译错误,仅供参考。如需获取准确内容,请参阅链接中的英语原文或自行翻译。

    您好 Walter、

    我对您显示的代码不完全清楚。 例如、您共享的代码似乎适用于 1 个通道、但似乎您打算运行多个通道。 您能否确认要运行的代码?该代码是否来自 TI 示例? 如果是、请给我指向具体的链接。

    此外、关于运算放大器及其 1.8V 外部电源:由于运算放大器由单独的 1.8V  稳压器供电、因此请确保 ADC 输入绝不会超出 AM335x 数据表“所有 I/O 引脚的稳态最大电压:–0.5V 至 I/O 电源电压+ 0.3V“中的器件绝对最大限值。  此外、采用 1.8V 运算放大器电源时、运算放大器可能会在电源轨附近饱和、从而会将 ADC 输入端的可用 0 至满量程动态范围降低。

    此致、
    Karam

  • 请注意,本文内容源自机器翻译,可能存在语法或其它翻译错误,仅供参考。如需获取准确内容,请参阅链接中的英语原文或自行翻译。

     Karam Haddad 多年以来、我发现 TI 提供的示例代码、因此我必须四处探索以找到链接。   我在 TI.com 上做了一个简短的搜索,但还没有找到它。   

    我在我发布的代码中读取两个通道 — AIN0 和 AIN1、并设置两个步骤来执行此操作。  我指的是我发布的代码。 自发布以来、我们一直在向其他渠道移动一些内容。  我不在办公室、无法访问当前设置。  我们现在继续使用 AIN0 和 AIN1。

    我意识到、我发布的代码中有许多注释掉的行、这会使阅读变得困惑。  设置通道的线路是什么

    //SENSOR WITH DRIFT
    	HWREG(SOC_ADC_TSC_0_REGS + TSC_ADC_SS_STEPCONFIG(0)) = 0x00000008;
    	
    
    	//FLOW METER
    
    	HWREG(SOC_ADC_TSC_0_REGS + TSC_ADC_SS_STEPCONFIG(1)) = 0x00080008; //averages 4 samples

    运算放大器电路的电源专门设置为 1.8V、以防止 ADC 的高输入电压损坏 ADC。  来自传感器的信号最多摆动 0.00 至 1.6V、因此我们不会有读取错误的危险。   这是一个很好的事情指出。

  • 请注意,本文内容源自机器翻译,可能存在语法或其它翻译错误,仅供参考。如需获取准确内容,请参阅链接中的英语原文或自行翻译。

     Karam Haddad  我还不能在任何地方找到该示例代码。  但是,好消息是,问题已经解决,感谢你的所有帮助。  让我总结一下我们所做的工作。

    最初、 AIN0 直接连接到我们定制 PCB 上 1M Ω 电阻器和光电二极管之间的点。  幸运的是、我们还将此输入输入输入到 1.8V 电源电压的单位增益缓冲放大器中、放大器的输出用于馈入数字采集系统、以便单独监控和分析信号。

    我们最初的时钟分频值为 0 、即最大 ADC 时钟速度。

    修复:

    我们将单位增益缓冲放大器的输出连接到未使用的 AIN6。

    我们会切断进入 AIN0 的布线。

    我们更改了步进配置、因此第 0 步的读数为 AIN6、而不是 AIN0。

    我们将 ADC 时钟分频保留为 0 (24MHz)。

    结果: 没有明显的信号漂移、信号上的噪声要低得多!

    注释:

    我们尝试使用较慢的 ADC 时钟速度、但发现它不适用于我们的应用。  我们只读取两个通道、因此这个速度似乎可以正常工作、没有任何问题、但我们会留意可能由这种情况引起的问题。

    感谢:  我真诚地感谢您对解决这一问题的奉献以及您对我的耐心 、因为您正在学习(实际上是再学习)。  我们已经与这个问题挣扎了一段时间,并在寻找所有错误的地方!  这种监测的过程具有导致这种漂移的理论潜力、但我们最终知道情况并非如此。  这对了解未来也很有帮助。

    我将此标记为已解决。