Hands-On Embedded Programming with Qt - John Werner - E-Book

Hands-On Embedded Programming with Qt E-Book

John Werner

0,0
39,59 €

-100%
Sammeln Sie Punkte in unserem Gutscheinprogramm und kaufen Sie E-Books und Hörbücher mit bis zu 100% Rabatt.

Mehr erfahren.
Beschreibung

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.

Das E-Book können Sie in Legimi-Apps oder einer beliebigen App lesen, die das folgende Format unterstützen:

EPUB
MOBI

Seitenzahl: 451

Veröffentlichungsjahr: 2019

Bewertungen
0,0
0
0
0
0
0
Mehr Informationen
Mehr Informationen
Legimi prüft nicht, ob Rezensionen von Nutzern stammen, die den betreffenden Titel tatsächlich gekauft oder gelesen/gehört haben. Wir entfernen aber gefälschte Rezensionen.



Hands-On Embedded Programming with Qt
Develop high performance applications for embedded systems with C++ and Qt 5
John Werner
BIRMINGHAM - MUMBAI

Hands-On Embedded Programming with Qt

Copyright © 2019 Packt Publishing

All rights reserved. No part of this book may be reproduced, stored in a retrieval system, or transmitted in any form or by any means, without the prior written permission of the publisher, except in the case of brief quotations embedded in critical articles or reviews.

Every effort has been made in the preparation of this book to ensure the accuracy of the information presented. However, the information contained in this book is sold without warranty, either express or implied. Neither the author, nor Packt Publishing or its dealers and distributors, will be held liable for any damages caused or alleged to have been caused directly or indirectly by this book.

Packt Publishing has endeavored to provide trademark information about all of the companies and products mentioned in this book by the appropriate use of capitals. However, Packt Publishing cannot guarantee the accuracy of this information.

Commissioning Editor: Richa TripathiAcquisition Editor: Shriram ShekharContent Development Editor:Tiksha SarangSenior Editor: Afshaan KhanTechnical Editor: Gaurav GalaCopy Editor:Safis EditingProject Coordinator: Prajakta NaikProofreader: Safis EditingIndexer: Manju ArasanProduction Designer: Arvindkumar Gupta

First published: July 2019

Production reference: 1120719

Published by Packt Publishing Ltd. Livery Place 35 Livery Street Birmingham B3 2PB, UK.

ISBN 978-1-78995-206-3

www.packtpub.com

Packt.com

Subscribe to our online digital library for full access to over 7,000 books and videos, as well as industry leading tools to help you plan your personal development and advance your career. For more information, please visit our website.

Why subscribe?

Spend less time learning and more time coding with practical eBooks and Videos from over 4,000 industry professionals

Improve your learning with Skill Plans built especially for you

Get a free eBook or video every month

Fully searchable for easy access to vital information

Copy and paste, print, and bookmark content

Did you know that Packt offers eBook versions of every book published, with PDF and ePub files available? You can upgrade to the eBook version at www.packt.com and as a print book customer, you are entitled to a discount on the eBook copy. Get in touch with us at [email protected] for more details.

At www.packt.com, you can also read a collection of free technical articles, sign up for a range of free newsletters, and receive exclusive discounts and offers on Packt books and eBooks.

Contributors

About the author

John Werner is an internationally published author, engineer, consultant, and conference speaker with more than 15 years' experience. He has earned patents for inventions ranging from Inkjet printers to automotive ignition systems. John was one of the early users of Qt on QNX and contributed to the early knowledge of how to make it work. He is a contributor to the Qt-related information on Stack Exchange. He is currently a senior software engineer, specializing in Qt development, for Caliber Imaging & Diagnostics.

I would like to acknowledge the following people and companies: Qt, for providing trial licenses of their embedded productsMy GoG family for their support and their endless humorThe team at Caliber Imaging & Diagnostics, my employer, for their support and encouragementNick at La Salon Bianca, for making me look goodThe editorial staff at Packt, for helping me walk through this process of writing my first bookMost of all, my wife and children for their infinite understanding, patience, and support

About the reviewer

Pablo Rogina was born and lives in Buenos Aires, Argentina. He earned his bachelor's degree in computer science at Universidad de Buenos Aires (UBA) and holds a postgraduate degree in information security, also from UBA. He has more than 25 years' extensive experience and exposure to several different positions and responsibilities in IT environments, ranging from programming to network administration, and including system analysis and design, end user support, and database design and management. Over the last few years, he has been focusing on embedded system development, with specific exposure to IoT and computer vision solutions.

