Qt Quick with PyQt5 on Raspberry Pi

QtLogoThe prime motivation for me to go through Qt licensing documentation and installing Qt Creator IDE was to explore the new UI infrastructure introduced in Qt 5 under the umbrella of “Qt Quick“. As far as I can tell, this is an entirely different system for creating user interface of a Qt application. Built with modern ideas such as OpenGL graphics acceleration for animation effects and UI layout declared with a text-based markup language QML (probably stands for Qt Markup Language.)

Up to this point my experience with building graphics user interface in Qt was with the QWidget-based infrastructure, which has a long lineage in past editions of Qt. Qt Quick is new for Qt5 and seem to share nothing in common with QWidget other than both a part of Qt5. Now that I’ve had a bit of QWidget UI work under my belt I wanted to see what Qt Quick has to offer. And this starts with a smoke test to make sure I could run Qt Quick in the environments I care about: Python and Raspberry Pi.

Step 1: Qt Creator IDE Default Boilerplate.

Once the Qt Creator IDE was up and running, I followed the Qt Quick tutorial to create a bare bones boilerplate Qt Quick application. Even without any changes to the startup boilerplate, it reported error messages complaining of missing modules. Reading the error message, I looked at the output of apt list qml-module-qtquick* and installed the ones that sound right. (From memory:qml-module-qtquick2qml-module-qtquick-controls2, qml-module-qtquick-templates2, and qml-module-qtquick-layouts)


Once the boilerplate successfully launched, I switched languages…

Step 2: PyQt5

The next goal is to get it up and running on Python via PyQt5. The PyQt5 documentation claimed support for QML but the example on the introductory page doesn’t quite line up with the Qt Creator boilerplate code. Looking at the Qt Creator boilerplate main.cpp for reference, I translated the application launch code into main.py. This required sudo apt install python3-pyqt5.qtquick in addition to the python3-pyqt5 I already had. (If there are additional dependencies I forgot about, look for them in the output of apt list python3-pyqt5*)


Once that was done, the application launched successfully on my Ubuntu desktop machine, albeit with visual appearance very different from the C++ version. That’s good enough for now, so I pushed these changes up to Github and switched platforms…

Step 3: Raspberry Pi (Ubuntu mate)

I pulled the project git repository to my Raspberry Pi running Ubuntu Mate and tried to run the project. After installing the required packages, I got stuck. My QML’s import QtQuick 2.7 failed with error module "QtQuick" version 2.7 is not installed The obvious implication is that the version of QtQuick in qml-module-qtquick2 was too old, but I couldn’t figure out how to verify version number is indeed the problem or if it’s a configuration issue elsewhere in the system.

Searching on the web, I found somebody on stackoverflow.com stuck in the same place. As of this writing, no solution had been posted. I wish I was good enough to figure out what’s going on and contribute intelligently to the discussion!

I don’t have a full grasp of what goes on in the world of repositories ran by various Debian-based distributions, but I could see URLs flying by on-screen and I remembered that Ubuntu Mate pulled from different repositories than Raspbian. I switched to Raspbian to give that a shot…

Step 4: Raspberry Pi (Raspbian Stretch)

After repeating the process on the latest Raspbian, the Qt Quick QML test application launches. Hooray! Whether it was some configuration issue or out of date binaries we don’t know yet for sure, but it does run.

That’s the good news. Now the bad news: it launches with the error:

JIT is disabled for QML. Property bindings and animations will be very slow. Visit https://wiki.qt.io/V4 to learn about possible solutions for your platform.

And indeed, the transition between “First” and “Second” tabs were slow. Looking on the page that it pointed to, it looks like the V4 JavaScript engine used by Qt for QML applications does not have JIT compilation for Raspberry Pi’s ARM chip. That’s a shame.

For now, this excludes Qt Quick as a candidate for writing modern responsive user interfaces for Raspberry Pi applications. If I want to stick with Qt and Python, I’m better off writing Qt interfaces in the old school QWidget style. We’ll keep an eye on this – maybe they’ll add JIT support for Raspberry Pi in the future.

