我使用一個Arduino與Firmata庫通訊C#應用程序,和我想要消除的COM端口配置組件,因爲它可以從機改爲機...如何自動檢測Arduino COM端口?
是否有可能:
- 枚舉系統中的COM端口列表? (在我的谷歌搜索中,我已經看到一些相當醜陋的Win32 API代碼,希望現在可能有更清潔的版本)
- 自動檢測哪個COM端口連接到Arduino?
我使用一個Arduino與Firmata庫通訊C#應用程序,和我想要消除的COM端口配置組件,因爲它可以從機改爲機...如何自動檢測Arduino COM端口?
是否有可能:
這個代碼一點已經表現非常出色,這(返回COM口弦,即「COM12」如果檢測到的Arduino):
private string AutodetectArduinoPort()
{
ManagementScope connectionScope = new ManagementScope();
SelectQuery serialQuery = new SelectQuery("SELECT * FROM Win32_SerialPort");
ManagementObjectSearcher searcher = new ManagementObjectSearcher(connectionScope, serialQuery);
try
{
foreach (ManagementObject item in searcher.Get())
{
string desc = item["Description"].ToString();
string deviceId = item["DeviceID"].ToString();
if (desc.Contains("Arduino"))
{
return deviceId;
}
}
}
catch (ManagementException e)
{
/* Do Nothing */
}
return null;
}
我很好開放的端口和發送命令/監聽響應......只是不知道是否有一個最佳實踐「p ing「一個Arduino會迴應..並且還發現該端口是否已被其他東西使用,等等。 – Brandon 2010-07-20 20:13:06
This(http://stackoverflow.com/questions/195483/c-check-if-a- com-serial-port-is-already-open)發佈有關查找端口是否正在使用的討論。基本上你需要嘗試打開它們。如果你得到一個異常,那麼它可能正在使用。如果打開正常,您可以檢查IsOpen屬性以驗證其連接。我會從Arduino開發板發現最小的消息或修訂響應消息,以確認您實際連接到了電路板而不是其他設備。 – SwDevMan81 2010-07-20 20:21:45
試試這個,我工作的一個非常類似的項目,任何人都可以隨時編輯這個!
在Arduino代碼的設置部分,我調用了setupComms()方法,這個方法只是打印一個「A」直到它接收到一個「a」。一旦收到「a」,它將跳轉到主循環()函數。因此,C#部分檢查每個可用端口的「A」,如果發現「A」,我們知道我們已經打開了Arduino的端口!
再次,這可能不是很乾淨,但它確實工作,我歡迎任何意見和建議!
foreach (string s in SerialPort.GetPortNames())
{
com.Close(); // To handle the exception, in case the port isn't found and then they try again...
bool portfound = false;
com.PortName = s;
com.BaudRate = 38400;
try
{
com.Open();
status.Clear();
status.Text += "Trying port: " + s+"\r";
}
catch (IOException c)
{
status.Clear();
status.Text += "Invalid Port"+"\r";
return;
}
catch (InvalidOperationException c1)
{
status.Clear();
status.Text += "Invalid Port" + "\r";
return;
}
catch (ArgumentNullException c2)
{
// System.Windows.Forms.MessageBox.Show("Sorry, Exception Occured - " + c2);
status.Clear();
status.Text += "Invalid Port" + "\r";
return;
}
catch (TimeoutException c3)
{
// System.Windows.Forms.MessageBox.Show("Sorry, Exception Occured - " + c3);
status.Clear();
status.Text += "Invalid Port" + "\r";
return;
}
catch (UnauthorizedAccessException c4)
{
//System.Windows.Forms.MessageBox.Show("Sorry, Exception Occured - " + c);
status.Clear();
status.Text += "Invalid Port" + "\r";
return;
}
catch (ArgumentOutOfRangeException c5)
{
//System.Windows.Forms.MessageBox.Show("Sorry, Exception Occured - " + c5);
status.Clear();
status.Text += "Invalid Port" + "\r";
return;
}
catch (ArgumentException c2)
{
//System.Windows.Forms.MessageBox.Show("Sorry, Exception Occured - " + c2);
status.Clear();
status.Text += "Invalid Port" + "\r";
return;
}
if (!portfound)
{
if (com.IsOpen) // Port has been opened properly...
{
com.ReadTimeout = 500; // 500 millisecond timeout...
sent.Text += "Attemption to open port " + com.PortName + "\r";
try
{
sent.Text += "Waiting for a response from controller: " + com.PortName + "\r";
string comms = com.ReadLine();
sent.Text += "Reading From Port " + com.PortName+"\r";
if (comms.Substring(0,1) == "A") // We have found the arduino!
{
status.Clear();
status.Text += s + com.PortName+" Opened Successfully!" + "\r";
//com.Write("a"); // Sends 0x74 to the arduino letting it know that we are connected!
com.ReadTimeout = 200;
com.Write("a");
sent.Text += "Port " + com.PortName + " Opened Successfully!"+"\r";
brbox.Text += com.BaudRate;
comboBox1.Text = com.PortName;
}
else
{
sent.Text += "Port Not Found! Please cycle controller power and try again" + "\r";
com.Close();
}
}
catch (Exception e1)
{
status.Clear();
status.Text += "Incorrect Port! Trying again...";
com.Close();
}
}
}
}
所有的Try Catch語句都在我最初測試的時候出現,這對我來說迄今爲止都有效。祝你好運!
把WMI管理路線做得更遠一點,我想出了一個包裝類,它掛接到Win32_SerialPorts事件並動態填充Arduino和Digi International(X-Bee)設備的SerialPorts列表, PortNames和BaudRates。
現在,我已經使用Win32_SerialPorts條目中的設備描述字段作爲字典的關鍵字,但這可以很容易地更改。
它已經通過Arduino UNO進行了有限容量的測試,看起來很穩定。
// -------------------------------------------------------------------------
// <copyright file="ArduinoDeviceManager.cs" company="ApacheTech Consultancy">
// Copyright (c) ApacheTech Consultancy. All rights reserved.
// </copyright>
// <license type="GNU General Public License" version="3">
// This program is free software: you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// the Free Software Foundation, either version 3 of the License, or
// (at your option) any later version.
//
// This program is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License for more details.
//
// You should have received a copy of the GNU General Public License
// along with this program. If not, see http://www.gnu.org/licenses
// <license>
// -------------------------------------------------------------------------
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Diagnostics;
using System.IO.Ports;
using System.Linq;
using System.Management;
using System.Runtime.CompilerServices;
// Automatically imported by Jetbeans Resharper
using ArduinoLibrary.Annotations;
namespace ArduinoLibrary
{
/// <summary>
/// Provides automated detection and initiation of Arduino devices. This class cannot be inherited.
/// </summary>
public sealed class ArduinoDeviceManager : IDisposable, INotifyPropertyChanged
{
/// <summary>
/// A System Watcher to hook events from the WMI tree.
/// </summary>
private readonly ManagementEventWatcher _deviceWatcher = new ManagementEventWatcher(new WqlEventQuery(
"SELECT * FROM Win32_DeviceChangeEvent WHERE EventType = 2 OR EventType = 3"));
/// <summary>
/// A list of all dynamically found SerialPorts.
/// </summary>
private Dictionary<string, SerialPort> _serialPorts = new Dictionary<string, SerialPort>();
/// <summary>
/// Initialises a new instance of the <see cref="ArduinoDeviceManager"/> class.
/// </summary>
public ArduinoDeviceManager()
{
// Attach an event listener to the device watcher.
_deviceWatcher.EventArrived += _deviceWatcher_EventArrived;
// Start monitoring the WMI tree for changes in SerialPort devices.
_deviceWatcher.Start();
// Initially populate the devices list.
DiscoverArduinoDevices();
}
/// <summary>
/// Gets a list of all dynamically found SerialPorts.
/// </summary>
/// <value>A list of all dynamically found SerialPorts.</value>
public Dictionary<string, SerialPort> SerialPorts
{
get { return _serialPorts; }
private set
{
_serialPorts = value;
OnPropertyChanged();
}
}
/// <summary>
/// Performs application-defined tasks associated with freeing, releasing, or resetting unmanaged resources.
/// </summary>
public void Dispose()
{
// Stop the WMI monitors when this instance is disposed.
_deviceWatcher.Stop();
}
/// <summary>
/// Occurs when a property value changes.
/// </summary>
public event PropertyChangedEventHandler PropertyChanged;
/// <summary>
/// Handles the EventArrived event of the _deviceWatcher control.
/// </summary>
/// <param name="sender">The source of the event.</param>
/// <param name="e">The <see cref="EventArrivedEventArgs"/> instance containing the event data.</param>
private void _deviceWatcher_EventArrived(object sender, EventArrivedEventArgs e)
{
DiscoverArduinoDevices();
}
/// <summary>
/// Dynamically populates the SerialPorts property with relevant devices discovered from the WMI Win32_SerialPorts class.
/// </summary>
private void DiscoverArduinoDevices()
{
// Create a temporary dictionary to superimpose onto the SerialPorts property.
var dict = new Dictionary<string, SerialPort>();
try
{
// Scan through each SerialPort registered in the WMI.
foreach (ManagementObject device in
new ManagementObjectSearcher("root\\CIMV2", "SELECT * FROM Win32_SerialPort").Get())
{
// Ignore all devices that do not have a relevant VendorID.
if (!device["PNPDeviceID"].ToString().Contains("VID_2341") && // Arduino
!device["PNPDeviceID"].ToString().Contains("VID_04d0")) return; // Digi International (X-Bee)
// Create a SerialPort to add to the collection.
var port = new SerialPort();
// Gather related configuration details for the Arduino Device.
var config = device.GetRelated("Win32_SerialPortConfiguration")
.Cast<ManagementObject>().ToList().FirstOrDefault();
// Set the SerialPort's PortName property.
port.PortName = device["DeviceID"].ToString();
// Set the SerialPort's BaudRate property. Use the devices maximum BaudRate as a fallback.
port.BaudRate = (config != null)
? int.Parse(config["BaudRate"].ToString())
: int.Parse(device["MaxBaudRate"].ToString());
// Add the SerialPort to the dictionary. Key = Arduino device description.
dict.Add(device["Description"].ToString(), port);
}
// Return the dictionary.
SerialPorts = dict;
}
catch (ManagementException mex)
{
// Send a message to debug.
Debug.WriteLine(@"An error occurred while querying for WMI data: " + mex.Message);
}
}
/// <summary>
/// Called when a property is set.
/// </summary>
/// <param name="propertyName">Name of the property.</param>
[NotifyPropertyChangedInvocator]
private void OnPropertyChanged([CallerMemberName] string propertyName = null)
{
var handler = PropertyChanged;
if (handler != null) handler(this, new PropertyChangedEventArgs(propertyName));
}
}
}
我發現我的Arduino納米的中國克隆在設備管理器中顯示正確的COM端口,但它並沒有在C#應用程序村落下拉列表中顯示,當你使用這個嘗試,並得到所有端口命令:
using (var searcher = new ManagementObjectSearcher("SELECT * FROM WIN32_SerialPort"));
但是,在執行時,它被正確地示出:
foreach (string z in SerialPort.GetPortNames())
所以,我有2所列出:一個具有第一碼輸出,以及一個從第二代碼輸出。比較兩者時,它會找到正確的COM端口。顯然,當使用原始Andurino Uno時,兩個命令都能正確顯示端口,所以這個解決方案只適用於中國克隆,由於某種奇怪的原因,這些克隆不可見using (var searcher = new ManagementObjectSearcher("SELECT * FROM WIN32_SerialPort"));
這種方法並不能幫助您找出arduino連接的端口到您的計算機
SerialPort.GetPortNames方法()
// Get a list of serial port names.
string[] ports = SerialPort.GetPortNames();
Console.WriteLine("The following serial ports were found:");
Console.WriteLine("Aşşağıda Seri Bağlantı Noktaları Bulundu:");//For Turkish
// Display each port name to the console.
foreach(string port in ports)
{
Console.WriteLine(port);
}
Console.ReadLine();
你可以給你的答案添加一個簡短的解釋嗎? – 2017-05-15 19:05:13
okey我很抱歉 – 2017-05-21 19:23:17
我試過這段代碼,它似乎沒有在我的機器上找到任何東西。當時我有一個seeeduino巨型連接。 – cmroanirgo 2011-04-20 02:07:05
@cmroanirgo它在設備管理器中顯示的是什麼? – Brandon 2011-04-20 04:26:12
它顯示爲「USB串行端口」(並且deicimila也響應相同)。對我來說,唯一真正的解決方案是打開每個COM端口,發送一個魔法字節,並聽取魔術般的迴應,就像其他答案所暗示的那樣。 – cmroanirgo 2011-05-12 04:35:14