Packt is searching for authors like you

If you're interested in becoming an author for Packt, please visit authors.packtpub.com and apply today. We have worked with thousands of developers and tech professionals, just like you, to help them share their insight with the global tech community. You can make a general application, apply for a specific hot topic that we are recruiting an author for, or submit your own idea.

Table of Contents

Title Page

Copyright and Credits

Hands-On Embedded Programming with Qt

About Packt

Why subscribe?

Contributors

About the author

About the reviewer

Packt is searching for authors like you

Preface

Who this book is for

What this book covers

To get the most out of this book

Download the example code files

Download the color images

Code in Action

Conventions used

Get in touch

Reviews

Section 1: Getting Started with Embedded Qt

Setting Up the Environment

Technical requirements

Creating our embedded environment

Obtaining the hardware

Loading the firmware

Backing up the SD card

Identifying the SD card device

Grabbing the image

Burning a new image

Connections and first boot

Network configuration

Installing RSync

Preparing the host machine

Installing Qt

Setting up the cross compilation environment

Installing the cross compilation tools

Preparing for debugging

Accessing the Target's root directory on the host

Building Qt for the Target

Fixing the sources

Building a program

Configuring the Qt build

Decoding the configure command

Building the code

Synchronizing the new components with the target

Running a quick test to ensure how the program works

Summary

Questions

Further reading

Writing Your First Qt Application

Technical requirements

Introducing Qt Creator

Starting Qt Creator

Qt Creator welcomes you

The Examples screen

The Tutorials screen

The Projects screen

The left icon bar

Greetings from Qt

Creating a project

Walking through the New File or Project wizard

Choosing a template

Picking a name and location

Selecting a kit

Defining the main window class

Selecting a source control system for your project

Examining the Edit screen

Viewing projects and open files

A place for editing

Presenting outputs

Designing the UI

Placing a text label

Running the code

Protecting your work

Who are you?

Adding a place to type your name

Causing a response

Fixing a mistake

Launching our application in the Qt Creator debugger

Examining the Debug screen

Setting a breakpoint

Tripping the breakpoint

Getting some help

Digging deeper

Explaining the push button code

Sending and receiving between objects–signals and slots

Cool things about signals and slots

Rules of signals and slots

Testing

Summary

Questions

Further reading

Running Your First Application on the Target

Technical requirements

Configuring Qt Creator for our Target

Telling Qt Creator about a new device

Telling Qt Creator about the cross-compiler

Configuring the debugger for the Target

Letting Qt Creator know about our Raspberry Pi Qt build

Creating a Qt kit

Building for the Target

Adding a kit to the project

Building the application

Deploying on the Target

Running the application on the Target

Making a more flexible display using layouts

Debugging on the Target

Troubleshooting debugging

Summary

Questions

Section 2: Working with Embedded Qt

Important Qt Concepts

Technical requirements

Communicating effectively – signals and slots

Quick info – Signals and slots

Signals and slots in non-GUI code

Preparing the header

Using the QTimer

Setting up the timer

Connecting the QTimer signal

Finishing the code

Running our application

Signals and slots using lambdas

Queuing things up

When should I use a queued connection?

Implementing Signals Not Needed

Looking inside – Qt's introspection support

Properties

Q_PROPERTY

QVariant

Enums

Differing views — model/view architecture

A quick dive

Formalizing Qt's model/view

Customizing how model data is viewed

Filtering and sorting what's viewed

Keeping it portable – Qt's platform abstraction

Qt's OS and filesystem abstractions

Qt's container class abstractions

Taking a closer look at building and Main

Qt Creator's supported build systems

QMake

Qbs

CMake

What's all that in main(..)?

Summary

Questions

Managing the Overall Workflow

Technical requirements

Modernizing software development

Falling down the development cycle

Continuous Integration

Unit testing

Modern development cycle

Moving ahead without hardware

Layering the problem

Starting our BigProject

BigProject customer requirements

Starting the Qt project

Initial main window design

Wiring up the time display

Testing

Commit it

Mocking the hardware

A new requirement

Defining the interface

Implementing the mock

Injecting the mock

Wiring up the temperature display

Test it!

Summary

Questions

Further reading

Exploring GUI Technologies

Technical requirements

Two roads diverge

Qt Widgets

Programming widgets

Creating a widget with Qt Creator/Designer

Creating a widget by hand

Doing something new – QML

What is QML?

Developing a UI in QML