(The source code related to this blog post are publicly available on Github.)

Raspberry Pi Pin Initial States are a Consideration For Machine Control

As an intermediate step towards controlling the thermoforming machine with the Raspberry Pi, we populated a breadboard with some components we planned to use. A Raspberry Pi could only source a total of 50mA of power across all the IO pins, so we had it switch circuits on/off via opto-isolators that required far less current to activate. We started by using these opto-isolators to control power to LEDs. Just to see how it works and make sure nothing unexpected occurs before we start hooking up bigger things.

This proved to be wise, as it exposed some Raspberry Pi behavior we did not expect. When the Pi was powered-up, some of the LEDs glowed dimly. They’re not full bright, but they’re definitely not dark, either. Once the control program starts up and all pins are initialized to off, they go dark as expected. But there’s something going on between initial power-on and when the control program starts running.

This was important to chase down because we don’t want the machine relay to close when we’re not expecting them to close. Even worse if it occurs while the system is powering up and components are not yet in known good states. Making this an important consideration in designing our system.

A bit of web searching confirmed this startup behavior was noticed and investigated by a lot of people looking at various parts of the system. The answer was most succinctly answered by a post on the Raspberry Pi subsection of StackExchange: In the peripherals manual for the BCM2835 chip at the core of the Raspberry Pi, the power-on initial states are explicitly stated: All IO pins are configured to be input and not output. Furthermore, pins 0-8 are set with pull-up to 3.3V and pins 9-27 are pulled-down to 0V.

Looking back on the breadboard, we could confirm the explanation matches the observed behavior. The dimly lit LEDs were controlled by opto-isolators that were, in turn, connected to Raspberry Pi pins 5 and 6. None of the other isolators were controlled by pins in the 0-8 range. Since opto-isolators required so little current to operate, the weak pull-up on a pin set to input was sufficient to partially activate the circuit.

Once the cause was determined the solution was simple: move all output control out of the 0-8 range of pins. These pins would be fine for input, so the task of reading the position of a limit switch was moved to pin 5.

The resulting breadboard is visible in the attached image, and the code was changed to match the new pin assignments in this commit. After these changes, we observed no partially lit LEDs which also hopefully means no unexpected relay activity when we hook it up to the machine.


Setting Up Raspberry Pi GPIO Pins For Device Control

A rough draft of the thermoformer touchscreen control panel application, witting in Python with the Qt UI framework, is now up and running. Now it is time to see how it works controlling some physical hardware. We’re going to build up to this in steps on the way towards actually controlling the thermoform machine. The first step is to have the Pi light up some LEDs as commanded by the control panel application.

I had been playing with a Microchip PIC16F18456 earlier, which can drive LEDs effortlessly. Each pin can handle 50mA which is more than enough to drive LEDs as they typically require no more than 20mA each. I had assumed the Pi would be even more capable with its onboard voltage regulators, but I thought it’d be better to check just to be safe. I’m glad I did! It turns out the pins on the Raspberry Pi has significantly lower power capability than the pins on the PIC16F18345.

The consensus on the Raspberry Pi forums says the limit is 16mA per pin, and 50mA total across all pins. A bunch of LEDs would quickly exceed the 50mA total cap. Given this, we’re going to take two baby steps at once.

We’ve known we couldn’t drive the thermoforming machine directly with Pi. And even if we could, a direct connection is not the best idea. The plan had always called for the use of opto-isolators to keep some separation between the delicate low-power circuitry on the Raspberry Pi chip and the high-power components of the machine. I just didn’t expect that bright LEDs to qualify as “high power” in this context. But since they are, we’re going to use opto-isolators to build the LED proof of concept.

The current design for the control has 9 outputs to relays, and 1 input from a limit switch. For the outputs we’re starting with the Vishay 4N32 chip to see how they work. For input, we wanted a chip that works in the reverse direction, and we’re starting with the Toshiba TLP2200. With the help of a Raspberry Pi I/O breakout board we could hook everything up on a breadboard for the first test.


