繁体   English   中英

C#-Arduino串行通信在读取数据时冻结(?)

[英]C# - Arduino Serial Communication freezes(?) while reading Data

我的程序在启动时检查是否已连接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变量中的内容ardAnswer ,该程序似乎已冻结,并且不会继续执行任何操作。

我真的很想知道为什么。 我必须承认,我已经有一段时间没有接触过该程序了,但是当我最后一次使用它时,它的行为完全相同,并且代码完全相同。

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

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

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

更好的是:让Arduino代码在第一次启动时发送响应或打印某种横幅。 然后, 打开串行端口 ,让您的C#代码等待该代码,因此您知道Arduino已复位,通过引导加载程序,您的代码现在已完全启动并运行。

我得到了答案。 C#/ Visual Studio / .NET Framework /似乎不喜欢高波特率。 我将其从115200降低到9600(据我所知是标准),现在一切正常。 奇怪。

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM