Skip to content

Tremendous Speed-Up with SQL Transactions

The function CustomerDatabase::importCustomers reads 500 customers from the list c_customers, creates an SQL query cmd for each customer and inserts each customer into the Customers table of the SQL database db.

void CustomerDatabase::importCustomers() {
    auto db = QSqlDatabase::database("CustomerDB");
    for (auto row : c_customers) {
        auto cmd = QString{"INSERT INTO Customers "
                   "(fullName, street, postalCode, city, phone, email) "
                   "VALUES (\'%1\')"}.arg(row.join("\', \'"));
        auto query = QSqlQuery{cmd, db};
    }
}

On an NXP i.MX6 SoC with four Cortex-A9 cores, this function takes 17.5 seconds! Your user would have to wait more than 17.5 seconds for the import of a CSV file with 500 customers to finish. This is unacceptable. How can you speed up the import to 0.2 seconds?
Read More »Tremendous Speed-Up with SQL Transactions

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

Connectivity Solutions Will Not Help with Autonomous Farming

Over the last two years, agricultural OEMs have been in a rush to get data from their machines to their cloud servers. Claas uses Proemion’s connectivity solution. Agco, Grimme, Krone and a few others bet on AgriRouter running on SAP’s cloud servers. Holmer seems to favour Bosch’s IoT suite. All these solutions have one thing in common: They transfer little data, typically less than 50 data points per second. They top out at 100 data points. They are good for task or order management, asset tracking, fleet management, monitoring of machine health and remote diagnosis.

At least some of these companies seem to think that these connectivity solutions will help them with driver-less or autonomous farming like harvesting, seeding, spraying or fertilising. The wishful thinking would go like this.

The farm machines transfer data to the cloud. The data is used to train machine learning algorithms on extremely powerful compute servers. The model, the result of the learning process, automagically detects whether grains are dirty, maize leaves are dry or the heads of sugar beets are chopped off. Typically, this model runs in the cloud as well, because it requires more compute power than is available on the farm machine or because it adapts to new conditions and self-optimises by continuous learning. This is the way how voice assistants like Alexa and Siri understand spoken language or how medical software recognises cancer cells in MRT scans.

This approach does not work for farm machines. Here is why and what we can do about it.
Read More »Connectivity Solutions Will Not Help with Autonomous Farming

Agritechnica 2017: What’s New for Terminals?

Agritechnica 2017 was my third visit after 2013 and 2015. My focus was on terminals (display computers) as usual.

The standard terminal of 2017 is powered by a quad-core NXP i.MX6 processor (32-bit ARM Cortex-A9 with ARMv7a architecture) and has an HD 12-inch multi-touch display (resolution: 1280×800, format: 16:10). The new ISOBUS terminal CCI 1200 manufactured by CrossControl is the prime example.

In 2013, there were only terminals with single-core Cortex-A8 processors (NXP i.MX53). In 2015, there was only the odd prototype terminal with a quad-core i.MX6 in 2015 (from Grammer Belgium) but no production-quality ones. In 2017, most terminals sport a quad-core i.MX6 (Cortex-A9) processor. The processing power of terminals increases very, very slowly.

Compare this to a typical processor used in today’s in-vehicle infotainment systems. For example, the Renesas R-Car M3 sports two Cortex-A57 and four Cortex-A53 cores (all 64-bit), which has the performance of low-end to mid-range desktop PCs. Agricultural terminals need this procesing power as well, if the agricultural industry is serious about autonomous seeding, spraying and harvesting.

CLAAS demonstrated a first step into this direction. A camera is trained on the crop flow. An image recognition software (most likely using machine learning) detects whether the grains are too dirty and whether there are foreign particles between the grains. The future will see more and more such software to deduce actions from sensor data.

These expensive computations must be performed onboard the machine, because the Internet connection is not good enough on the field to send the data to powerful servers and to perform the computations there. The most powerful computer on the machine is typically the terminal. Current terminals are not powerful enough for these computations.

One terminal stands out from the uniform, slightly boring bulk of 12-inch, 1280×800 and quad-core i.MX6 terminals: the PowerView 1200 from Murphy by Enovation Controls. It is powered by a dual-core Cortex-A15 and has a 12.3-inch multi-touch display with a resolution of 1280×480 (format: 8:3). The PowerView 1200 is well-suited for dashboards and can double up as a rearview mirror.

I’ll take a more detailed look at some terminals in the rest of this post. I will ignore quite a few terminals, because they don’t stand out in any way from the rest or I simply overlooked them.
Read More »Agritechnica 2017: What’s New for Terminals?