Revisiting some old friends

Hello from Qt!

Hello from QML!

Creating the project

Defining the window

Customizing the display

Using the Designer

The Form Editor

The Text Editor

The Library window

The Navigator window

The Connections window

The Properties window

Experimenting with the QML Designer

Comparing the technologies

What if you didn't have to choose?

New requirements for BigProject

Designing the UI

Creating the historical data form

Implementing the historical table

Adding the QtQuick (QML) chart

Adding the temperature history form to the UI

Providing data for the chart

Storing the last reading

Updating temperatureUpdate(..)

Catching newReading in the chart

Adjusting the .pro file

Reformatting the History page

Summary

Questions

Further reading

Adding More Features

Technical requirements

Keeping records

Defining the database structure

Interfacing to the database

Simplifying handling readings

Defining the TemperatureStorage class

Opening (and creating) the database

Closing the database

Saving data

Retrieving readings

Using a QSqlQuery

Using QSqlTableModel

Integrating the storage

Designing with state machines

Guess what marketing wants now?

Determining the states

Determining the conditions that cause transitions

Drawing it out

Qt's early state machine support

An easier way to make state machines

Using the state machine

Updating the UI

Creating an HVAC controller

Wiring in the HVAC state machine

Testing our simple thermostat

Handling more requirements!

Adding a new state

Adding an event to a state

Working with embedded states

Searching for a keyboard

Defining the input panel

Adding the input panel to the GUI

Solving a crash

Decoding the fix

Weaving a web of sockets

Implementing the embedded WebSocket server

Defining the WSReporter class

Implementing WSReporter

The constructor and destructor

Handling connects and disconnects

Sending the updated temperature

Wiring in WSReporter

Monitoring the Host

Considering IoT security

Authentication and encryption

Anti-playback

Implications on the BigProject

Summary

Questions

Further reading

Section 3: Deep Dive into Embedded Qt

Qt in the Embedded World

Technical requirements

Microcontrollers in embedded super PCs

Qt's place in the embedded world

Last word on hardware choices

Qt licensing and features

Open-source version

Commercial version

Qt's embedded options

Boot to Qt (B2Qt)

Qt Configuration Tool

Safety-critical display

Qt for Medical

Qt for Automotive

Qt for Automation

Qt for Device Creation

Remote objects

Qt UI development tools

Virtual keyboard

Summary

Questions

Exploring the IoT with Qt

Technical requirements

Examining the IoT and Qt

The IoT – a brief history

Where does Qt fit into the IoT?

Forecasting the weather using a Web API

Searching for a weather API

Implementing WeatherFetcher

What we need to know

Constructing WeatherFetcher

Requesting the current conditions

Handling the API response

Forcing a weather update

Setting the location and weather units

Starting and stopping WeatherFetcher

Making use of WeatherFetcher

Creating a WeatherFetcher instance

Displaying the weather

Setting the location and temperature inits

Testing and committing

Checking your results

Reading the temperature sensor in Qt

Installing the Sense HAT board

Why didn't you just plug in another USB power supply for the display?

Building the software support

RTMULib – the low-level interface

Creating a cross-compilation cmake file for the Raspberry Pi

Building RTMULib

Installing RTMULib on the target

Testing RTMULib on the target

Building QSensors for the Sense HAT

Testing QSensors for the Sense HAT

Reading the temperature in BigProject

Creating an ambient temperature sensor class

Wiring in the ambient temperature sensor

Testing the temperature reading on the host and the target

Publishing our status using MQTT

Building IoT extensions

Building Qt MQTT

Building Qt KNX

Using QtMQTT

Creating the MqttClient class

Implementing the MqttClient class

Implementing the constructor

Implementing our hostname and port setters

Connecting and disconnecting from a broker

Handling connection state changes and incoming messages

Publishing BigProject's status

Wiring in and setting up the MqttClient class

Starting and stopping the MQTT publication

Creating menu entries

Assigning actions to menu items

Testing the MQTT publication

Final words on MQTT

Summary

Questions

Further reading

Using More Qt-Related Technologies

Technical requirements

Saving settings

Searching for settings

Settings file formats

Using QSettings

Digging deeper into QVariant and meta types

Changes to MainWindow

Loading settings

Saving settings

Updating TemperatureSensorIF and its children

Fire it up and see whether it smokes!

Continuing with QSettings

Communicating using D-Bus

Basic D-Bus concepts

Qt's D-Bus support

Tools

Qt classes

