串口数据精确时间戳 [英] Serial port data precise time stamp

查看:199
本文介绍了串口数据精确时间戳的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我正在从事一个项目,该项目要求我从连接到编码器(带 QSB 的美国数字 S5 光学轴编码器)的串行端口读取的每个数据条目都需要精确的时间 (ms).

I am working on a project which requires precise time(ms) for each data entry I read from a serial port connected to an encoder (US digital S5 Optical Shaft Encoder with a QSB).

我在一辆小推车上安装了编码器,我用它来计算推车的速度.

I installed the encoder on a small cart where I use it to count the speed of the cart.

这是我目前所做的:

  1. 连接到串口并向QSB写入命令以告诉编码器流式传输数据.此处可用的命令:

  1. connect to the serial port and write command to QSB to tell the encoder to stream data. commands available here:

www.usdigital.com/assets/general/QSB%20Commands%20List_1.pdfwww.usdigital.com/assets/general/QSB%20Applications%20Examples.pdf

www.usdigital.com/assets/general/QSB%20Commands%20List_1.pdf www.usdigital.com/assets/general/QSB%20Applications%20Examples.pdf

使用 readline() 读取接收到的数据.

Use readline() to read received data.

当我将输出值阈值和间隔率设置为尽可能快时,我能够在 1 毫秒内获取数据条目.这是我得到的:

I am able to get data entries in between 1ms when I set the output value threshold and interval rate to as fast as possible. Here is what I got:

----time stamp(h/m/s/ms)-------value

具有正确时间戳的数据:https://www.dropbox.com/s/pvo1dz56my4o99y/Capture1.JPG

data with correct time stamp: https://www.dropbox.com/s/pvo1dz56my4o99y/Capture1.JPG

然而,有突然的跳跃",数据连续时大约200ms(我正在以恒定速度滚动推车)

However, there are abrupt "jumps", roughly 200ms when data is continuous (I am rolling the cart in a constant speed)

时间戳不正确的数据:https://www.dropbox.com/s/sz3sxwv4qwsb2cn/Capture2.JPG

这是我的代码:

private void buttonOpenEncoderPort_Click(object sender, EventArgs e)
    {
        serialPortEncoder.Write("S0E\r\n");//start streaming data
        System.Threading.Thread.Sleep(500);
        serialPortEncoder.Write("W0B0\r\n");//set threshold to 0 so the encoder will stream data a the interval I set.
        System.Threading.Thread.Sleep(500);
        serialPortEncoder.Write("W0C0000\r\n");//set output interval to 0 so it will stream as fast as possible
        System.Threading.Thread.Sleep(1500);
        backgroundWorkerEncoder.RunWorkerAsync();}
        //I am using a background worker to pull data out.


 private void backgroundWorkerEncoder_DoWork(object sender, DoWorkEventArgs e)
    {
        while (serialPortEncoder.IsOpen)
        {
            if (serialPortEncoder.BytesToRead != 0)
            {
                try
                {
                    String s = serialPortEncoder.ReadLine();//read from encoder
                    LazerBucket.Add(getCurrentTimeWithMS(timeEncoder) + "-----" + s + "\r\n");//put one line of data with time stamp in a List<String>
                    richTextBoxEncoderData.BeginInvoke(new MethodInvoker(delegate()
                    {
                        richTextBoxEncoderData.Text = s; })); //update UI

                }
                catch (Exception ex) { MessageBox.Show(ex.ToString()); }                   
            }

        }
    }

private String getCurrentTimeWithMS(DateTime d)//to get time
    {
        StringBuilder s = new StringBuilder();
        d = DateTime.Now;
        int hour = d.Hour;
        int minute = d.Minute;
        int second = d.Second;
        int ms = d.Millisecond;
        s.Append("  ----" + hour.ToString() + ":" + minute.ToString() + ":" + second.ToString() + ":" + ms.ToString());
        return s.ToString();
    }

如果有人能找到时间跳跃的原因,我会很高兴.200 毫秒太多了,不容忽视.

I would appericiate it if someone could find the cause of the time jump. 200ms is too much to be ignored.

EDIT: 

按照建议,我尝试了 Stopwatch 但仍然有 200 毫秒的延迟.但是当我一起打印时间戳和 BytesToRead 时,我发现缓冲区中的数据随着 readLine() 的执行而减少.最终 BytesToRead 将下降到个位数,这就是延迟发生的地方.我正在寻找关于如何实现线程的更好的解决方案.还有延迟的解释.也许我读得太快了,所以缓冲区跟不上我?

As suggested, I tried Stopwatch but still there are 200ms delay. But when I print out time stamps and BytesToRead together, I found that data in the buffer is decreasing as readLine() is being executed. Eventually BytesToRead will drop to single digit and that's where the delay happens. I am looking for better solutions on how to implement threads. And also explanations for the delay. Maybe I am reading to fast so the buffer can't keep up with me?

EDIT:

问题解决了.请参阅下面的我的答案.谢谢你的回复.秒表真的很有帮助.现在我正在尝试确定事件驱动或轮询哪个更好.

problem solved. see my answer below. Thanks for replying though. Stopwatch really helps. Now I am trying to work out whether event driven or polling is better.

推荐答案

您使用的是 C# 4.5 吗?如果是这样,我强烈建议使用 async/await 而不是 BackgroundWorker.

Are you using C# 4.5? If so, I highly recommend using async/await over BackgroundWorker.

此外,DateTime 对于实时应用程序来说并不准确.我会严格推荐 DateTime 作为 开始时间,然后在 System.Diagnostics 中使用 Stopwatch 来获取 开始时间以来的时间.

Also, DateTime isn't really accurate for real-time applications. I would recommend DateTime strictly as a start time and then using Stopwatch in System.Diagnostics to get the elapsed time since the start time.

private void backgroundWorkerEncoder_DoWork(object sender, DoWorkEventArgs e)
{
  var startTime = DateTime.Now;
  var stopwatch = Stopwatch.StartNew();

  while (serialPort.IsOpen && !backgroundWorker.CancellationPending)
  {
    if (serialPort.BytesToRead > 0)
    {
      try
      {
        var line = serialPort.ReadLine();
        var timestamp = (startTime + stopwatch.Elapsed);

        var lineString = string.Format("{0}  ----{1}", 
                                       line,
                                       timestamp.ToString("HH:mm:ss:fff"));

        // Handle formatted line string here.
      }
      catch (Exception ex)
      {
        // Handle exception here.
      }
    }
  }

至于 200 毫秒 的差异,可能是多种原因.也许 BackgroundWorker 的优先级较低,并且没有您希望的那么多 CPU 时间.也可能是 SerialPort 或实际串行设备本身的 I/O 端.

As for the 200 ms discrepancy, it could be a variety of things. Perhaps the BackgroundWorker is on a lower priority and doesn't get as much CPU time as you hoped. Could also be something on the I/O side of either SerialPort or the actual serial device itself.

这篇关于串口数据精确时间戳的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