Book Image

Hands-On Embedded Programming with Qt

By : John Werner
Book Image

Hands-On Embedded Programming with Qt

By: John Werner

Overview of this book

Qt is an open source toolkit suitable for cross-platform and embedded application development. This book uses inductive teaching to help you learn how to create applications for embedded and Internet of Things (IoT) devices with Qt 5. You’ll start by learning to develop your very first application with Qt. Next, you’ll build on the first application by understanding new concepts through hands-on projects and written text. Each project will introduce new features that will help you transform your basic first project into a connected IoT application running on embedded hardware. In addition to gaining practical experience in developing an embedded Qt project, you will also gain valuable insights into best practices for Qt development and explore advanced techniques for testing, debugging, and monitoring the performance of Qt applications. The examples and projects covered throughout the book can be run both locally and on an embedded platform. By the end of this book, you will have the skills you need to use Qt 5 to confidently develop modern embedded applications.
Table of Contents (22 chapters)
Free Chapter
1
Section 1: Getting Started with Embedded Qt
5
Section 2: Working with Embedded Qt
10
Section 3: Deep Dive into Embedded Qt
14
Section 4: Advanced Techniques and Best Practices
Appendix A: BigProject Requirements

Creating our embedded environment

As much as I would like to get right down to writing software, there are some hardware issues that need to be taken care of first. I chose to cover this first so that you have time to get everything together before you need to use it.

The Raspberry Pi 3B+ was chosen because of its low cost, high availability, and good community support. We will also be using the Raspberry Pi 7" touchscreen display and a Raspberry Pi Sense HAT. Additionally, you will want a USB keyboard, USB mouse (optional), power supply for the Raspberry Pi, and a 16 or 32 GB micro SD card.

You will also want a network connection between your Raspberry Pi and your development host. If possible, you will want the Raspberry Pi on the same network that your host uses for its network access; however, you may also choose to add an additional network interface to your host and set up a separate network.