Adding D-Bus the brute-force way

Adding D-Bus the tool-using way

Preparing the Target for our D-Bus to enable applications

Adding D-Bus to our project

Writing the C++ interface class you want to use with D-Bus

Generating XML from the class declaration

Making fixes to the XML

Generating the Adapter and Interface classes from the XML

Hooking up to D-Bus

Sending change notifications

Receiving settings changes

Testing our D-Bus code

Remote GUI

Preparing the Target

A simple GUI

Connecting the web GUI to BigProject using D-Bus

Adding the D-Bus interface code

Wiring in the D-Bus interface

QML code changes

Printing (PDF)

The basics

Adding printing to BigProject

Summary

Questions

Further reading

Section 4: Advanced Techniques and Best Practices

Debugging, Logging, and Monitoring Qt Applications

Technical requirements

Testing Qt applications

Code analysis

Clang analysis

Manually running Clang analysis

Code reviews

Active testing

Writing good tests

Hand testing

Automated testing

Preparing for testing

Qt testing

Basic tests

Covering the possibilities

Running the tests and viewing the results

Google Test

Checking code coverage

The traditional way

Testing doesn't have to be hard!

Debugging Qt applications

Old-school debugging

Working with the Qt Creator debugger

Examining threads

Debugging and the target firewall

Monitoring Qt applications

Logging the Qt way

Controlling the logging format

Controlling the logging destination

Using Valgrind

Function profiling

Analyzing for memory issues

Summary

Questions

Responsive Application Programming - Threads

Technical requirements

Examining Qt's different threading models

Simple threads

Using QThread

Running a QObject in its own QThread

Thread pools

Qt Concurrent

Running concurrent functions

Mapping, filtering, and reducing data

Mapping a function onto data example

Filtering and reducing data

Concurrent examples

QML WorkerScript

Solving problems with threads

Responsive GUIs

Image processing

Near real-time control

Overcoming cross-thread communication and synchronization

Synchronization

Mutexes and semaphores

Waiting with mutexes

Protecting data

Communicating between threads

Being careful mixing threads and Qt GUI

Summary

Questions

Further reading

Qt Best Practices

Technical requirements

Understanding the Why? of Qt

Choosing between C++ features and the Qt Way

Increasing efficiency in Qt

Don't make extra copies

Passing parameters

Hidden copies

Keep it DRY

Avoiding pointless initializations

Avoiding useless work

Using the best solution

Stay in one place

Letting Qt Creator help

Summary

Questions

Further reading

Appendix A: BigProject Requirements

Appendix B: Bonus Code - Simplifying Q_PROPERTY

Simplifying defining Q_PROPERTY()

Simplifying working with Q_PROPERTY items

Assessments

Section 1: Getting Started with Embedded Qt

Chapter 1 – Setting Up the Environment

Chapter 2 – Writing Your First Qt Application

Chapter 3 – Running Your First Application on Your Target

Section 2: Working with Embedded Qt

Chapter 4 – Important Qt Concepts

Chapter 5 – Managing the Overall Workflow

Chapter 6 – Exploring GUI Technologies

Chapter 7 – Adding More Features

Section 3: Deep Dive into Embedded Qt

Chapter 8 – Qt in the Embedded World

Chapter 9 – Exploring the IoT with Qt

Chapter 10 – Using More Qt-Related Technologies

Section 4: Advanced Techniques and Best Practices

Chapter 11 – Debugging, Logging, and Monitoring Qt Applications

Chapter 12 – Responsive Application Programming – Threads

Chapter 13 – Qt Best Practices

Other Books You May Enjoy

Leave a review - let other readers know what you think

Preface

Welcome to Hands-On Embedded Programming with Qt!

By means of the pages, examples, and projects in this book, you will get hands-on experience of developing a Qt application on an embedded target. Through the development of an overarching project, BigProject, you will learn about and gain experience with the many technologies that the Qt framework has to offer the embedded developer.

You will also be exposed to safe programming practices that will help you save time and prevent bugs in the field.

Who this book is for

This book is intended for software and hardware professionals with experience in a variety of different fields who are seeking to learn about embedded and IoT programming using the Qt framework. Whether you are new to embedded programming, a less experienced embedded programmer, or quite familiar with embedded development and are looking to add Qt to your toolbox, you will find something for you.

What this book covers

