הערה
הגישה לדף זה מחייבת הרשאה. באפשרותך לנסות להיכנס או לשנות מדריכי כתובות.
הגישה לדף זה מחייבת הרשאה. באפשרותך לנסות לשנות מדריכי כתובות.
Question
Thursday, March 3, 2016 5:32 PM
Hello,
I am creating a script to auto-detect the arduino on the serial port. For some reason the code I found for this only displays ONE port even if there are TWO ports available. Arduino is on COM5. Any help will be greatly appreciated.
If I run the below code, I get COM1 & COM5:
Sub GetSerialPortNames()
For Each sp As String In My.Computer.Ports.SerialPortNames
lstPorts.Items.Add(sp)
Next
End Sub
But if I run this, I only get COM1:
Dim connectionScope As New ManagementScope()
Dim serialQuery As New SelectQuery("SELECT * FROM Win32_SerialPort")
Dim searcher As New ManagementObjectSearcher(connectionScope, serialQuery)
Dim desc As String
MsgBox(searcher.Get.Count) 'Displays only one port
Try
For Each queryObj As ManagementObject In searcher.Get()
desc = queryObj("Name").ToString
MsgBox(queryObj("Name")) 'Only shows COM1
If (desc.Contains("Arduino")) Then
MsgBox(queryObj("Name"))
End If
Next
Catch err As ManagementException
MessageBox.Show("An error occurred while querying for WMI data: " & err.Message)
End Try
All replies (16)
Friday, March 11, 2016 12:11 AM ✅Answered
Got it Cyrille.
Private Sub autoconnect()
For Each sp As String In My.Computer.Ports.SerialPortNames
Try
SerialPort1 = New SerialPort(sp, 9600, Parity.None, 8, StopBits.One)
SerialPort1.ReadTimeout = 700
SerialPort1.WriteTimeout = 700
SerialPort1.Open()
Dim ListeningWatch As New Stopwatch
Dim serialMessage As String
SerialPort1.Write("Arduino")
ListeningWatch.Start()
While ListeningWatch.ElapsedMilliseconds < 700 And ListeningWatch.IsRunning
serialMessage = SerialPort1.ReadLine()
If serialMessage.Contains("Arduino") Then
ListeningWatch.Stop()
btnConnect.Text = "Disconnect"
ArduinoConnected = True
lstConsole.Items.Add("Arduino Connected")
Exit For
End If
End While
Catch ex As TimeoutException
End Try
Next
If ArduinoConnected = False Then
MsgBox("Arduino failed to connect. Please check that it is plugged in.")
End If
End Sub
Thursday, March 3, 2016 5:52 PM
I'm not too sure why you are doing a sql query here.
What I use for enumerating the available ports into a selectable combobox is:
don't forget to Imports System.IO.Ports
Dim myPort As Array 'Array to hold the COM detected
myPort = IO.Ports.SerialPort.GetPortNames() 'Get the portnames for the IO.Ports.SerialPort
'Loading COM into combobox
ComboBox9.Items.AddRange(myPort)
Thursday, March 3, 2016 6:50 PM
I want to autodetect the arduino instead of adding the com ports to a combobox. So I need to analyze the description associated with the ports until I find "Arduino" rather than looking just at the port number.
here is the original explanation of how to do it in C#
http://stackoverflow.com/questions/3293889/how-to-auto-detect-arduino-com-port
Thursday, March 3, 2016 7:00 PM
I see, sorry for the confusion about WMI...
What's your connectionScope parameter looking like? root\cimv2 maybe?
Thursday, March 3, 2016 8:50 PM
For some reason the code I found for this only displays ONE port even if there are TWO ports available. Arduino is on COM5. Any help will be greatly appreciated.
When you use My.Computer.Ports what are the names that you get?
When you examine the ports in device manager, what names are listed?
What is the hardware for these ports? In some cases virtual ports report incorrect names.
Thursday, March 3, 2016 10:14 PM
COM1 and COM5
COM1 - Microsoft Raw Port
COM5 - Arduino
Both show up in the Device Manager and in the combo box so I can manually select the port but if I run the other code to have it done automatically it only finds one port called COM1 Communications Port. If I could only see the port with the code, then auto-detecting the arduino would work.
Friday, March 4, 2016 12:34 AM
I tried that first and it did the same thing then changed the code to the above. Should I put those paramaters back in and change that root\cimv2 to something else?
Friday, March 4, 2016 2:04 AM
Have you seen this?
http://www.codeproject.com/Articles/32330/A-Useful-WMI-Tool-How-To-Find-USB-to-Serial-Adapto
The screen shot would indicate that the query should be SELECT * FROM MSSerial_PortName. Most likely the Win32_SerialPort only refers to hardware based serial ports, not virtual ports. MSSerial_PortName likely includes all serial adapters, both physical and virtual.
Reed Kimble - "When you do things right, people won't be sure you've done anything at all"
Saturday, March 5, 2016 3:40 AM
That seems promising Reed! But I still can't get it to work yet. I tried it in my code and also downloaded the tool and clicked on "Find USB-Serial converters using WMI" but I get "An error occurred while querying for WMI data: Access denied".
Also downloaded the official tool from microsoft and got access denied. I am logged in as the administrator on this PC not sure what else it could be.
EDIT: I checked the COM Security "Access Permissions" and "Launch and Activation Permissions" all local access are set to allow. I restarted my PC too just in case recent windows updates were messing with it. Also tried it first thing after rebooting to make sure nothing else was interfering.
Saturday, March 5, 2016 6:14 AM
If I run the WMI tool (right click run as admin) it works. Problem is autodetecting arduino is supposed to be a fool-proofing thing. If I need to ask people to run as admin, might as well tell them to check the ports by connecting and disconnecting the arduino.
Saturday, March 5, 2016 7:45 PM
If you now just need your application to automatically run as admin, add a new app.manifest file to the project and then edit the requestedExecutionLevel element, setting Level="requireAdministrator".
Reed Kimble - "When you do things right, people won't be sure you've done anything at all"
Saturday, March 5, 2016 11:30 PM
I wonder if you aren't going through a lot of effort for nothing... I'd be willing to bet that anyone who knows what an Arduino is also knows enough to figure out which COM port it is using. Considering that every tutorial on getting started with the hardware includes instructions on finding the COM port, I think it would be safe to assume that users of your application could select the correct COM port for your software.
Now then, if your software is meant to work with some specific firmware running on an Arduino, then discovering a COM port with the "Arduino" description is not sufficient. Suppose the user plugged in some other Arduino that wasn't running the intended firmware? If this is the scenario, then it may be better to poll each COM port with a specific command which will identify the correct device. For example, if the firmware automatically sends some welcome string or command prompt when connecting, your software can open each available serial port and look for that string.
I guess the main point here is that the description of the serial port may not be as useful as it might first appear, depending on how you are wanting to use the information.
Reed Kimble - "When you do things right, people won't be sure you've done anything at all"
Tuesday, March 8, 2016 7:10 AM
This sounds promising! How do I add a new app manifest file? Last time I changed something in a config file it killed the application.
I want to have this done automatically because I am creating a finished product, not a kit. They won't know what an Arduino is. Just open this app on your PC, connect the box, and everything works.
Tuesday, March 8, 2016 9:04 PM
GOT IT WORKING! Basically I cycle through all the ports, ping them and wait half a second for them to respond. If they respond "Arduino", then I leave that port open. I had already tried to do this before but couldn't figure out how to keep the other subs going with the timer active. If you have any suggestions on how to simplify the below I am all ears. I am sure many will benefit from it. Hopefully sending "Arduino" to some random port doesn't cause some self-destruct thing :)
Imports System.IO.Ports
'in public class:
Dim ArduinoConnected As Boolean
'in main window form load:
Timer2.Enabled = False
ArduinoConnected = False
Private Sub autoconnect()
For Each sp As String In My.Computer.Ports.SerialPortNames
Try
SerialPort.PortName = sp
SerialPort.BaudRate = 9600
SerialPort.DataBits = 8
SerialPort.Parity = Parity.None
SerialPort.StopBits = StopBits.One
SerialPort.Handshake = Handshake.None
SerialPort.Encoding = System.Text.Encoding.Default
SerialPort.Open()
SerialPort.Write("Arduino")
Timer2.Interval = 500
Timer2.Enabled = True
While Timer2.Enabled And ArduinoConnected = False
Application.DoEvents()
End While
If ArduinoConnected Then
Exit For
End If
SerialPort.Close()
Catch ex As Exception
MsgBox(ex.Message)
End Try
Next
End Sub
Public Sub Timer2_Tick(sender As Object, e As EventArgs) Handles Timer2.Tick
Timer2.Stop()
End Sub
Public Sub SerialPort_DataReceived(ByVal sender As Object, ByVal e As System.IO.Ports.SerialDataReceivedEventArgs) Handles SerialPort.DataReceived
Dim str As String = SerialPort.ReadExisting()
If str.Contains("Arduino") Then
ArduinoConnected = True
lstConsole.Items.Add("Arduino Connected")
End If
End Sub
Tuesday, March 8, 2016 10:21 PM
Your Timer2 is doing it's cycle only once, and you are defeating the Timer threading ability by doing a While loop (The While...Doevents is not necessary when using a Timer... that's the all point of using a Timer.).
And since you are doing only one cycle with your Timer, maybe you should just use a StopWatch, basically you are waiting for the answer for 500ms... so do a While StartTime-Now <500 ReadLine...
Although it is nice to spell out the parameters for your serialport, you are not (yet?) using parameters, also using the class name as object name is looking for confusion down the Strict programming road so rename the object.
Have a look at this:
Dim _serialPort As SerialPort
_serialPort = New SerialPort("sp", 9600, Parity.None, 8, StopBits.One)
_serialPort.Handshake = Handshake.None 'The default here... why bother?
_serialPort.Encoding = System.Text.Encoding.Default 'Again the Default...
' What about the TimeOuts? need to handle the exceptions if used
'_serialPort.ReadTimeout = 500
'_serialPort.WriteTimeout = 500
_serialPort.Open()
Dim ListeningWatch As New Stopwatch
Dim serialMessage As String
_serialPort.Write("Arduino")
ListeningWatch.Start()
While ListeningWatch.ElapsedMilliseconds < 500 And ListeningWatch.IsRunning
serialMessage = _serialPort.ReadLine() 'wait for a line until the timeout time is reached
If serialMessage.Contains("Arduino") Then
ListeningWatch.Stop() 'Do the other stuff here to get out of the For loop too
End If
End While
Thursday, March 10, 2016 6:52 PM
Thanks Cyrille. I am having trouble getting this new code to work. It does not read anything from the arduino. Also, in the console I get a bunch of: Exception thrown: 'System.TimeoutException' in System.dll
Private Sub autoconnect()
Dim ListeningWatch As New Stopwatch
Dim serialMessage As String
For Each sp As String In My.Computer.Ports.SerialPortNames
serialMessage = Nothing
ListeningWatch.Reset()
Try
_SerialPort = New SerialPort(sp, 9600, Parity.None, 8, StopBits.One)
_SerialPort.ReadTimeout = 500
_SerialPort.WriteTimeout = 500
_SerialPort.Open()
_SerialPort.Write("Arduino")
ListeningWatch.Start()
While ListeningWatch.ElapsedMilliseconds < 500 And ListeningWatch.IsRunning
serialMessage = _SerialPort.ReadLine()
If serialMessage.Contains("Arduino") Then
ListeningWatch.Stop()
btnConnect.Text = "Disconnect"
ArduinoConnected = True
lstConsole.Items.Add("Arduino Connected")
End If
End While
ListeningWatch.Stop()
Catch ex As TimeoutException
_SerialPort.Close()
End Try
Next
If ArduinoConnected = False Then
MsgBox("Arduino failed to connect. Please check that it is plugged in.")
End If
End Sub