串行Arduino中的随机损坏数据



我在UWP C#中从Arduino Uno读取串行数据时遇到问题。有时当我启动应用程序时,我会得到损坏的数据。但在arduino显示器总是好的。损坏的数据是这样的:

57 
5

但应该是557。

Arduino代码:

String digx, digx2, digx3, digx1 ;
void setup() {
delay(500); 
Serial.begin(9600);
}
void loop() {
int sensorValue = analogRead(A1);
sensorValue = map(sensorValue, 0, 1024, 0, 999);
digx1 =  String(sensorValue % 10);
digx2 =  String((sensorValue / 10) % 10);
digx3 =  String((sensorValue / 100) % 10);
digx = (digx3 + digx2 + digx1);

Serial.println(digx);
Serial.flush();
delay(100);
}

和windows通用代码:

public sealed partial class MainPage : Page
{
public DataReader dataReader;
public SerialDevice serialPort;
private string data;
private async void InitializeConnection()
{
var aqs = SerialDevice.GetDeviceSelectorFromUsbVidPid(0x2341, 0x0043);
var info = await DeviceInformation.FindAllAsync(aqs);
serialPort = await SerialDevice.FromIdAsync(info[0].Id);
Thread.Sleep(100);
serialPort.DataBits = 8;
serialPort.BaudRate = 9600;
serialPort.Parity = SerialParity.None;
serialPort.Handshake = SerialHandshake.None;
serialPort.StopBits = SerialStopBitCount.One;
serialPort.ReadTimeout = TimeSpan.FromMilliseconds(1000);
serialPort.WriteTimeout = TimeSpan.FromMilliseconds(1000);
Thread.Sleep(100);
dataReader = new DataReader(serialPort.InputStream);
while (true)
{
await ReadAsync();
}
}
private async Task ReadAsync()
{
try
{
uint readBufferLength = 5;
dataReader.InputStreamOptions = InputStreamOptions.Partial;
//dataReader.UnicodeEncoding = UnicodeEncoding.Utf8;
var loadAsyncTask = dataReader.LoadAsync(readBufferLength).AsTask();
var ReadAsyncBytes = await loadAsyncTask;
if (ReadAsyncBytes > 0)
{
data = dataReader.ReadString(ReadAsyncBytes);
serialValue.Text = data;
}
}
catch (Exception e)
{
}
}
}

我的想法是,如果真的发生了,程序会跳过这些数据。我尝试了不同的缓冲区长度,但大于或小于5总是会收到不正确的。

谢谢你的帮助。

两种可以解决问题的方法。

方法1:使UART通信健壮

这是不可能出错的,但在windows软件与Arduino通信的情况下,这是一项棘手而耗时的任务。

但仍然有一些技巧可以帮助你,因为我已经尝试过了,其中一些有效,但请不要问为什么有效。

  1. 将UART波特率从9600更改为其他值(如果在38400时工作正常,则为我的(
  2. 将SERIAL_8N1中的Serial.begin(9600);替换为Serial.begin(38400,SERIAL_8N1),其中8是数据位,1是停止位,N是奇偶校验零。您也可以在数据位、停止位和奇偶校验中尝试不同的设置。在这里检查
  3. 在将数据转换为字符串Serial.println(digx);之后不发送数据。使用Serial.write(digx,len);以字节数组的形式发送数据。在这里检查

方法2:添加CRC数据包

在每个数据包结束后再发送。当它到达windows时,软件首先获取所有UART数据,然后根据该数据计算CRC,然后只比较计算的CRC和接收的CRC。如果CRC匹配,则数据是正确的,如果不匹配,则忽略数据并等待新数据。

您可以检查CRC计算及其直接公式库实现,并通过vinmenn检查此库。

我用了两件事来解决这个问题,

1。在Windows中,代码添加了SerialDevice.IsDataTerminalReadyEnabled = true属性以正确顺序读取字节。来自Microsoft文档这里有一个链接!

2.在dharmik的帮助下,我在Arduino中使用数组并使用Serial.write(array, arrayLength)发送它,并在Windows应用程序中使用dataReader.ReadBytes(array[])和正确的缓冲区大小读取它们。

即使延迟低得多,结果也是如此稳定。

最新更新