Skip to content

Burkhard Stubert

What’s Wrong with Multiple Display Computers in Driver Cabins?

Three cabins with 2-4 display computers each.
Figure 1. Top left: Claas cabin with three terminals. Top right: Agco cabin with two terminals. Bottom: Continental concept cabin with four terminals.

The top row shows the status quo. Two or three display computers (a.k.a. terminals) are normal. Even four display computers are not unusual. The bottom row shows the cabin of the future with four display computers. The display computers at the left and right beam show the videos from the wing mirror cameras. The display computer in the middle is the instrument cluster. The small display computer on the right-hand side shows additional information. It would be bigger in a harvester.

Let us assume for simplicity that the cabin is equipped with two display computers, which have identical hardware and nearly identical software – except for the main application. When sourced from low-volume, high-customisation electronics manufacturing services (LVHC-EMS), the two display computers, the telematics unit and a switch will cost roughly 2750 Euros for 200 machines.

We will bring down the costs to 2350 Euros, if we replace the two display computers by one computer with two displays. The computer doesn’t have a display and the displays don’t have a computer inside. The telematics unit is folded into an M.2 or PCIe card, which is plugged into a slot of the computer.

We will reduce the costs by another 200 Euros to 2150 Euros, if we source the components from a value-added reseller (VAR) instead of an LVHC-EMS. VARs buy standard components from high-volume low-customisation EMSs (HVLC-EMS). They charge lower prices because of the higher volumes, but they allow only minimal customisations.

For 200 machines, the solution with one computer and two displays saves us 80,000 Euros and 120,000 Euros per year, respectively, when sourced from an LVHC-EMS and from a VAR. We save even more, if we replace more display computers by one computer with displays and if the display computers are more expensive like ISOBUS terminals. We do not only save costs on hardware but also on software, because we consolidate multiple diverse systems into one system.

A clever change of the system architecture leads to sizeable cost savings. It also leads to a system that can easily be extended in many directions – a competitive advantage.

Read More »What’s Wrong with Multiple Display Computers in Driver Cabins?

Building Yocto Packages Manually with devshell

We must figure out why a Yocto package doesn’t work as expected. So, we must tweak the source code a bit here and there, cross-build the package for our ARM-based embedded Linux system and install some shared libraries from the package on the embedded Linux system. Of course, we want short turnaround times to try out our changes quickly. The bitbake task devshell will save our day.
Read More »Building Yocto Packages Manually with devshell

Emitting Signals during Construction or Destruction

In the beginning, the application shows the Main Screen. When the user clicks on the Open button, the application will show a second screen. The second screen creates a C++ model when opened and destroys this model when closed.

As zealous Qt developers, we use the pimpl idiom to hide private declarations from its clients. Hence, we move the write and read functions of Qt properties to the implementation class in the source file. When the value of the property changes, the write function emits a signal of the interface class.

When the signal emission occurs during the construction or destruction of the interface class, we end up in the land of undefined behaviour. At the point of the signal emission, the interface object does not exist yet or does not exist any more. A real-life application will most likely crash – right a way if we are lucky or much later if Old Murphy has his way.
Read More »Emitting Signals during Construction or Destruction

Monitoring Sys Files with QFileSystemWatcher

When the driver turns off the ignition in a vehicle, display computers like terminals in harvesters or infotainment systems in cars should be notified. The display computers should save important data and shut down orderly.

When the display computer runs on Linux, it learns the status of the ignition by monitoring the GPIO for clamp 15. Linux writes the value of the GPIO to a special file in the sys filesystem. On one of my display computers, clamp15 is mapped to the special file /sys/class/gpio/gpio72/value. When the ignition is on, this file contains the string “1”. When off, this file contains “0”. The number of GPIO (here: 72) varies from display computer to display computer.

On the Linux command line, we get the value of clamp 15 with this command:

$ cat /sys/class/gpio/gpio72/value
1

The command returns “0” when the ignition is off and “1” when it is on.

How can a Qt application monitor the status of the GPIO clamp 15 such that it can shut down orderly when the driver turns off the ignition?
Read More »Monitoring Sys Files with QFileSystemWatcher

QML Engine Deletes C++ Objects Still In Use

Correction: In the original post, I stated that ownership is transferred from C++ to QML by READ functions of Q_PROPERTYs. This is wrong. Ownership is only transferred by Q_INVOKABLE functions and slots, which return a QObject pointer. I corrected my post and my code example. Now, the simple code example crashes as desired. Many thanks to Richard and Simon for pointing out my mistake.

I recently spent three days on a customer project to figure out why my QML application crashed with a segmentation fault. The crash happened after a long sequence of interactions, which was hard to reproduce. I finally managed to reproduce the crash reliably after going through the same six-step interaction four times.

After many hours of debugging and scrutinising my code, I had an epiphany about the stack trace leading to the crash. The stack trace originated from deep inside the QML engine and ended in calling the destructor of a C++ object, which was still in use on the C++ side. The trace never touched any of the application’s C++ code in between.

So far, I had only asked myself the question: Where in my C++ code do I corrupt the memory? After my little epiphany, I changed my question: Why does the QML engine delete a C++ object still in use? What do I overlook in the interaction between QML and C++?
Read More »QML Engine Deletes C++ Objects Still In Use

Converting a QByteArray into an Unsigned Integer

My program received messages from a network as an array of bytes. The sender of the messages encoded integers in Big Endian format. So, the hex number 0x1540 arrived in the sequence [0x15, 0x40]. I wrote the following function, which converts such a byte array of at most four bytes into a 32-bit unsigned integer. The function converts the sequence [0x15, 0x40] into the hex number 0x1540.

quint32 byteArrayToUint32(const QByteArray &bytes)
{
    auto count = bytes.size();
    if (count == 0 || count > 4) {
        return 0;
    }
    quint32 number = 0U;
    for (int i = 0; i < count; ++i) {
        auto b = static_cast<quint32>(bytes[count - 1 - i]);
        number += static_cast<quint32>(b << (8 * i));
    }
    return number;
}

Of course, I also wrote a unit test.

void TestByteArrayToUint32::testByteArrayToUint32()
{
    QCOMPARE(byteArrayToUint32(QByteArray::fromHex("9020562f")), 0x9020562fU);
    QCOMPARE(byteArrayToUint32(QByteArray::fromHex("314922")), 0x314922U);
    QCOMPARE(byteArrayToUint32(QByteArray::fromHex("1540")), 0x1540U);
    QCOMPARE(byteArrayToUint32(QByteArray::fromHex("38")), 0x38U);
    QCOMPARE(byteArrayToUint32(QByteArray::fromHex("")), 0x0U);
    QCOMPARE(byteArrayToUint32(QByteArray::fromHex("559020562f")), 0x0U);
}

All QCOMPARE checks passed. All seemed fine. After using my function for a (short) while, a test didn't want to pass. I tracked the problem down to my function. Converting the byte array [0x01, 0x80] yielded the result 0x80.

Can you spot the bug in my code - and in my test?
Read More »Converting a QByteArray into an Unsigned Integer