Learning Timers: Qt QTimer and Python threading.Timer

QtLogoWhen I interfaced my PyQt application to the Raspberry Pi GPIO pins, I ran into a classic problem: the need to perform input debouncing. The classic solution is to have the software wait a bit before deciding whether the input change is noise to be ignored or not. A simple concept, but “wait a bit” can get complicated in the world of GUI programming. When writing simple programs, we can probably get away with a literal wait by “going to sleep” for a little bit. But we don’t have that luxury in the world of GUI programming – going to sleep would freeze everything in the program. In general, users do not appreciate their UI becoming frozen and unresponsive.

Python LogoThe solution: a timer. In a Windows application, the programmer can use the operating system timer and do their “after waiting a bit” tasks in response to the WM_TIMER message. I went looking for the Qt equivalent and found several timer-related features. QTimer, QBasicTimer, and QObject::startTimer(). Thankfully, the documentation also provided an overview describing how they differ. For debounce purposes, the most fitting mechanism is a single-shot timer.

Unfortunately, when I tried to use it, I received an error message telling me I could only use Qt timer objects from code launched with QThread. Which apparently wasn’t the case with code running under the context of a QWidget within a QApplication.

I had hoped the Qt timers, working off of the QApplication event queue, would stay on the UI thread. But it appears they have to have their own QThread. I could put in more time to figure out how to get Qt timers to work, but I decided to turn to Python library instead. If I have to deal with multi-threading issues anyway, there’s no reason to avoid Python’s Timer object in the threading library.

It does mean I had to review my code to make sure it would be correct even if called from multiple threads. Since the important state are the status of the GPIO pins, they are handled by the pigpio library and the code in my app should be fairly safe. I do set a flag to avoid creating multiple Timer objects in the case of input bounce. If I cared about making sure I only ever create a single Timer, this flag should be protected against cross-thread access. But reviewing the code I decided it was OK if a few Timer ends up being created – the final result of reading the GPIO pin should still be the same even in the case of multiple Timers doing duplicate work.

(The project discussed in this blog post is publicly available on Github.)

Qt + Python = GUI for Raspberry Pi Project

Since the mission of the Raspberry Pi foundation is to “put the power of digital making into the hands of people all over the world” there is no shortage of options for programming the Pi. We have at our disposal many choices in programming languages, each with multiple application frameworks, and a large community of Raspberry Pi users for support.

QtLogoFeeling overwhelmed with options, I chose the one that best lines up with my long-term goal of getting up and running on ROS. The ROS plug-in architecture for operator GUI is rqt, based on Qt. And like much of ROS, the user has the option of working with rqt in either C++ or Python. Since I had started dabbling with ROS in Python before getting distracted, I thought the combination of Qt and Python would be a good direction to go.Python Logo

The Qt framework itself is aimed at C++ developers, and its documentation is written accordingly. Fortunately there are translation layers (language bindings) for Python. The one that seems to be the most mature is PyQt with a long list of resources, books, and online tutorials.

The next decision to make is which version to start learning. Browsing through the resources, it looks like Qt 4 is the mainstream version and Qt 5 is the new shiny. Since ROS is still in the midst of transitioning from Python 2 to Python 3, I assume rqt would be relatively old school as well. No matter which one I choose, there’ll be differences I have to tackle whenever I get around to diving deep into ROS. On the assumption that the latest and greatest versions are also the most polished (an assumption based on how Python 3 cleaned up a lot of architectural messiness of Python 2) I thought I’d start learning with the latest releases and make adjustments later as I need to.

So: Qt 5 and Python 3 it is, with the help of PyQt5 binding. Which is easily installed on a Raspbian Stretch system by installing the packages “pyqt5-dev” and “pyqt5-dev-tools”.

Si7021 Sensor to Raspberry Pi to PIC to LED

I started this I²C project by creating a simple I²C-controlled LED display using a PIC micro controller. Then I found an I²C Python Raspberry Pi library to communicate with my PIC. The next addition to the mix should be an I²C device I did not create, to verify my code plays well with others.

