我有一个程序,可以从PSoC上的ADC读取串行数据。
这些号码以<uint16>
格式发送,包括&#39;&lt;&#39;和&#39;&gt;&#39;符号,以二进制格式00111100 XXXXXXXX XXXXXXXX 00111110
传输,其中&#39; X组成16位无符号整数。
有时,阅读工作不会很好,程序会使用二进制数据进行&#39;&gt;&#39;符号作为其数字的一部分导致毛刺,如2500个样本的屏幕截图所示(忽略样本800到1500之间的下降,这是我使用ADC输入):
您可以清楚地看到毛刺导致数据每次发生时都会采样大致相同的值。
数据每秒发送十次,所以我打算做的是取十个样本,去除任何毛刺(其中值远离其他样本),然后平均剩余值以平滑曲线有点。输出可以从0到50000+,因此我不能删除低于某个数字的值。
我不确定如何删除超出10个样本组中其他值范围的值,因为可能存在两个样本受此故障影响的情况。也许还有其他一些方法可以修复这些毛病数据,而不仅仅是解决它!
这样做的最佳方式是什么?这是我到目前为止的代码(这是在DataReceivedEvent方法中):
SerialPort sp = (SerialPort)sender; //set up serial port
byte[] spBuffer = new byte[4];
int indata = 0;
sp.Read(spBuffer, 0, 4);
indata = BitConverter.ToUInt16(spBuffer, 1);
object[] o = { numSamples, nudDutyCycle.Value, freqMultiplied, nudDistance.Value, pulseWidth, indata };
lock (dt) //lock for multithread safety
{
dt.Rows.Add(o); //add data to datatable
}
答案 0 :(得分:1)
工程中的常用方法是添加阻尼功能。阻尼函数基本上作用于参数的微分,即连续值之间的差。关于如何选择阻尼函数没有严格的规则,大多数都是经过调整以产生合理的结果。
因此,在您的情况下,这意味着您将最新值与之前的值进行比较。如果它大于某个数量,则将最新值默认为前一个值,或者将最新值减少某个固定因子,例如10%或1%。这样你就不会丢失信息,但也没有突然的跳跃和故障。
答案 1 :(得分:1)
我怀疑你的问题可能是因为你从串口读取的字节数比你想象的少。
例如,sp.Read(spBuffer, 0, 4);
不一定读取4个字节。它可以读取1,2,3或4个字节(但从不为0)。
如果您知道您应该读取一定数量的字节,请尝试以下方法:
public static void BlockingRead(SerialPort port, byte[] buffer, int offset, int count)
{
while (count > 0)
{
// SerialPort.Read() blocks until at least one byte has been read, or SerialPort.ReadTimeout milliseconds
// have elapsed. If a timeout occurs a TimeoutException will be thrown.
// Because SerialPort.Read() blocks until some data is available this is not a busy loop,
// and we do NOT need to issue any calls to Thread.Sleep().
int bytesRead = port.Read(buffer, offset, count);
offset += bytesRead;
count -= bytesRead;
}
}
如果在阅读过程中出现超时,则应该有TimeoutException
,因此无需在此处设置超时。
然后改变这样的呼叫:
sp.Read(spBuffer, 0, 4);
对此:
BlockingRead(sp, spbuffer, 0, 4);
答案 2 :(得分:1)
首先,我强烈建议只修复解析问题,然后你不必担心毛刺值。
但是,如果你仍然决定继续修复数据的路线: 我看到所有的glitched数据都在某个值附近:~16000。事实上,从图表来看,我说它每次都几乎相同。您可以简单地忽略处于glitched值范围内的数据(您必须进行一些测试才能找到确切的边界),并使用最后一个非glitched值。