简体   繁体   中英

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

My program checks on startup if an Arduino is connected, and if that's the case, it sends a test message via Serial Port to see if it responds correctly. It then waits for the result, and if the answer is "success", it continues starting up.

Here's the important part of the code:

...
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;
            }

            ...
        }

        ...
    }
}

I checked via the Arduino Serial Monitor if the command is read correctly and the appropriate response message is written into the Serial Port, which is the case.

However, the ArdSerPort_DataReceived event is never triggered. When I try to manually put a ardAnswer = arduinoBoard.ReadTo("\\x03"); before it tests what is in the ardAnswer variable, the program seems to freeze and does not continue with anything.

I am really wondering why. I have to admit that I haven't touched this program for quite a while now, but when I last worked on it, it all behaved as it should, with the exact same code.

You most likely have a race condition: when you open the serial port (on most systems), the change in the DTR/RTS serial port signals will reset the Arduino. That, in turn, will cause the bootloader to run, wait for a short period to see if there's any code to load. If not, it drops into your program.

My guess: you are sending your test command while the bootloader is waiting, causing some or all of your command to get lost.

Try: adding a delay (few seconds to start) after you open the port and before you send your command.

Even better: have your Arduino code send a response or print a banner of some sort when it first starts. Then, have your C# code wait for that after opening the serial port, so you know that the Arduino has reset, gone through the bootloader, and your code is now fully up and running.

I got the answer. C# / Visual Studio / .NET Framework / Whatsoever doesn't seem to like high baud rates. I turned it down from 115200 to 9600 (standard as far as I know), and now everything works as it should. Strange.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

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