Chapter 1,Setting Up the Environment, covers the setup of the host and target environments we will be using for the rest of the book. It starts by specifying the host hardware we will be using for learning purposes. From there, it moves on to covering how to set up the host development environment with Qt and other tools. Cross-compiling Qt for the target environment and preparing the target operating system are also covered. Parts of this chapter can be completed without the need for the host.

Chapter 2, Writing Your First Qt Application, has been written so that you can continue learning without the target system. In this chapter, we'll write our first Qt program and execute it on the host. In the process, you will learn how to start Qt Creator; build a widgets-based Qt application; compile it for the host, run it, and even debug it; all from within the Qt Creator IDE.

Chapter 3, Running Your First Application on the Target, takes the application we wrote and ran on the host in Chapter 2, Writing Your First Qt Application, and focuses on running that application on the target. You will learn how to set up a Qt Creator kit that will allow you to simply select all the proper tools and settings to cross-compile, deploy, run, and debug on an embedded target. You will also be introduced to the problem of differing screen resolutions and sizes and how to easily solve it in Qt.

Chapter 4, Important Qt Concepts, starts laying the groundwork for the remainder of the book by exploring some of the basic, underlying concepts that are found throughout Qt. We will look at signals and slots, Qt's introspection system, the model/view architecture, and how Qt abstracts hardware and software platforms so that we can easily write code once and run it on many different systems.

Chapter 5, Managing the Overall Workflow, starts by looking at how we develop safe software systems with the highest possibility of success, both in terms of quality and time to market. From there, we start BigProject. We will work on this as we learn how to develop embedded software with Qt. As we move through the book, the mythical marketing and management teams reveal the new requirements of BigProject, just like they have done in real-world projects I have worked on. To overcome one of the first changes they make, we will learn about mocking.

Chapter 6, Exploring GUI Technologies, starts by examining the two different GUI technologies, widgets and Qt Quick/QML, which are available in Qt. As we finish up exploring the differences between them and the different ways in which they are developed, there are new requirements given to us for BigProject , leading us to learn how we can combine the two GUI technologies in a single application.

Chapter 7, Adding More Features, introduces a number of new requirements. In order to satisfy these requirements, we will learn how to interact with SQL databases using Qt, design state machines graphically in Qt Creator and have them automatically converted to C++ code, deploy a virtual keyboard, and use Qt's WebSocket support. Throughout this journey, we will be adding to BigProject. We will also look at the often overlooked world of IoT security, learning why it is important, and how we can find out more about it.

Chapter 8, Qt in the Embedded World, takes a step back and looks at Qt's place in the embedded world. We will learn how the computer and embedded markets have changed since Qt was first written. We will then examine how Qt is licensed and learn what we need to be careful of in terms of which license we develop and release our product under. We will then look at some of the commercial products Qt offers to make embedded development even easier, and even see some of the specific packages Qt has developed for targeted markets, such as medical, automotive, and safety-critical systems.

Chapter 9, Exploring the IoT with Qt, brings us to IoT. Here, we will learn how IoT and Qt fit together. After receiving yet more requirements from our mythical marketing and management teams, we will learn about accessing Web APIs from within BigProject, and how to interact using the MQTT IoT protocol. In between, we will learn about Qt's sensor support, and configure and build tools to allow the user to read the target's temperature, humidity, and pressure sensors within Qt.

Chapter 10, Using More Qt-Related Technologies, continues the theme of new requirements for BigProject and explains how we can fulfill them using Qt. In this case, we will learn how to save settings, perform inter-process communications using D-Bus, write a GUI that can be accessed from a web browser, and how to print to PDF files.

Chapter 11, Debugging, Logging, and Monitoring Qt Applications, teaches us various ways to test, debug, and monitor Qt applications. We will learn about different methods for verifying software, ranging from analysis to testing, and the tools that come with Qt Creator to help us do both of these. We will also look at using Google and the Qt Test frameworks and uncover and fix a couple of latent bugs in BigProject. We will then take a quick look at some old and new debugging tricks, and finish off learning about how we can use Qt's built-in logging system.

Chapter 12, Responsive Application Programming – Threads, dives into a fun topic—threading. In this chapter, we will learn about the different threading models that Qt supports and actually compare how they work on some sample problems. Speaking of problems, we will also look at the types of problems with which the threading models work. Finally, we learn how we can communicate between threads and safely synchronize multiple threads.

