串行Arduino中的随机损坏数据
random corrupted data in serial Arduino
我在 UWP C# 中从 Arduino Uno 读取串行数据时遇到问题。有时,当我启动应用程序时,我会收到损坏的数据。
但是在arduino monitor中总是很好。
损坏的数据是这样的:
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.begin(9600);
替换为Serial.begin(38400,SERIAL_8N1)
,其中8为数据位,1为停止位,N为SERIAL_8N1中的奇偶校验none。您还可以在数据位、停止位和奇偶校验方面尝试不同的设置。检查 here
- 转换成字符串后不要发送数据
Serial.println(digx);
。使用 Serial.write(digx,len);
以字节数组的形式发送数据。检查 here
方法二:添加CRC包
在每个数据包结束后再发送。当它到达 windows 软件时,首先获取所有 UART 数据,然后从该数据计算 CRC,然后比较计算的 CRC 和接收到的 CRC.If CRC 匹配,然后数据正确,如果不正确则忽略数据并等待新数据。
您可以检查其直接公式基础工具的 CRC 计算,如果要抢先一步,请检查此 library by vinmenn.
我用了两个东西来解决这个问题,
1. 在 Windows 代码中添加 SerialDevice.IsDataTerminalReadyEnabled = true
属性 以正确顺序读取字节。来自微软文档
这里是 a link!
2. 在 dharmik 的帮助下,我使用数组并在 Arduino 中使用 Serial.write(array, arrayLength)
发送它,并使用 dataReader.ReadBytes(array[])
读取它们,并在 Windows应用
即使延迟低得多,结果也非常稳定。
我在 UWP C# 中从 Arduino Uno 读取串行数据时遇到问题。有时,当我启动应用程序时,我会收到损坏的数据。 但是在arduino monitor中总是很好。 损坏的数据是这样的:
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.begin(9600);
替换为Serial.begin(38400,SERIAL_8N1)
,其中8为数据位,1为停止位,N为SERIAL_8N1中的奇偶校验none。您还可以在数据位、停止位和奇偶校验方面尝试不同的设置。检查 here - 转换成字符串后不要发送数据
Serial.println(digx);
。使用Serial.write(digx,len);
以字节数组的形式发送数据。检查 here
方法二:添加CRC包
在每个数据包结束后再发送。当它到达 windows 软件时,首先获取所有 UART 数据,然后从该数据计算 CRC,然后比较计算的 CRC 和接收到的 CRC.If CRC 匹配,然后数据正确,如果不正确则忽略数据并等待新数据。
您可以检查其直接公式基础工具的 CRC 计算,如果要抢先一步,请检查此 library by vinmenn.
我用了两个东西来解决这个问题,
1. 在 Windows 代码中添加 SerialDevice.IsDataTerminalReadyEnabled = true
属性 以正确顺序读取字节。来自微软文档
这里是 a link!
2. 在 dharmik 的帮助下,我使用数组并在 Arduino 中使用 Serial.write(array, arrayLength)
发送它,并使用 dataReader.ReadBytes(array[])
读取它们,并在 Windows应用
即使延迟低得多,结果也非常稳定。