[EN] List the serial ports connected to the RPi with pySerial and PyQt5.

In the previous article, we have read the list of devices connected to the serial port of the Raspberry Pi board or RPi with the pySerial library in text mode as shown in Figure 1. This article combines the previous working principles with the use of a graphical user interface via the PyQt5 library, listed in the combobox for users to choose from. If no serial port connected to the board is found, the RPi disables the combobox from user selection. Therefore, this article discusses the implementation of pySerial with the QLabel and QComboBox libraries. PyQt5.

This article consists of 3 parts:

  1. List the serial ports connected to the RPi with pySerial.
  2. List the serial ports connected to the RPi with pySerial and PyQt5.
  3. LEDs on/off via PyQt5 and serial communication.

Improve the code

From the previous sample program code, the programmer must specify the name of the port in order to check whether each name is connected or not. If you want the program to read all the relevant lists after that do all checks if any device is connected it remembers its name in the list of connected ports. After that, report which port devices are found. As an example of the following program.

# -*- coding: UTF-8 -*-
import sys
import glob
import serial

ports = glob.glob('/dev/tty[A-Za-z]*')
result = []
for port in ports:
    try:
        s = serial.Serial(port)
        s.close()
        result.append(port)
    except (OSError, serial.SerialException):
        pass
if (len(result) == 0):
    print("ไม่พบพอร์ตอนุกรม")
else:
    print("พบพอร์ตอนุกรมดังรายการต่อไปนี้:")
    for p in result:
        print("{}".format(p))

An example of the result of an adjusted program is shown in Figure 2.

PyQt5

Based on the PyQt5 article, we can use PyQt5 with Windows, macOS or Linux operating systems, along with an example of opening a window and the use of the button has been completed. In this article, we will add more to the Raspberry Pi board in terms of installing PyQt5 via apt. The sample programs in this article can be applied to other operating systems as well.

Install PyQt5

Installing the PyQt5 library with Raspbian, the Raspberry Pi board’s operating system, can be done via apt install:

sudo apt install python3-pyqt5

QLabel

QLabel is a widget for displaying text inherited from QtWidgets.QFrame which is inherited from QtWidgets.QWidget, in addition, must be imported to the QLabel library. To create a QLabel object, you must run as follows: The parameters that must be passed include the text displayed in the label and the position value of the parent window that this label should be displayed on the window. The part of the text can be set to any value and can be changed later. The main window in the example program uses self to indicate that the label is under the window that was created.

obj = QLabel( message, window )

To assign text to an object of type QLabel, use the following format method.

obj.setText( message )

If you want the new QLabel to be resized to suit the specified text, the following function is called.

obj.adjustSize()

The move() command can be set as follows:

obj.move( x, y)

An example of creating a label is as follows.

        self.lbl = QLabel("ข้อความ", self)
        self.lbl.move( 100, 20 )
        self.lbl.setText("ข้อความ2")
        self.lbl.adjustSize()

In addition, if you want to display an image instead of that text, it can be done as well but will be discussed in the next article.

QComboBox

The QComboBox widget looks like a list, but the user can select only one item from the list provided by the programmer, as shown in Figure 3. The QComboBox library is a class that inherits from the QComboBox library, another QtWidgets.QtWidget

To create a QComboBox widget, write as follows: where the parent window is the position value of the window that our combobox widget is under that window. For example, the program would be self because it uses the created window as the parent window and puts a combobox inside it.

obj = QComboBox( window )

Adding an item to the combobox’s list can use the addItem() command in the following format.

obj.addItem( data )

To set the display position of the combobox, use the move() command to specify the coordinates (x,y) in the upper-left corner of the combobox as the following format

obj.move( x, y )

If the programmer wants to know the number of items in a combo box, the count() function can be used to count numbers according to the following usage patterns:

item_number = obj.count()

Reading the sequence value selected by the user use currentIndex() as follows:

selected_index = obj.currentIndex()

If you want to read the name of the selected item, use the command currentText() according to the following usage pattern.

message = obj.currentText()

Example Code

The following example program is using the code to read the list of serial ports connected to the Raspberry Pi Board as shown in Figure 1 and display it via PyQt5 by bringing the list of found ports into a QComboBox object. 3 Serial port devices are listed as 3 selections in the combo box, etc.

# -*- coding: UTF-8 -*-
import glob
import serial
from PyQt5.QtWidgets import QApplication, QLabel, QComboBox, QWidget, QMainWindow, QPushButton
from PyQt5.QtGui import QIcon, QColor
 
class MyApp(QWidget):
    def __init__(self, title, w=640, h=480):
        super().__init__()
        self.setWindowTitle(title)
        self.setGeometry(0, 0, w, h)
        self.status = False

        self.lbl = QLabel("รายการพอร์ตอนุกรม", self)
        self.lbl.move( 100, 20 )
        self.lbl.adjustSize()

        self.cbb = QComboBox(self)
        self.cbb.move( 280, 20 )
        
        ## serial port
        ports = glob.glob('/dev/tty[A-Za-z]*')
        for port in ports:
            try:
                s = serial.Serial(port)
                s.close()
                self.cbb.addItem(port)
            except (OSError, serial.SerialException):
                pass

        self.show()


if __name__ == '__main__':
    app = QApplication(sys.argv)
    my_app = MyApp("PyQt5 Serial")
    sys.exit(app.exec_())

The working principle of the sample program is as follows.

  • Create a main window from QWidget.
  • Set width 640 and height 480 or user-defined from main program.
  • Two sub widgets have been created.
    • Create labels for display “Serial port list”
    • Create a combo box to keep a list of connected ports for users to choose
  • Search for a list of ports connected to external devices via serial communication ports.
    • Create a variable to store a list of all known serial ports whose format begins as /dev/tty
    • Do a loop to check if each name is valid or not.
      • If it valids, put the name in the combobox list.
      • If there’s the exception, the error is ignored.
  • Displays the window

The main program creates a window with the window title text “PyQt5 Serial” and exits by closing the window close button. An example of the results of the program’s operation is shown in Figure 4.

Figure 4 Result of the code

Conclusion

From this article, the reader has taken reading the list of ports connected to the serial port of the Raspberry Pi board to work in graphical mode via PtQt5 by putting the read value in the Combobox for the user to select the list. It has been found that having previously coded in text-mode prototypes makes it easier to convert the code to graphics mode. This is because in graphics or GUI mode it requires running widgets and other windows (Windows or Widgets) for the user interface and the hard thing that is ripe is a matter of how to place it, how beautiful, attractive, and easy to use according to the principles of UX Design or user-centered design which is another very important issue because no matter how good the program but the design is hard to use or not usable, there is no incentive for users to turn to our program. Finally, We hope this article will be of some help to you and have fun with programming.

Reference

  1. QComboBox

(C) 2020-2022, By Jarut Busarathid and Danai Jedsadathitikul
Updated 2022-01-11