Details on how to configure multiple network cards will depend on your exact version of Linux. A good place to start looking is the Ubuntu Stack Exchange forum (http://askubuntu.com) or the Server Fault Stack Exchange (http://serverfault.com). You may want to try searches like multiple NICs or two network cards.

Obtaining the hardware

While you can purchase all of these individually, there are several starter kits available that include everything you need but the Sense HAT. I chose to go with the NeeGo Raspberry Pi 3B+ Starter Kit and ordered the Sense HAT separately.

To get the most out of this book, you will want to get the hardware as soon as possible, but don't let that stop you! If you are waiting for pieces to arrive, you can skip ahead to the section, Installing Qt, and get that going. One of the great things about using Qt is that you can do most of your early development and testing on the host computer, and then simply rebuild it for your target!

Once you have the hardware, assemble the main Raspberry Pi board and the touch screen display and its driver card, but don't put anything in a case. You will need access to the SD card slot on the main Raspberry Pi board, and most cases will not allow this. We won't need the Sense HAT for a bit, so don't try adding it yet.

Loading the firmware

After experimenting with setting up the stock Raspbian build to work well with Qt, I found it much easier to get a Qt Ready firmware image based on the Yocto Project.

Yocto is a project that simplifies creating embedded Linux images. Jumpnow Technologies has contributed a custom meta-layer for Raspberry Pi boards and generated prebuilt images. The images can be found on the Jumpnow Technologies website at https://jumpnowtek.com/downloads/rpi/. At the time of writing, the thud directory contains the latest images for the Raspberry Pi. The qt images support Qt OpenGL and QML out of the box, which is something I found a bit tricky to get running with Raspbian. Because we are using a Raspberry Pi 3B+, you will want to use the qt-raspberrypi3-2gb.img.xz file. This image does not have built-in support for Wi-Fi, so we will connect through the Ethernet port.

Take a second here to note the default root password for the image. It should be found in the README.txt file in downloads/pi. The first time you log in, you will be prompted to change the password.

More information on the Yocto Project can be found at https://www.yoctoproject.org/, and details on the Raspberry Pi layer for Yocto can be found at https://jumpnowtek.com/rpi/Raspberry-Pi-Systems-with-Yocto.html.

Backing up the SD card

If your Raspberry Pi came with an image pre-installed on a micro SD card, you should make a backup of that image before putting a new image on the card. Since you will be extracting an uncompressed image, you will need to have at least as much free space on your host PC as the size of the micro SD card.

Identifying the SD card device

First, you need to identify the Linux device ID of the micro SD card. The simplest way to do this is to use dmesg and a little logic.

If the SD card is already in the host PC, safely eject it.

In Command Prompt, enter the dmesg command. This will produce a list of kernel-level messages. Identify the last line of the output so that you can recognize new lines when they are added, as shown in the following code:

[On Host] $ dmesg
​​...
[175534.610523] Key type id_legacy registered
[183431.189380] usb 2-5: new high-speed USB device number 7 using ehci-pci
[183433.051881] usb 2-5: New USB device found, idVendor=0bda, idProduct=0138
[183433.051889] usb 2-5: New USB device strings: Mfr=1, Product=2, SerialNumber=3
[183433.051893] usb 2-5: Product: USB2.0-CRW
[183433.051896] usb 2-5: Manufacturer: Generic
[183433.051899] usb 2-5: SerialNumber: 20090516388200000
[183433.363950] ums-realtek 2-5:1.0: USB Mass Storage device detected
[183437.118622] scsi host5: usb-storage 2-5:1.0
[183437.119522] usb 2-5: USB disconnect, device number 7

[On Host] $

Now, insert the SD card, and immediately issue the dmesg command again. When the card is inserted, Linux will generate log messages noting what device it is assigned to:

[On Host] $ dmesg
...
[183433.363950] ums-realtek 2-5:1.0: USB Mass Storage device detected
[183437.118622] scsi host5: usb-storage 2-5:1.0
[183437.119522] usb 2-5: USB disconnect, device number 7
[183527.597445] usb 2-5: new high-speed USB device number 8 using ehci-pci
[183528.626641] usb 2-5: New USB device found, idVendor=0bda, idProduct=0138
[183528.626645] usb 2-5: New USB device strings: Mfr=1, Product=2, SerialNumber=3
[183528.626647] usb 2-5: Product: USB2.0-CRW
[183528.626649] usb 2-5: Manufacturer: Generic
[183528.626650] usb 2-5: SerialNumber: 20090516388200000
[183528.938856] ums-realtek 2-5:1.0: USB Mass Storage device detected
[183531.850735] scsi host5: usb-storage 2-5:1.0
[183533.307556] scsi 5:0:0:0: Direct-Access Generic- Multi-Card 1.00 PQ: 0 ANSI: 0 CCS
[183533.309572] sd 5:0:0:0: Attached scsi generic sg2 type 0
[183534.866611] sd 5:0:0:0: [sdb] 62333952 512-byte logical blocks: (31.9 GB/29.7 GiB)
[183535.386748] sd 5:0:0:0: [sdb] Write Protect is off
[183535.386757] sd 5:0:0:0: [sdb] Mode Sense: 03 00 00 00
[183535.965682] sd 5:0:0:0: [sdb] No Caching mode page found
[183535.965693] sd 5:0:0:0: [sdb] Assuming drive cache: write through
[183538.506518] sdb: sdb1
[183540.690613] sd 5:0:0:0: [sdb] Attached SCSI removable disk
[On Host] $

The new lines referring to sdb (italicized) are shown in the preceding code. From looking at them, we see that the SD card is /dev/sdb.

Grabbing the image

Now that we know the device, we can grab a backup image of the pre-installed image. If you are using a new SD card, you can skip this section and refer to it when needed in the future.

You will want to use as fast an SD card and reader as you can. Making a backup will require reading the entire card—that's 32 GB of data on a 32 GB card.

We will be using the dd command to pull the image off of the card and bzip2 to compress it as it is stored. On Ubuntu systems, reading from the raw SD requires root privileges, for which we will use sudo. The following example also includes status=progress in the dd command so that it prints out progress as it's extracting:

[On Host] $ sudo dd if=/dev/sdb status=progress bs=1M | bzip2 -c > BackupImage.img.bz2

Burning a new image

There are many ways to load the firmware on the micro SD card. One of the most basic ways is to use the Linux dd command, but that requires that the image is uncompressed. That's why I prefer to use the graphical balenaEtcher (https://balena.io/etcher). It can handle several different compression formats, including ZIP. Simply insert the SD card into your host machine, start balenaEtcher, choose the image, choose the micro SD card, and start flashing the image to the SD card.

When the flashing is done, ensure that the Raspberry Pi is powered off and insert the micro SD card into the micro SD card slot on the main Raspberry Pi board.

Connections and first boot

Now that your Raspberry Pi is assembled and the micro SD card has been inserted, it's time to connect it up and boot it, as follows:

  1. Connect your keyboard and mouse to the USB ports on the Raspberry Pi. If you went with the NeeGo kit we mentioned previously, you will have received a combined wireless keyboard/mouse that uses a single USB dongle. Plug that in.
  2. Next, connect an Ethernet cable to the Raspberry Pi.
  1. There is no on/off switch on the Raspberry Pi, so I find it easiest to plug the power supply into a power strip with a switch. When powered, the Raspberry Pi automatically starts booting.
  2. Now that the power supply is plugged into mains power, it's time to plug the other end into the USB OTG port on the Raspberry Pi or the video card (either will work). If you don't have a switch on the power supply, the Raspberry Pi will immediately start booting. If you do have a switch, now is the time to turn it on.
  3. The screen will briefly display the Yocto logo as it boots then come up with a login prompt.
  4. Log in as root using the password provided, then choose a new secure password for root. You will be using this password to log in later.

Network configuration

Now that you have logged in and set the root password, use hostname to find the hostname of the system. If needed, edit /etc/hostname and manually set your desired hostname. If you changed /etc/hostname, you must reboot the Raspberry Pi to make it take effect. This can be done by simply typing reboot at Command Prompt.

If your network is set up for DHCP connections, an IP address will have already been set for the board, and the Raspberry Pi will already be accessible through the hostname. If you don't have DHCP set up on your network, you will want to configure a static IP address for the Raspberry Pi and add the hostname and IP address to /etc/hosts on your host PC.

You can test the connection between your Host PC and the Raspberry Pi by issuing the following command on the host: $ ssh root@raspberrypi
Here, raspberrypi is the name of the device you found or configured previously.
If everything is correctly configured, you should be able to enter the root password and get Command Prompt on the Raspberry Pi.

The Yocto image we are using comes complete with a firewall. It is designed to help to make your Target more resistant to network-based attacks. But like many safety features (especially child-proof medicine bottles), the Target's firewall can get in the way. For the purposes of training, I suggest that you disable it and reboot your Target:

[On Target]$ update-rc.d firewall remove
[On Target]$ rm ./rcS.d/S60firewall
[On Target]$ reboot

If you want to avoid having to enter the root password with every connection to the Target, you can use ssh-copy-id to copy a unique key from your host PC to the Target. After doing this, ssh will try the key before asking for a password.

The format of the command is as follows:

[On Host] $ ssh-copy-id -f root@raspberrypi

If you don't have the ssh credentials on the host machine, the command will prompt you on how to create them. -f tells ssh-copy-id not to test whether the credentials already exist.

The Yocto image comes with a custom firewall rule that will lock login for 30 seconds after three failed login attempts. ssh-copy-id can trigger this.

Installing RSync

RSync is a very powerful tool for synchronizing directories across machines. We will be using it fairly heavily during our setup. Unfortunately, rsync is not part of the Yocto image we are using, so we need to download, build, and install it ourselves on the Target. Let's get started:

  1. From Command Prompt, you can download the sources for rsync using wget:
[On Target] $ wget https://download.samba.org/pub/rsync/src/rsync-3.1.3.tar.gz
  1. Once the tarball has been downloaded, untar and configure it to install in /usr/bin:
[On Target] $ ./configure --prefix=/usr

  1. You can now build and install it, as follows:
[On Target] $ make && make install