Chapter 13, Qt Best Practices, wraps up our learning. Over the course of the book, we have learned the Qt Way of doing things, and that has probably gotten you wondering, Why did they do that? To answer this question, we will look at just that question. We will then try to come up with some guidelines as to when we should be using modern C++11 (or later) features, and when we should be using the Qt approach. Finally, we will look at how to write efficient Qt code and learn about some of the powerful tools Qt Creator has incorporated into it to give you advice on how to improve the efficiency of your code.

Appendix A, BigProject Requirements, containsthe requirement list for BigProject.

Appendix B, Bonus Code - Simplifying Q_PROPERTY, contains macros that will make the Q_PROPERTY coding simpler.

To get the most out of this book

The reader is expected to have basic knowledge of C++. While some knowledge of C++11 is helpful, new features are explained when we come to them. You should also have experience with using Linux shell commands. You will also want to get an embedded target. For this book, we will be using a Raspberry Pi 3B+ with a couple of extra pieces of hardware. The details can be found inChapter 1, Setting Up the Environment.However, you can work through most of the first two chapters without having the hardware!

Download the example code files

You can download the example code files for this book from your account at www.packt.com. If you purchased this book elsewhere, you can visit www.packt.com/support and register to have the files emailed directly to you.

You can download the code files by following these steps:

Log in or register at

www.packt.com

.

Select the

SUPPORT

tab.

Click on

Code Downloads & Errata

.

Enter the name of the book in the

Search

box and follow the onscreen instructions.

Once the file is downloaded, please make sure that you unzip or extract the folder using the latest version of:

WinRAR/7-Zip for Windows

Zipeg/iZip/UnRarX for Mac

7-Zip/PeaZip for Linux

The code bundle for the book is also hosted on GitHub athttps://github.com/PacktPublishing/Hands-On-Embedded-Programming-with-Qt. In case there's an update to the code, it will be updated on the existing GitHub repository.

We also have other code bundles from our rich catalog of books and videos available athttps://github.com/PacktPublishing/. Check them out!

Download the color images

We also provide a PDF file that has color images of the screenshots/diagrams used in this book. You can download it here: https://static.packt-cdn.com/downloads/9781789952063_ColorImages.pdf.

Code in Action

To see the code being executed, please visit the following link:

http://bit.ly/2Jb2Yzv.

Conventions used

There are a number of text conventions used throughout this book.

CodeInText: Indicates code words in text, database table names, folder names, filenames, file extensions, pathnames, dummy URLs, user input, and Twitter handles. Here is an example: "Because we are using a Raspberry Pi 3B+, you will want to use the qt-raspberrypi3-2gb.img.xz file."

A block of code is set as follows:

void

MainWindow

::

on_pushButton_clicked

(){

QString

name

ui

->

lineEdit

->selectedT

ext

();

ui

->

label

->

setText

(

QString

(

"Nice

to

meet

you

%1!"

).

arg

(

name

));}

When we wish to draw your attention to a particular part of a code block, the relevant lines or items are set in bold:

//

find

the

sensor

and

start

it

m_sensor

new

QAmbientTemperatureSensor

(

this

);

m_connected

m_sensor

->

connectToBackend

();

m_sensor

->

start

();

Any command-line input or output is written as follows:

[On Host]$ # fetch the code

[On Host]$ cd ~/raspi

[On Host]$ git clone https://code.qt.io/qt/

qtknx

.git

[On Host]$ cd qt

knx

/

Bold: Indicates a new term, an important word, or words that you see on screen. For example, words in menus or dialog boxes appear in the text like this. Here is an example: "You can always jump back to the Welcome screen by hitting the Welcome icon at the top of the left-hand icon menu."

Warnings or important notes appear like this.
Tips and tricks appear like this.

Get in touch

Feedback from our readers is always welcome.

General feedback: If you have questions about any aspect of this book, mention the book title in the subject of your message and email us at [email protected].

Errata: Although we have taken every care to ensure the accuracy of our content, mistakes do happen. If you have found a mistake in this book, we would be grateful if you would report this to us. Please visit www.packt.com/submit-errata, selecting your book, clicking on the Errata Submission Form link, and entering the details.

Piracy: If you come across any illegal copies of our works in any form on the internet, we would be grateful if you would provide us with the location address or website name. Please contact us at [email protected] with a link to the material.

If you are interested in becoming an author: If there is a topic that you have expertise in, and you are interested in either writing or contributing to a book, please visit authors.packtpub.com.

Reviews

Please leave a review. Once you have read and used this book, why not leave a review on the site that you purchased it from? Potential readers can then see and use your unbiased opinion to make purchase decisions, we at Packt can understand what you think about our products, and our authors can see your feedback on their book. Thank you!

