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

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

电容后信号补偿
/*
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;
}

浙公网安备 33010602011771号