While talking about I²C at Tux-Lab, one of the past projects came up: a breakout board for the Si7021 temperature and humidity sensor. A unit was brought out for show during this conversation. This particular unit was built a few years ago and has yet to be incorporated into a project.

A web search confirmed this is quite a popular sensor. Lots of sample code and projects. Both Adafruit and Sparkfun sell breakout boards similar to the one Tux-Lab created. And the sensor is also part of the popular Sense HAT. I looked at the data sheet and thought it looked like a good place to start. Best of all, a search for existing code found one in the “Examples” section of the Pi GPIO library I wanted to learn anyway.

I asked to borrow that unused breakout board and added it to my bread board. (Visible in the lower-left of the attached picture.) The additional wiring was trivial, most of the work was on the software side learning Python basics. It didn’t take terribly long to create a rudimentary thermometer. My Python code running on the Pi uses I²C to query the Si7021 for temperature, converted that data for display, and sent that data out the same I²C bus to the PIC.

With the work and learning I’ve put in, I now have an overly complicated contraption that tells me my work space temperature is 75.18 degrees Fahrenheit.

No decimal point on the LED because I ran out of pins on the 18-pin PIC16F1847 chip.


Exploring Options For Raspberry Pi I²C Programming

i2cbuslogoNow that I have a rudimentary I²C implementation up and running on my PIC, it’s time to figure out how I’ll control it from code running on a Raspberry Pi. Which means it’s time for this novice to go bumping around in the dark looking for a place to start.

The first thing I looked at was the Raspberry Pi Sense HAT. I bought one along with my Raspberry Pi and it was a fun little thing to play with, learning some basic Python along the way. The Sense HAT communicates with the Pi via I²C. I found the Github repository where the source code for the SenseHat module is published, but my Python knowledge is too thin to trace to their low-level I²C communications code.

The next thing I thought of was the Adafruit PWM/Servo HAT, which I also purchased for experimentation. Looking at that HAT’s tutorial and the Adafruit I²C tutorial, I found their I²C library which worked well enough for me to do rough tests of my I²C code running on the PIC. Adafruit code seem to be Python 2 specific with no Python 3 version. This is not an immediate problem because I intend to use ROS which is also on Python 2, but I wanted something with broader (more than Adafruit) support and more future-proofing.

On the logic of “If there’s something on Adafruit, there’s probably also something on Sparkfun.” I found the SparkFun Raspberry Pi I²C tutorial which uses the wiringPi library to access the Pi’s GPIO pins. This library looks pretty popular, and it includes an I²C library. The downside is that wiringPi is focused on C programs. A Python interface layer exists but not maintained by the owner.

raspberry-pi-logoI felt there must be another way since the Raspberry Pi is focused on education and making technology accessible. A little more web searching paid off: The pigpio library. It is the default option for GPIO control in Raspberry Pi documentation. Built into recent builds of Raspbian so it is a part of the stock Raspberry Pi. I can interface with it in C, Python 2, Python 3, or even the command line utility. Source code is public if I ever wanted to dig deeper.

This looks like the best option. I’ll start using it and see how far I get.

Powering the Raspberry Pi 3 With MP1584 Voltage Step-Down Converter

The Raspberry Pi 3 is a very impressive piece of hardware for the price, but it has its flaws. One challenge is supplying power to a Pi 3. Like all the Pi boards, power is supplied via a standard micro USB plug. This implies the Pi only needs USB level power with its specified maximum of 0.5 amp @ 5 volts = 2.5 watts. In reality, this USB port is abused beyond the specified range. The Raspberry Pi foundation recommends the power supply for a Pi 3 should supply up to 2.5 amp @ 5 volt = 12.5 watts. Five times the USB specification maximum.

None of the USB power sources I already had could handle this workload. I originally had ideas about running a Pi 3 off of a portable USB charger, but that failed under the vastly greater power draw. I went looking online for solutions.