For more information about Packt, please visit packt.com.

Section 1: Getting Started with Embedded Qt

In this section, we will be learning how to set up an embedded development environment. In Chapter 1, Setting Up the Environment, we will go over the software setup for our host and target machines and learn what hardware you will need as we move forward. In Chapter 2, Writing Your First Qt Application, we will focus on setting up and running our first Qt application on the host system. We won't be using the target system yet, so the host system can be completed while you are waiting for the target to arrive. In Chapter 3, Running Your First Application on the Target, we will take the application we wrote in Chapter 2, Writing Your First Qt Application, and run it on the target.

The following chapters will be covered in this section:

Chapter 1

,

Setting Up the Environment

Chapter 2

,

Writing Your First Qt Application

Chapter 3

,

Running Your First Application on the Target

Setting Up the Environment

Did you ever buy something marked Some Assembly Required only to get it home and find out Some actually means several hours of work and that the tools you need aren't included? I feel guilty, because this chapter should be labeled Some Assembly Required, but at least I will help you to find all of the free tools you need.

In this chapter, we will look not only at getting the software tools, but also getting the hardware set up and working toward getting the best experience with the rest of this book. We will walk through the basic setup of the Qt toolchain, embedded compilers, and reference hardware.

The following topics will be covered in this chapter:

Creating our embedded environment

Preparing the host machine compiler

Building Qt for the target

Technical requirements

The following hardware will be needed in order to derive the most from this chapter and the rest of this book:

A target device (Raspberry Pi 3B+) with supporting hardware. See the

Embedded Hardware and Firmware Setup

section for more information.

A host development PC running Ubuntu 16.04 or higher. This can be running directly on a PC or in a VM with network access. Other Linux distributions may work, but this book is written for Ubuntu. (I am running Ubuntu 18.10 on dedicated hardware.) You will need the following access rights for your account on the host:

Administrative (or root) privileges for installing software on your development PC are needed.

A web browser (Chrome is recommended) is required.

Internet access is necessary.

The following tools should be configured and working on the host:

ssh

rsync

scp

tar

xz

bzip2

g++

patch

The Host PC must be connected to a network that can also connect to the target device.

The Host PC must be able to read/write micro SD cards. You will want a fast SD card reader.

Additionally, this book assumes that you have at least a basic grasp of the following technologies:

Installation of distribution provided software packages on your development PC

A basic understanding of how to use Linux, including how to make files executable, run a program, edit a text file without a GUI, and safely reboot it

C++11 programming and debugging

The code samples for this chapter can be found at https://github.com/PacktPublishing/Hands-On-Embedded-Programming-with-Qt/tree/master/Chapter01.

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:

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.

Next, connect an Ethernet cable to the Raspberry Pi.

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.

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.

The screen will briefly display the Yocto logo as it boots then come up with a login prompt.

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:

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

Once the tarball has been downloaded, untar and configure it to install in

/usr/bin

:

[On Target] $ ./configure --prefix=/usr

You can now build and install it, as follows:

[On Target] $ make && make install

Preparing the host machine

In this section, we will look at setting up the Linux host PC so that we can easily develop Qt applications.

Installing Qt

Qt comes in two basic licenses—Commercial and Open Source. We will be using the Open Source version.

Projects developed with the Open Source version of Qt must comply with the applicable GPL and LGPL licenses.

Qt can be download from https://qt.io/dowownload. Make sure to download the Linux version of the online installer for the Open Source version.

You might be wondering why we don't use the version of Qt already installed or installable from your Linux distribution. The answer is quite simple—to avoid confusion caused by different versions of Qt and its tools. Each version of each Linux distributions tends to come with a different Qt version. By downloading Qt for ourselves, we ensure that we are working with the same version and tools.

Once downloaded, make the installer executable (chmod +x <file>) and then launch it.

This book is written for Qt 5.12.0 that's been installed in ~/Qt, along with Qt Creator. You can change the installation directory, but you will have to also adjust some of the steps that are provided.

We only need some of the Qt components, but you can install more if you like. From the Qt 5.12.0 section, select at least the following components from the Qt sub-menu:

Desktop gcc 64-bit

Sources

Qt Charts

Qt Virtual Keyboard

Qt WebGL Streaming Plugin

Qt Debug Information Files

Consider the following diagram for the preceding components:

Also, be sure to install the latest version of Qt Creator (4.8.0 at the time of writing).

Just these few items pose a fairly large download. If you have a slow internet connection, you may want to find something else to do while it completes.

