2017-08-27 28 views
0

我的程序在啓動時檢查Arduino是否連接,如果是這種情況,它會通過串行端口發送測試消息來查看它是否正確響應。然後等待結果,如果答案是「成功」,它會繼續啓動。C# - 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");時,該程序似乎凍結並且不會繼續執行任何操作。

我真的想知道爲什麼。我不得不承認,我已經有一段時間沒有觸及這個程序,但是當我上次研究這個程序時,它完全按照它的行爲,使用完全相同的代碼。

+0

您的SerialPort初始化代碼不足。您還必須設置奇偶校驗,數據位,停止位(無,8,1)。而重要的一個,因爲Arduino沒有實現握手信號,Handshake必須是None。不設置它會產生一個隨機值,這取決於以前使用的端口。 ARE是有風險的,但只要Arduino只有在你要求的時候才發送一些東西,那麼你就會擺脫它。根本不使用DataReceived更合理。 –

+0

更改了我的代碼,謝謝。遺憾的是沒有幫助主要問題。 – TheEpicSnowWolf

回答

0

我得到了答案。 C#/ Visual Studio/.NET Framework /什麼似乎不喜歡高波特率。我把它從115200降到9600(據我所知標準),現在一切正常。奇怪。

0

你很可能有競爭條件:當你打開串口(在大多數系統上)時,DTR/RTS串口信號的改變會重置Arduino。這反過來會導致引導加載程序運行,等待一段時間,看看是否有任何代碼要加載。如果沒有,它會進入你的程序。

我的猜測是:當引導加載程序在等待時發送測試命令,導致部分或全部命令丟失。

嘗試:在打開端口併發送命令之前添加延遲(幾秒鐘後啓動)。

更好:你的Arduino代碼在第一次啓動時發送響應或打印某種標語。然後,在打開串口之後,讓你的C#代碼等待,這樣你就知道Arduino已經復位,通過了bootloader,現在你的代碼已經完全啓動並運行了。

+0

不幸的是,這並沒有解決它。引導加載程序似乎無法在打開串行端口時運行,因爲我看不到Arduino LED閃爍,它們通常在啓動時執行(?) – TheEpicSnowWolf

+0

如果更改Arduino程序以在串行端口上打印橫幅在啓動時,您是否在Arduino IDE中打開串行監視器時看到了這條橫幅? – payne

+0

是的,我喜歡。但正如我所說的,當串行端口被C#程序打開時,似乎Arduino不會重新啓動。打開端口可能有問題,畢竟這是問題所在?奇怪的是,沒有錯誤信息,然而...... – TheEpicSnowWolf