如何使用 C# 从 Arduino 接收串行数据包?

How do I receive serial packet from Arduino using C#?

在某些情况下,我正在尝试创建自己的高扭矩伺服系统。

我创建了一个 Arduino 草图,它使用 2 个中断引脚跟踪 2 相旋转编码器的位置。它还使用 2 个额外的中断引脚跟踪 2 个限位开关的状态。

一切正常,我可以在 Arduino 串行监视器中看到返回的数据(我正在使用 VSCode 实际编写代码,但它与 Arduino IDE 的工作原理相同关于串行监视器。)

但是,我在编写面向 Windows x64 的 C# 控制台应用程序来接收我在 Arduino sketch 中创建的串行数据包时遇到了问题。

我设置了断点并添加了 Console.WriteLines,但它们从未被击中。我在网上进行了大量搜索并尝试了几个不同的代码示例,但都无济于事。感觉就像我做的一切都是正确的。我过去使用 .Net 框架进行了大量的串行编程,所以我了解串行协议和使用 SerialPort class。不过,那是很久以前(几年)了。

这是我的 C# 控制台应用程序代码:

using System;
using System.IO.Ports;

namespace ArduinoSerialTest
{
  class Program
  {

    public const byte PacketStart = 1;
    public const byte PacketEnd = 4;
    public const byte PacketSize = 5;

    static void Main(string[] args)
    {

      bool isStopping = false;

      SerialPort serialPort = new SerialPort();
      serialPort.PortName = "COM3";
      serialPort.BaudRate = 9600;
      serialPort.ReadTimeout = 500;

      serialPort.Open();

      try
      {
        while (!isStopping)
        {
          try
          {
            int startByte = serialPort.ReadByte();
            if (startByte == PacketStart)
            {
              byte[] positionState = new byte[] { (byte)serialPort.ReadByte(), (byte)serialPort.ReadByte() };
              byte limitSwitchState = (byte)serialPort.ReadByte();
              byte packetEnd = (byte)serialPort.ReadByte();

              // simple verification before we process the data
              if (packetEnd != PacketEnd)
              {
                throw new Exception("Invalid packet received.");
              }

              short position = BitConverter.ToInt16(positionState, 0);

              Console.WriteLine("Position: {0}", position); // TODO: Remove me
            }
          }
          catch (TimeoutException) { }
          catch (System.IO.IOException) { }
        }

      }
      finally
      {
        serialPort.Close();
      }

    }

  }
}

这是我的 Arduino 草图的适用部分:

void reportStatus() {
    Serial.write((byte)1); // SOH
    // position split into 2 bytes
    Serial.write((byte)lowByte(encoderAccumulator));
    Serial.write((byte)highByte(encoderAccumulator));
    // limit switches
    Serial.write((byte)limitSwitchState);
    Serial.write((byte)4); // EOT
}

它似乎从来没有收到过数据包;或任何与此有关的东西。我觉得有一些明显的东西我忽略了,但我不能把手指放在上面。

至于 try/catch,我在 VSCode 的调试器输出控制台中看到超时异常。我有时也会看到 IOException,但只有在我使用 Ctrl+C 强行停止应用程序时才会出现。我在没有 IOException 捕获的情况下尝试过,但也没有显示任何内容。

试试 SerialPort.ReadExisiting()。

我知道出了什么问题。 Arduino 正在使用 DTR 信号启动通信。我所要做的就是在打开串行端口之前设置 SerialPort.DtrEnable = true 并且它起作用了。我知道这很简单!耶!