电平信号经电容后的补偿

使用机器声卡做虚拟示波器, 当耦合电容过小, 或信号实际为数字信号导致波形漂移

经处理后, 转换数字信号如下

电容后信号补偿

/*
v_next      c(Q)
  +----------||---+-------+ nValue
                  |
                 -+-
                 |r|
		 -+-
                  |
                 -+-
                 GND
*/
//	RC电容串联补偿
int		CapacitanceNext(int nIndex, int nValue, double c = 12.0)
{
	static		double		Q, C, k = 0.0, v_c, v_last;
	double		v_next, q_dlt, r, t, i;

	if(k == 0.0)
	{
		k = 0.2;
	}
	if(nIndex == 0)
	{
		v_c = 0.0;
		C = c;
		Q = c*v_c;			//	初始电量
		v_last = nValue;
		return nValue;
	}
	v_c = Q / C;
	v_next = (nValue + v_c + v_last)/2.0;		//	平滑
	v_last = v_next;

	r = 1.0;
	t = 1.0;
	i = nValue / r;
	q_dlt = i*t*0.001*k;
	Q += q_dlt;

	if(nIndex == 128*1024-3)
		int ddd = 0;

	return (int)v_next;
}

也尝试了卡尔曼滤波

/*
卡尔曼滤波
nCount		Q			R	
4096		0.0001		0.01
128K		0.000001	0.1
*/
int		KalmanNext(int nValue, BOOL bInit = FALSE, double k = 1.0)
{
	static		double		A, P, Q, R, K, H;
	static		int			LAST;
	double		ValE, ValS;

	if(bInit)
	{
		A = 1.0;
		H = 1.0;
		P = 2.0;
		LAST = nValue;
		Q = 0.0001 / k;				//	强度
//		R = 0.01 * sqrt(k);			//	速度
		R = 0.01;

		return nValue;
	}
	
	P = A*A*P + Q;						//	P[n|n-1]=P[n-1|n-1]+Q
	K = H*P / (H*H*P + R);				//	K[n]=H*P[n|n-1]/{H^2*P[n|n-1]+R}

	ValE = A * LAST;
	ValS = ValE + (nValue - LAST)*K;	//	x[n|n]=x[n|n-1]+K[n]*{z[n]-x[n|n-1]}
	LAST = (int)ValS;

	P = (1 - K*H) * P;					//	P[n|n]=(1-K[n]*H)*P[n|n-1]

	return LAST;
}

脉冲检测

{
		dTotal = 0;
		for(i=1; i<nCount; i++)
		{
			d1 = pThresDat1[i] - pThresDat1[i-1];
			dTotal += d1*d1;
		}
		s_ThresholdK = (int)(sqrt(dTotal) / 1400);
		s_ThresholdK = max(s_ThresholdK, 10);
		ATLTRACE("s_ThresholdK: %d\r\n", s_ThresholdK);

		nStep = (SHORT_MAX - SHORT_MIN) * s_ThresholdK / nCount;
		hOld = pThresDat[0] = pThresDat1[0];
		hOld = pThresDat[1] = pThresDat1[1];
		for(i=2; i<nCount; i++)
		{
			d1 = pThresDat1[i-1] - pThresDat1[i-2];
			d2 = pThresDat1[i-0] - pThresDat1[i-1];
			if(d1 > nStep && d2 > nStep)
			{
				pThresDat[i] = hOld + d2;
				hOld = pThresDat[i];
			}
			else if(d1 < -nStep && d2 < -nStep)
			{
				pThresDat[i] = hOld + d2;
				hOld = pThresDat[i];
			}
			else
			{
				pThresDat[i] = hOld;
			}
		}

		FindThreshold(pThresDat, nCount, wThreshold);

		if(m_bThresholdRc_Dbg)
		{
			SetDbgWave(pThresDat, nCount, 2, 1024);
			SetDbgWave(&wThreshold, 1, 3, 1024);

		}
	}

阈值计算

BOOL	FindThreshold(short *pDat, int nCount, short &hThreshold)
{
	double		dTotal, dLg, dRg, dLc, dRc;
	int			i, nAvg, nNext, nSteps;
	int			nCenter, nLq, nRq;
	int			nDirect, nOldDirct;

	dTotal = 0;
	for(i=0; i<nCount; i++)
	{
		dTotal += pDat[i];
	}
	nAvg = (int)(dTotal/nCount);

//	ATLTRACE("FindThreshold Start: %d\r\n", nAvg);
	nOldDirct = 0;
	nNext = -1;
	nSteps = 0;
	for(nCenter=nAvg; nNext!=nCenter; )
	{
		nNext = nCenter;
		dLg = 0;
		dRg = 0;
		dLc = 0;
		dRc = 0;
		for(i=0; i<nCount; i++)
		{
			if(pDat[i] >= nNext)
			{
				dRc += 1;
				dRg += pDat[i];
			}
			else
			{
				dLc += 1;
				dLg += pDat[i];
			}
		}

		nLq = (int)(dLg/(dLc+1));
		nRq = (int)(dRg/(dRc+1));
//		nCenter = (nLq+nRq+nNext)/3;
		nCenter = (nLq+nRq)/2;
		nSteps ++;

		if(nCenter == nNext)
			break;
		nDirect = nCenter > nNext ? 1 : -1;
		if(nOldDirct && nDirect != nOldDirct)
			break;
		nOldDirct = nDirect;
		ATLTRACE("FindThreshold Step: %d\r\n", nCenter);

	}

	hThreshold = nNext;
	ATLTRACE("FindThreshold End: %d, Steps:%d\r\n", hThreshold, nSteps);
	return TRUE;
}
posted @ 2022-04-10 22:05  Yofoo  阅读(117)  评论(0)    收藏  举报