Serial Port Tutorial
From Xojo Documentation
Using Xojo, you can control any hardware with a serial interface. This Tutorial will walk you through creating an application in Xojo that can communicate with a serial device.
Watch the tutorial video or follow the steps below!
This tutorial assumes you have gone through the Xojo GettingStarted:Desktop QuickStart and GettingStarted:Desktop Tutorial and thus have a basic understanding of how to navigate around a simple project, get to the Inspector, the Library, the Code Editor, etc. If you haven’t gone through the Xojo Desktop QuickStart and Tutorial yet, you should do so first.
About the Barcode Scanner
It makes sense to first start with the serial device. For this tutorial, the serial device must be an RS-232 device. That means it has a connector like this:
Computers no longer have RS-232 ports so you’ll also need an RS-232 to USB adapter like this:
This allows your serial device to connect to your computer through USB. There are some devices that combine these two so you don’t need the adapter. What is important is that the device makes it clear that it’s a serial device.
This tutorial uses a Motorola LS2208 barcode scanner but you can connect to and communicate with any serial device. This particular barcode scanner is popular and available from Amazon for about $100 new or less than $40 used.
Many bar code scanners simply pretend to be a keyboard. You scan a barcode and they convert that to a value then inserts the value into the keyboard buffer as if the user typed it. That’s fine for some purposes but it means the user must have the cursor in the field where they want the barcode value to appear. You may not want to depend on that or you may be using a device that doesn’t pretend to be something else and you must communicate with it directly.
Create the Project
- Launch Xojo (if you haven’t already) and create a new Desktop project.
- Serial devices connect to a specific port on the computer so you’ll need to be able to tell your code the number of the port into which you connected your device. If you know the port number, you can just hard-code it. If you know the name the device uses, you can loop through all of the serial devices and look for the port that has the matching name.
- Unfortunately, operating systems don’t provide an easy way for a typical end user to find out which devices are plugged in to which ports. The best thing to do is add a Popup Menu to your app that lists the serial devices so the user can choose one.
- Drag a Label from the Library and title it "Serial Ports:".
- Drag a Popup Menu from the Library and set the Name property of the control SerialPortsPopupMenu.
- Your window should now look like this:
- Ideally, this Popup Menu will automatically update to show devices that have been added or removed. When you plug in your device, you’ll want it to appear in this menu and disappear when you unplug it. To do that, you will need a Timer control that will periodically update the SerialPortsPopupMenu control.
- Drag a Timer control from the Library and drop it anywhere in the Layout Editor.
- Because a Timer control has no user interface, it appears in the tray at the bottom of the Layout Editor in what is called the Shelf.
- Set the Timer’s Name property to PortListUpdater.
- Set the PortListUpdater’s Period property to 500.
- This will cause the PortListUpdater to fire over and over again every half second.
- Double-click the PortsListUpdater, select the Action event and click OK.
- In the Action event copy and paste the following code:Dim count As Integer = SerialPortsPopupMenu.ListCount
If System.SerialPortCount <> count Then
// The number of serial devices has changed so update the menu
SerialPortsPopupMenu.DeleteAllRows
For i As Integer = 0 To System.SerialPortCount - 1
SerialPortsPopupMenu.AddRow(System.SerialPort(i).Name)
Next
If System.SerialPortCount < count Then // a device has been removed
SerialPortsPopupMenu.ListIndex = 0
Else // one has been added so select the new device
SerialPortsPopupMenu.ListIndex = System.SerialPortCount - 1
End If
End If- This code first gets the count of the number of items in the SerialPortsPopupMenu. It then compares that to the number of serial ports in use and if they are not the same, it knows that either a new device has been connected or an existing device has been disconnected. In either case, it deletes all the rows from the popup menu then loops through the serial ports, adding the names of the device connected to each port to the popup menu. Finally, it checks to see if the number of serial ports currently in use is less than the number of rows the SerialPortsPopupMenu previously had. If that’s the case, a device was removed so the code selects the first item (item 0) from the list of serial ports. If not, then a device has been added and it makes sense the user would want that device selected so the code selects the very last row of the SerialPortsPopupMenu.
- Click the Run button to run the project.
- If you get a syntax error, it’s likely to be the result of one or more names of the controls not matching those in the code so check them over carefully and update your control names to match the code.
On MacOS with no new devices plugged in to your USB ports, you’ll see two items in the Popup Menu:
- Bluetooth-incoming-port
- Bluetooth modem
- On Windows, the Popup Menu will likely be empty. If you happen to be running Windows on MacOS via VMWare or Parallels, you may have an item titled “COM1” in the popup menu.
- On Linux it varies. With the Mint distribution you may see a long list of numbered ports all beginning with “/dev/ttyS”.
- If you get a syntax error, it’s likely to be the result of one or more names of the controls not matching those in the code so check them over carefully and update your control names to match the code.
- With the app still running, plug in your serial device and you should see it appear in the popup menu and be selected. Depending on the OS, you will get different port names when you plug in this barcode scanner:
- macOS: usbserial-FTHI8S8F
- Linux Mint: /dev/ttyUSB
- Windows: COM3
- Experiment with unplugging the device and plugging it back in to see that the popup menu automatically updates.
- Now it is time to add the Serial control. Drag a Serial control from the Library and drop it anywhere in the Layout Editor. Because it’s not a visible control, it will be added to the Shelf.
- Click Inspector in the toolbar to view it.
- You’ll see the default values for the Serial control in the Behavior section. You’ll have to look at the manual for your device to determine how to set the baud rate, bits, parity, etc. For the Motorola barcode scanner, you only need to change the Baud property to 9600. It will connect at a higher speed, but it won’t work properly.
- If you’re using the same barcode scanner I’m using, set the Baud property to 9600. Otherwise, set this property accordingly.
- Before you start programming the Serial control, add a button the user presses to connect to the serial device. You could of course choose to make this occur when the user selects a device from the popup menu. However, to keep things nicely separated for the purposes of this tutorial, add a Connect button.
- Switch to the Library and drag a Default Button to layout, positioning it to the right of the popup menu.
- Change the button’s Caption property to Connect.
- Change the button’s Name property to ConnectButton.
- Because we don’t want this button enabled until the user selects a device from the popup menu, set the ConnectButton’s Enabled property to False.
- Next, you need to make the ConnectButton enable if a device is selected and disable otherwise. Double-click on the SerialPortsPopupMenu and add the Change event to it.
- In the Change event, copy and paste the following code:
- Next we need to make the Connect button work. The button will change to “Disconnect” once a connection is made. When the user clicks the button, if the caption is Disconnect, it will:
- Close the serial port
- Change the caption back to “Connect”
- Enable the popup menu
- Tell the PortListUpdater timer to start firing again
- Otherwise, the user wants to connect so it will:
- Set the serial port to the number of the item selected in the popup menu
- Open the serial port
- Set the caption of the button to “Disconnect”
- Disable the popup menu
- Turn off the PortListUpdater timer
- Select Window1 in the Navigator on the left-hand side.
- Double-click on the Connect button and add the Action event handler.
- Copy and paste the following code into the Action event handler:If Me.Caption = "Disconnect" Then // Disconnect from the serial port
Serial1.Close
Me.Caption = "Connect"
SerialPortsPopupMenu.Enabled = True
PortListUpdater.Mode = Timer.ModeMultiple ' turn it on
Else // Connect to the serial port
// Set the serial port to the index of the one chosen in the popup menu
Serial1.SerialPort = System.SerialPort(SerialPortsPopupMenu.ListIndex)
If Serial1.Open Then
Me.Caption = "Disconnect"
SerialPortsPopupMenu.Enabled = False
PortListUpdater.Mode = Timer.ModeOff
Else
Beep
MessageBox("The selected serial port could not be opened.")
End If
End If- Before reading the data from the device, there needs to be a place to show it.
- Click on Window1 in the Navigator to select it.
- Drag a TextArea control from the Library to the window.
- Position and size the TextArea control so that your layout looks like this:
- In the Inspector, locate the ReadOnly property in the Behavior section and set it to ON.
- Last but not least, you need to add the code that will actually read the data from the serial port (through the Serial1 control) and append it to TextArea1.
- Double-click on Serial1 and add the DataAvailable event.
- Copy and paste the following code into the DataAvailable event:If Instr(Me.LookAhead(Encodings.ASCII), Chr(13) + Chr(10)) > 0 Then
TextArea1.Text = TextArea1.Text + Me.ReadAll(Encodings.ASCII)
End If- By default, the Motorola LS2208 barcode scanner provides a value with no terminating character. That means you have to keep reading from the serial port until you no longer get any data. That complicates things. If your device works this way, you can add a timer that keeps checking the length of the incoming data and when it sees it hasn’t changed, it assumes the full value has been received. Fortunately, the LS2208 can be programmed to append a carriage return and line feed to the end of the value. If you have one or bought one to experiment with, take a look at the quick start guide that came with it. You will see a section titled, "Add an Enter Key (Carriage Return/Line Feed)" with three bar codes. Just scan those three in order and your scanner will be programming to append CR and LF to the end of any value.
- The code above calls the Serial control’s LookAhead function to get the data from the serial port. It’s then passing that to the InStr method to see if CR and LF can be found. If they can, you have the entire value so you call the Serial control’s ReadAll method to read the data and append it to the TextArea.
- Lastly, add an error handler just in case something goes wrong.
- Click on the Serial1 control to make sure it’s selected.
- Click the Add button in the Layout Editor’s toolbar and choose Event Handler.
- Add the Error event handler and add the following code to it:Beep
MessageBox("A serial port error occurred.")
If you have a Motorola LS2208 bar code scanner and have programmed it as instructed, you can now run your project and give it a try. If you have another type of device that terminates the incoming data with other characters, you should be able to modify the code above accordingly.
This tutorial went through a bunch of set up to make the UI display the ports, update automatically, enable and disable when it should, but most of that in a real world scenario could probably be avoided. The meat of this example is the Serial control and its DataAvailable event code above which is only 3 lines.
Next Steps
For more information on Serial devices, refer to these topics:
- Serial Devices in User Guide
- Serial class in Language Reference
Examples Projects:
- Communication/Serial/Line State Change Tester
- Communication/Serial/Serial Port Bar Code Reader Example
- Communication/Serial/SerialLineIndicator