如何预防;“数据延迟”;在串行通信中(C#form<;->;Arduino)
我的代码可以工作,但我想确保它的健壮性,因为我记得在过去(用python)编写过类似的代码,并注意到我接收到的数据将是3或4分钟前的数据,并且随着时间的推移会变得更老。 我想这与串行缓冲区有关,我应该不时地“清除它”,这方面的最佳实践是什么 C#表格代码:如何预防;“数据延迟”;在串行通信中(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
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对象的流和内部缓冲区的内容。此方法不使用超时。这样你的线程就不会被阻塞,你就可以立即获得缓冲区中的所有数据。但是,如果使用此方法,则必须构建自己的字符串,直到看到新行字符为止。