串行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 通信的情况下,这是一项棘手且耗时的任务。

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

  1. 将您的 UART 波特率从 9600 更改为其他值(我的如果在 38400 下工作完美)。
  2. Serial.begin(9600);替换为Serial.begin(38400,SERIAL_8N1),其中8为数据位,1为停止位,N为SERIAL_8N1中的奇偶校验none。您还可以在数据位、停止位和奇偶校验方面尝试不同的设置。检查 here
  3. 转换成字符串后不要发送数据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应用

即使延迟低得多,结果也非常稳定。