Skip to content

Blog

Printing Custom Qt Types with qDebug()

When you define your own C++ types for a Qt application, you want to print their values with qDebug(), qWarning() or qCritical() eventually.

auto frame1 = QCanBusFrame{0x18ef0201U, QByteArray::fromHex("018A010000000000")};
qDebug() << "frame1 =" << frame1;

The C++ compiler will complain with this error message:

error: no match for ‘operator<<’ (operand types are ‘QDebug’ and ‘QCanBusFrame’)

The error message tells you to write your own output operator for the QDebug stream and for QCanBusFrame.

A custom C++ type that wants to play nicely with Qt should always define a QDebug output operator. Even the developers of the Qt library seem to forget it sometimes, as the example of QCanBusFrame shows.

Read More »Printing Custom Qt Types with qDebug()

Lessons from Six Years as a Solo Consultant

The beginning of this month marked my sixth anniversary of becoming a solo consultant. I don’t regret my decision and cannot imagine ever giving up solo consulting. I was essential in the implementation of some really interesting projects like infotainment systems for cars and driver terminals for sugar beet and forage harvesters. The income from these projects gives me the financial freedom to enjoy life more than ever before.

I took my anniversary as the cause for reflecting about what I should have done differently. I learned three main lessons.

  • Hourly billing runs against the best interest of your customers. As a solo consultant, you have no interest in becoming more productive. The longer hours you work the higher your income. You can only change this, if you Don’t Bill by the Hour but charge a value-based fee.
  • Charging customers for the value you provide becomes much simpler if you have a strong brand. A strong brand will Make Potential Customers Call You. You don’t have to search for projects any more, but projects will find you.
  • Productised Services are part product and part service. The product part is the same for all customers, whereas the service part is specific to each customer. You maximise your profit by minimising the time you spend on the service part.

I will heed the conclusions drawn from these lessons and implement them step by step. How about you?

Read More »Lessons from Six Years as a Solo Consultant

Speaking CAN: Write Buffer Overflow

In the first post of the Speaking CAN series, we learned how the terminal sends a read-parameter request to the ECU and how the ECU sends a response with the value of the parameter back to the terminal. This works fine, as long as the terminal does not send too many requests too fast.

We set the size txqueuelen of the write or TX buffer to 10, which is the default for many Yocto-based Linux systems. If the terminal writes, say, 50 requests to the CAN bus without any pause, we’ll see several error messages No buffer space available in the log window of the terminal. The terminal caused an overflow of the write buffer in the CAN controller.

If we have a request-and-response scenario, the terminal can wait for the response, before it sends the next request. If the response does not arrive within a certain time, the terminal flags an error.

Avoiding a write buffer overflow becomes more difficult, if the terminal sends out messages without expecting a response or if the terminal expects a response only every, say, 200 messages (e.g., an acknowledgement how many messages the ECU has received). The solution is to configure the CAN controller of the terminal to receive its own messages.

Read More »Speaking CAN: Write Buffer Overflow

Speaking CAN: Request and Response

Controller Area Networks (CANs, for short) are used for the communication between electronic control units (ECUs) in cars, trucks, tractors, harvesters, construction machines, packaging lines and e-bikes. Qt provides the Qt CAN Bus API as part of its QtSerialBus module. Qt CAN Bus provides a clean and simple API to connect to a CAN bus, to send and receive CAN frames over the CAN bus.

When we build an HMI application to control a machine, we need a lot more functionality than the Qt CAN Bus API should offer. The HMI application must not send CAN frames too fast to avoid buffer overflows in the CAN controller. When the HMI application receives, say, more than 200 CAN frames per second and tries to display the changes, it will freeze. The HMI application must be able to recover from CAN bus errors. We do not want to write the code for serialising and deserialising thousands of CAN messages manually, but want to generate this code automatically.

I’ll show solutions to these problems in a loose series of blog posts called Speaking CAN. In this first post, I’ll explain how an HMI application running on a display computer retrieves the value of a parameter from an ECU. The terminal sends a request to the ECU over CAN and receives a response from the ECU over CAN.

Read More »Speaking CAN: Request and Response

Using Qt under LGPLv3

At Qt Day 2019 in Florence, Italy, I gave a talk Using Qt under LGPLv3. In the first part The obligations of Qt LGPLv3: made understandable, I explain in detail, how you must provide the source code, the license texts, the copyright notices, any modification notices and the installation information. You don’t have to provide the installation information for B2B products like driver terminals in commercial vehicles, industrial devices and medical devices in hospitals. In other words, you don’t have to satisfy the anti-tivoisation rule for B2B products.

Read More »Using Qt under LGPLv3

Yocto Builds with CROPS Containers

In a recent post Using Docker Containers for Yocto Builds, I suffered an episode of NIHS (not-invented-here syndrome). I wrote a Dockerfile for Yocto builds. Stefan Agner pointed out in his comment that the CROPS project provides ready-made containers for Linux distributions like Ubuntu, Fedora and others. The crops/poky-container enables us to start our first Yocto build within minutes.

Read More »Yocto Builds with CROPS Containers

Running Neural Networks on Microcontrollers

3D face recognition, voice control and image recognition of faulty or fake parts were all the rage at Embedded World 2019. The trend towards performing these applications offline – without access to powerful compute servers in the cloud – was obvious. However, these applications require powerful CPUs with equally powerful GPUs to run predictions on deep neural networks.

I was interested in solutions that run (deep) neural networks (NNs) on microcontrollers (MCUs). And, Embedded World didn’t disappoint! Renesas showed how to predict motor failure by monitoring current and vibration. STMicroelectronics had a demo counting the cars driving by using the characteristic sound of the Doppler effect. That’s what I would call the “edge”!

Read More »Running Neural Networks on Microcontrollers

Using Docker Containers for Yocto Builds

We want to build a custom Linux image with Yocto for the Raspberry Pi 3 model B (BCM2837). The Linux image contains a very simple Internet radio application using Qt 5.11 and the eglfs graphics backend. Our colleagues shall be able to repeat the build easily – now, in three years and even in ten years.

I’ll explain why Docker is an excellent choice to build custom Linux images and give you a step-by-step guide how to do it. At the end of the post, you will be able to run a simple Internet radio on a custom Linux image on a Raspberry Pi 3.

Read More »Using Docker Containers for Yocto Builds