如何使用 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
并且它起作用了。我知道这很简单!耶!
在某些情况下,我正在尝试创建自己的高扭矩伺服系统。
我创建了一个 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
并且它起作用了。我知道这很简单!耶!