Setting up the cross compilation environment

There are several steps to setting up the cross compilation environment. We will put everything into the ~/raspi directory on the host so that you can create it.

Installing the cross compilation tools

Since the Raspberry Pi uses an ARM processor, we will need to install a cross compilation tool chain. A cross compile toolchain allows the host to build code that will run on a Target, even if the processor and possibly the OS do not match. A typical toolchain contains a compiler, linker, debugger, and other tools that run on the host, but generate code for the Target. You could think of it almost like a really cool translator that allows you to write a book in English and have it magically appear in Mandarin when it's done.

While we could build the cross compilation tools from sources, it is a lot easier to download pre-built binaries from https://github.com/raspberrypi/tools. We will want to put the tools in ~/raspi/tools. You can either use Git to pull them down or download the ZIP file.

To use Git, simply clone the directory, as follows:

[On Host] $ cd ~/raspi

[On Host] $ git clone https://github.com/raspberrypi/tools

You can grab the ZIP file from https://codeload.github.com/raspberrypi/tools/zip/master. Once you've download the ZIP file, extract the tools-master directory to ~/raspi/, then rename tools-master to tools:

[On Host] $ cd ~/raspi

[On Host] $ unzip tools-master.zip

[On Host] $ mv tools-master tools

Preparing for debugging

In order to successfully debug applications on the Target, we need to have a multi-architecture version of gdb (the debugger) installed. On Ubuntu, you can install it easily using apt:

[On Host] $ sudo apt install gdb-multiarch

Accessing the Target's root directory on the host

Cross compiling for the Linux target is best done when the host PC has access to parts of the root filesystem of the Target so that the proper includes and libraries can be accessed. There are a couple of different ways of doing this.

The first method is to share the filesystem between the host and target PC by remote mounting it from one system to the other. This is typically done using NFS.

The other method is by cloning the necessary parts of the target filesystem on the host. There are some definite advantages to cloning the filesystem, as follows:

The Target can be run independently of the host. This is perfect for demos or when the always available network is down.

The Target doesn't need to be present when compiling code for it. This seems to happen to me quite often when the software team grows and new Target hardware is limited. You will still need a Target at some point to transfer the code to it, just not while building.

For our purposes, we will clone the Target filesystem.

The required pieces of the root filesystem from the Target will be stored in ~/raspi/sysroot. RSync will be used to pull the copy:

[On Host] $ cd ~/raspi

[On Host] $ mkdir sysroot sysroot/usr

[On Host] $ rsync -avz root@raspberrypi:/lib sysroot

[On Host] $ rsync -avz root@raspberrypi:/usr/include sysroot/usr

[On Host] $ rsync -avz root@raspberrypi:/usr/lib sysroot/usr

The next step is to fix the symbolic links in

sysroot

. On the Target, they refer to absolute paths, but on the Host, they will need to refer to relative paths within

sysroot

. Once more, a script has been provided to take care of this for us, which can be found at

https://raw.githubusercontent.com/riscv/riscv-poky/priv-1.10/scripts/sysroot-relativelinks.py

. You can use

wget

to fetch it. Next, make it executable.

Run it by providing the location of the host copy of the Target's root filesystem:

[On Host] $ cd ~/raspi

[On Host] $ wgethttps://raw.githubusercontent.com/PacktPublishing/Hands-On-Embedded-Programming-with-Qt/master/Chapter01/sysroot-relativelinks.py

[On Host] $ chmod +x sysroot-relativelinks.py

[On Host] $ ./sysroot-relativelinks.py sysroot

Building Qt for the Target

While Qt can sometimes be obtained for a specific target, the version we are running isn't available for the Raspberry Pi. Instead, we will look at how to build Qt from the sources. At first, it may seem like a daunting task, but it really is straightforward. Let's get to it:

Before we start building Qt, we are going to make a backup copy of the source directory using

tar

. Open Command Prompt and

cd

to the installation directory for Qt 5.12.0. Next, tar up the

Src

directory, as follows:

[On Host] $ cd ~/Qt/5.12.0

[On Host] $ tar jcvf qt-5.12.0-src.tar.bz2 Src

Always keep the distribution sources untouched and don't build in the installed source directory. Use a copy of the directory instead. That way, should something happen, you won't have to re-download the sources.

Now, extract the tarball into

~/raspi/Src

and rename it

~/raspi/qt-5.12.0-src

:

[On Host] $ cd ~/raspi