Real Software Forums

The forum for Real Studio and other Real Software products.
[ REAL Software Website | Board Index ]
It is currently Tue Feb 20, 2018 12:50 pm
xojo

All times are UTC - 5 hours




Post new topic Reply to topic  [ 1 post ] 
Author Message
 Post subject: Windows Tip: From USB to Serial Port
PostPosted: Wed Feb 08, 2012 4:06 pm 
Offline
User avatar

Joined: Fri Nov 10, 2006 4:10 pm
Posts: 1855
Location: Michigan, USA
What:
If you're like me, you deal with USB serial devices; that is, a USB device that shows up as a Serial Device on some COM port. What's annoying, is that Serial Ports only give their port information COM1..2..etc. This has to do with what physical port you plugged your device into. So how do you detect which port your device is on? Well, with the information so far you can't. You either have to have the user select the COM port from a list, or assume the device is always plugged into the same port. Gah! No!

Now for this tutorial I'm going to assume you've spent the $40 and bought the MBS USB Plugin. Why? Because it saves time and energy. If you haven't done this, then roll up your sleeves and dig up the Declare functions from the Windows API. Completely doable, but I'd rather spend the money, personally. From there, the principal is the same, so this tutorial is equally relevant. (If you do achieve this with declares, be a friend and post the code on how you did it here.)

Again, this is a Windows Only solution. If someone wants to expand on how to do this for OSX, that'd be great.


How:
1. So let's look at what we've got from the WinUSBDeviceMBS object that's helpful: Product Name/ID, Vendor Name/ID, serial number. There's nothing here that even hints as to what COM port is being used. Bummer. We're going to have to dig. To the registry!

2. Deep in the tedious registry is a magical directory called "CurrentControlSet". This can be found at the path: HKEY_LOCAL_MACHINE\SYSTEM\CurrentControlSet\". This is a directory of all the services and controls your machine is actively using. New Control Sets are made, which you'll see as the adjacent directories, but the Current Control Set is what interests us because it's a pointer to the active set. If you dig a bit deeper in here, you'll find the /Enum/FTDIBUS directory. If you're not familiar, FTDI is the chip which manufacturers put in their USB devices to make them immediately serial communicable. Brilliant.

3. Here's our find: The FTDIBUS directory contains every USB device with serial capabilities. It's formatted: VID_XXXXX+PID_XXXXX+SERIALKEYA" — Vendor ID, Product ID, and the Serial Key with a strange "A" tossed on the end. Now, if you're fortunate, the manufacturer has a unique PID for their products... or they're stupid and made them all the same, as Omega Engineering did for the products I use. No problem, we're going to use the serial anyway. With this information, we're going to tie the Serial of the product with the vital information found in the "/0000/Device Parameters" directory: the "PortName" key, the value of which is the name of the COM port.

4. Alright, so let's get coding:
Dim Registry As New RegistryItem ("HKEY_LOCAL_MACHINE\SYSTEM\CurrentControlSet\Enum\FTDIBUS")
Dim Devs() As WinUSBDeviceMBS = WinUSBDeviceMBS.Devices()
Dim Name, SerialNumber, ComName As String
Dim Child, PortReg As RegistryItem
Dim HumidityPort, TempPort As String
Dim Port As SerialPort
Dim Index As Integer

For Index = 0 To (Registry.FolderCount - 1)
Child = Registry.Item(Index)
Name = Child.Path.NthField("\", Child.Path.CountFields("\"))
SerialNumber = Name.NthField("+", Name.CountFields("+"))
SerialNumber = SerialNumber.Left(SerialNumber.Len - 1)

For DevIndex As Integer = Devs.Ubound DownTo 0
If (Devs(DevIndex).Vendor = "Omega Engineering") And (Devs(DevIndex).SerialNumber = SerialNumber) Then
PortReg = Child.Child("0000").Child("Device Parameters")
ComName = PortReg.Value("PortName")

Select Case Devs(DevIndex).Product
Case "RH-USB"
HumidityPort = ComName

Case "IR-USB"
TempPort = ComName

End Select
End If
Next
Next

If (HumidityPort = "") Then MsgBox "Error: Unable to find humidity guage."

If (TempPort = "") Then MsgBox "Error: Unable to find IR thermometer."

For Index = 0 To (System.SerialPortCount - 1)
Port = System.SerialPort(Index)

Select Case Port.Name
Case AmbPort
HumiditySerial = Port

Case DiskPort
TemperatureSerial = Port

End Select
Next


5. Yeah.. Let's break that down a bit. First, I get all of the USB devices in an array, then I dig into the registry, as described, and break apart the directory names in the FTDIBUS directory to get my serial numbers. I then check for USB devices that have the vendor name I'm looking for, serial key, and matching product name I'm interested in. I then store the COMX name for the corresponding device. Finally, I go through all the System Serial Ports, find the port with the matching name, and we're good to go.

Some additional error checking should be placed within this code, but I wanted to keep it simple for the sake of explanation and readability. I also used constants in my code for product and vendor names. But all in all, that's really how it's done. I hope this useful to someone, somewhere, someday. :)

_________________
Windows 8 x64
Windows XP Pro SP3
Ubuntu 11.04 via Virtual Box
RS Enterprise 2012r1.1

Programming Tutorials & Free Projects: http://www.JasonTheAdams.com
"Christianity has not been tried and found wanting; it has been found difficult and not tried." - G.K. Chesterton


Top
 Profile  
Reply with quote  
Display posts from previous:  Sort by  
Post new topic Reply to topic  [ 1 post ] 

All times are UTC - 5 hours


You cannot post new topics in this forum
You cannot reply to topics in this forum
You cannot edit your posts in this forum
You cannot delete your posts in this forum

Search for:
Jump to:  
cron
Powered by phpBB © 2000, 2002, 2005, 2007 phpBB Group