首页 文章

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

提问于
浏览
0

如果连接了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 变量中的内容之前手动放置 ardAnswer = arduinoBoard.ReadTo("\x03"); 时,程序似乎冻结并且不会继续任何操作 .

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

2 回答

  • 0

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

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

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

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

  • 0

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

相关问题