我在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通信的情况下,这是一项棘手而耗时的任务。
但仍然有一些技巧可以帮助你,因为我已经尝试过了,其中一些有效,但请不要问为什么有效。
- 将UART波特率从9600更改为其他值(如果在38400时工作正常,则为我的(
- 将SERIAL_8N1中的
Serial.begin(9600);
替换为Serial.begin(38400,SERIAL_8N1)
,其中8是数据位,1是停止位,N是奇偶校验零。您也可以在数据位、停止位和奇偶校验中尝试不同的设置。在这里检查 - 在将数据转换为字符串
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[])
和正确的缓冲区大小读取它们。
即使延迟低得多,结果也是如此稳定。