如何预防;“数据延迟”;在串行通信中(C#form<;->;Arduino)

如何预防;“数据延迟”;在串行通信中(C#form<;->;Arduino),c#,forms,arduino,serial-port,C#,Forms,Arduino,Serial Port,我的代码可以工作,但我想确保它的健壮性,因为我记得在过去(用python)编写过类似的代码,并注意到我接收到的数据将是3或4分钟前的数据,并且随着时间的推移会变得更老。 我想这与串行缓冲区有关,我应该不时地“清除它”,这方面的最佳实践是什么 C#表格代码: using System; using System.Windows.Forms; using System.IO.Ports; namespace SerialTest1 { public partial class Form1

我的代码可以工作,但我想确保它的健壮性,因为我记得在过去(用python)编写过类似的代码,并注意到我接收到的数据将是3或4分钟前的数据,并且随着时间的推移会变得更老。 我想这与串行缓冲区有关,我应该不时地“清除它”,这方面的最佳实践是什么

C#表格代码:

using System;
using System.Windows.Forms;
using System.IO.Ports;

namespace SerialTest1
{
    public partial class Form1 : Form
    {
        public SerialPort ArduinoSerial;

        public Form1()
        {
            InitializeComponent();
        }

        private void Form1_Load(object sender, EventArgs e)
        {
            Timer MyTimer = new Timer();
            MyTimer.Interval = (1000); // 1 sec
            MyTimer.Tick += new EventHandler(SerialTimer_Tick);
            MyTimer.Start();
            Console.WriteLine("Form1_Loading....");
            OpenSerialPort();
        }
        private void OpenSerialPort() // creating serial communication object
        {
            try
            {
                Console.WriteLine("OpenSerialPort: opening port.....");
                ArduinoSerial = new SerialPort("COM7", 115200);//Set board COM
                ArduinoSerial.Open();
                ArduinoSerial.DataReceived += new SerialDataReceivedEventHandler(dataReceived);
            }
            catch (Exception ex)
            {
                Console.WriteLine("OpenSerialPort: Can not find port");
            }
        }

        // write to arduino and restart Serial com if error like cable disconnected and reconnected
        private void writeToArduino() 
        {
            try
            {
                Console.WriteLine($"writeToArduino: writing msg to arduino");
                ArduinoSerial.WriteLine("hello from pc");
            }
            catch (Exception ex)
            {
                Console.WriteLine("writeToArduino: Serial Error");
                //MessageBox.Show("Serial Error: " + ex.ToString(), "ERROR");
                if (!ArduinoSerial.IsOpen)
                {
                    Console.WriteLine("writeToArduino: ArduinoSerial is close, opening it...");
                    OpenSerialPort();
                }
            }
        }

        private void SerialTimer_Tick(object sender, EventArgs e) // will write to arduino at each timer tick
        {
            writeToArduino();
        }

        private void dataReceived(object sender, SerialDataReceivedEventArgs e) // receiving datas from arduino
        {
            string SerialLine = ArduinoSerial.ReadLine();
            Console.WriteLine($"dataReceived: Got serial line for arduino: {SerialLine}");
        }
    }
}
Arduino代码:

#include <TimeLib.h>
#include <Time.h>

//WINDOWS COMMUNICATION
String receivedString;

void setup(void) {
    Serial.begin(115200);
}

void loop(void) {
    static time_t lastMsg = 0;
    static int counter = 1;
    if (now() - lastMsg > 1) {
        lastMsg = now();
        Serial.print("msg ");
        Serial.print(counter);
        Serial.println("Hello from arduino");
        counter++;
    }
    while (Serial.available() > 0) {
        receivedString = Serial.readString();
        Serial.println(receivedString);
    }
    delay(5);
}
#包括
#包括
//WINDOWS通信
字符串接收字符串;
作废设置(作废){
序列号开始(115200);
}
无效循环(无效){
静态时间\u t lastMsg=0;
静态整数计数器=1;
如果(现在()-lastMsg>1){
lastMsg=now();
串行打印(“msg”);
串行打印(计数器);
Serial.println(“来自arduino的你好”);
计数器++;
}
while(Serial.available()>0){
receivedString=Serial.readString();
Serial.println(receivedString);
}
延误(5);
}

考虑到您所有的邮件都是相同的,您如何知道它们是旧的?此外,如果您打算使用如此高的波特率,特别是全双工,您应该使用某种形式的流量控制,最好是DTR+DSR+RTS+CTS。您当前的代码是否遇到问题?或者你只是担心过去用完全不同的代码发生的事情可能会再次发生。。。调用
SerialTimer\u Tick
函数的频率是多少?如果您以最大速度(没有任何延迟)连续地从计算机发送数据,您无法期望Arduino能够跟上进度。我认为,如果您的计时对双方都有意义(发送并等待一段合理的时间,等待回答),那么您不应该在该波特率下需要任何类型的流量控制。我认为您正在超时,因为串行端口配置不正确。确保在c#和Arduino(硬件和软件)上都关闭了握手功能,并将端口设置为8位无奇偶校验。@MickyD:消息并不完全相同,因为Arduino会在每条消息中发送一个计数器值。我的波特率是任意的,我不知道DTR+DSR+RTS+CTS是什么,所以我要研究一下,谢谢@Marcos G:我的代码确实运行得很好,但我担心它的某些部分是否可以改进或是最佳实践,我的计时器每秒都在滴答作响。干杯。@jdweng:我不知道如何设置端口奇偶校验或将其定义设置为8位,所以我会研究它,谢谢。我更喜欢使用
ReadExisting
而不是
ReadLine
,因为
ReadLine
会阻塞线程,直到它收到新行字符
ReadExisting
以字符串形式返回SerialPort对象的流和内部缓冲区的内容。此方法不使用超时。这样你的线程就不会被阻塞,你就可以立即获得缓冲区中的所有数据。但是,如果使用此方法,则必须构建自己的字符串,直到看到新行字符为止。