I needed an efficient DC to DC voltage regulator that can handle the maximum power draw of a Raspberry Pi 3 without consuming a lot of power itself. Since the voltage of a battery changes as it drains, the converter needs to handle a range of input voltages while holding the output voltage steady.

The MP1584 chip from Monolithic Power Systems fit the bill, but I didn’t want to deal with a tiny surface mount IC, nor do I have the skill to design the supporting circuit required. Consulting with a few electronics hardware hobbyists, I got the recommendation to take the reference design out of the datasheet and build that.

And then, an even better recommendation: If it’s a popular chip, and its reference design is good enough, somebody would have mass-produced it and put it on Amazon. And indeed, they have. A lot of vendors, in fact, from all around the world.

I scrolled through a few of the listings but didn’t really have a good feel on how to judge one vendor against another. So I took the easy way out: I clicked on the “Amazon’s Choice” link to this offering.

Once the module arrived, I soldered battery connectors to the input and a micro USB plug to the output. I adjusted the output voltage to 5 volts, and connected everything to power up my Raspberry Pi 3.


So far it has worked very well. The Raspberry Pi 3 stayed running through tasks that demanded extra power, that would previously trigger a low-power brownout with my existing USB power sources. The output voltage held steady as the battery drained.

Functional, inexpensive, and I didn’t even have to deal with surface mount components! This was a win.


Fusion 360 vs. Onshape: Raspberry Pi

raspberry-pi-logoAnd now for something completely silly: let’s look at how our two competing hobbyist-friendly CAD offerings fare on the hobbyist-friendly single-board computer, the Raspberry Pi.

(Spoiler: both failed.)

Raspberry Pi

I have on hand the Raspberry Pi 3 Model B. Featuring a far more powerful CPU than the original Pi which finally made the platform usable for basic computing tasks.

When the Raspberry Pi foundation updated its Raspbian operating system with PIXEL, they switched the default web browser from Epiphany to Chromium, the open-source fork of Google’s Chrome browser. Bringing in a mainstream HTML engine resulted in far superior compatibility with a wider range of web sites, supporting many of the latest web standards, including WebGL which is what we’ll be playing with today.

Autodesk Fusion 360

Fusion 360 is a native desktop application compiled for Windows and MacOS, so we obviously couldn’t run that on the Pi. However, there is a web component: Fusion 360 projects can be shared on the Autodesk 360 collaboration service. From there, the CAD model can be viewed in a web browser via WebGL on non-Windows/MacOS platforms.

While such files can be viewed on a desktop machine running Ubuntu and Chromium, a Raspberry Pi 3 running Chromium is not up to the task. Only about half of the menu bar and navigation controls are rendered correctly, and in the area of the screen where the actual model data should be, we get only a few nonsensical rectangles.


Before this experiment I had occasionally worked on my Onshape projects on my desktop running Ubuntu and Chromium, so I had thought the web-based Onshape would have an advantage in Raspberry Pi Chromium. It did, just not usefully so.

In contrast to A360’s partial menu UI rendering, all of Onshape’s menu UI elements rendered correctly. Unfortunately, the actual CAD model is absent in the Raspberry Pi Chromium environment as well. We get the “Loading…” circle and it was never replaced by the CAD model.


Sorry, everyone, you can’t build a web-based CAD workstation with a $35 Raspberry Pi 3.

You can, however, use these WebGL sites as a stress test of the Raspberry Pi. I had three different ways of powering my Pi and this experiment proved enlightening.

  1. A Belkin-branded 12V to 5V USB power adapter: This one delivered good steady voltage at light load, but when the workload spiked to 100% the voltage dropped low enough for the Pi to brown out and reset.
  2. A cheap Harbor Freight 12V to 5V USB adapter: This one never delivered good voltage. Even at light load, the Pi would occasionally flash the low-voltage warning icon, but never low enough to trigger a reboot. When the workload spiked to 100%, the voltage is still poor but also never dropped enough to trigger a reset. Hurray for consistent mediocrity!
  3. An wall outlet AC to 5V DC power unit (specifically advertised to support the Raspberry Pi) worked as advertised – no low-voltage warnings and no resets.