C# - Arduino串行通信在读取数据

时间:2017-08-27 15:30:11

标签: c# arduino serial-port

如果连接了Arduino,我的程序会在启动时检查,如果是这样,它会通过串行端口发送测试消息,看它是否正确响应。然后它等待结果,如果答案是"成功",它会继续启动。

以下是代码的重要部分:

...
using System.IO.Ports;
using System.Threading;

namespace ProFlagControlApp
{
    public partial class MainWindow : Window
    {
        static AutoResetEvent autoEvent = new AutoResetEvent(false);

        ...
        private SerialPort arduinoBoard = new SerialPort();
        private string ardAnswer;

        /// <summary>
        /// Automatically detect the COM port on which an Arduino is connected.
        /// </summary>
        /// <returns>If an Aduino is connected, the port is returned as a string. If not, it returns null.</returns>
        private string AutodetectArduinoPort() { ... }

        /// <summary>
        /// Initializing communications with the Arduino.
        /// </summary>
        /// <param name="port">The identifier of the port the Arduino is connected to. Example: 'COM4'</param>
        private void OpenArduinoConnection(string port)
        {
            if (!arduinoBoard.IsOpen)
            {
            arduinoBoard.DataReceived += new SerialDataReceivedEventHandler(ArdSerPort_DataReceived);
            arduinoBoard.BaudRate = 115200;
            arduinoBoard.PortName = port;
            arduinoBoard.Parity = Parity.None;
            arduinoBoard.DataBits = 8;
            arduinoBoard.StopBits = StopBits.One;
            arduinoBoard.Handshake = Handshake.None;

            arduinoBoard.Open();
            }
            else
            {
                throw new InvalidOperationException("port is already in use");
            }
        }

        /// <summary>
        /// The event handler for receiving data from the Arduino.
        /// </summary>
        private void ArdSerPort_DataReceived(object sender, SerialDataReceivedEventArgs e)
        {
            string data = arduinoBoard.ReadTo("\x03"); // Read Arduino data until exit code
            ardAnswer = data.Split('\x02', '\x03')[1]; // Only save information between the start and exit code
            autoEvent.Set();
        }

        public MainWindow()
        {
            InitializeComponent();

            ...

            // Detect if Arduino is connected, shutdown the application otherwise.
            if (AutodetectArduinoPort() == null) { ... }

            OpenArduinoConnection(AutodetectArduinoPort());

            // Test Arduino communication
            arduinoBoard.Write("connection#");

            autoEvent.WaitOne(500);
            if (ardAnswer != "success")
            {
                MessageBox.Show("Error communicating with Arduino", "Control Unit Error", MessageBoxButton.OK, MessageBoxImage.Warning);
                Application.Current.Shutdown();
                return;
            }

            ...
        }

        ...
    }
}

我通过Arduino串行监视器检查是否正确读取了命令并且相应的响应消息被写入串行端口,就是这种情况。

但是,永远不会触发ArdSerPort_DataReceived事件。当我在测试ardAnswer = arduinoBoard.ReadTo("\x03");变量中的内容之前尝试手动放置ardAnswer时,该程序似乎冻结并且不会继续任何内容。

我真的很想知道为什么。我不得不承认,我现在已经有很长一段时间没有碰过这个程序了,但是当我上次工作时,它的表现都应该如此,完全相同的代码。

2 个答案:

答案 0 :(得分:0)

您很可能遇到竞争条件:当您打开串行端口(在大多数系统上)时,DTR / RTS串口信号的变化将重置Arduino。反过来,这将导致引导加载程序运行,等待一小段时间,看看是否有任何代码要加载。如果没有,它会进入你的程序。

我的猜测:您在引导加载程序等待时发送测试命令,导致部分或全部命令丢失。

尝试:在打开端口之后和发送命令之前添加延迟(启动几秒钟)。

更好:让Arduino代码在首次启动时发送响应或打印某种类型的横幅。然后,让你的C#代码在打开串口后等待,这样你就知道Arduino已经重置,通过引导加载程序,你的代码现在已经完全启动并运行。

答案 1 :(得分:0)

我得到了答案。 C#/ Visual Studio / .NET Framework /无论如何似乎都不喜欢高波特率。我把它从115200调低到9600(就我所知的标准而言),现在一切正常。奇怪。