
Visualisierung von Gesundheitsdaten
Da die Gesundheitsbranche immer mehr Daten generiert, liegt die Herausforderung nicht mehr nur in der Datensammlung, sondern in der Interpretation. […]
Ich begrüße Sie zu einem weiteren Blogbeitrag. Der letzte Beitrag behandelte eine Form der Kommunikation zwischen Geräten mit Qt Bluetooth Low Energy. Ich habe mich entschieden, noch ein wenig bei diesem Thema zu bleiben, daher werden wir uns heute mit dem CAN-Bus befassen. Dieses Thema könnte etwas schwieriger sein als das letzte, aber keine Sorge – wie immer werde ich versuchen, es so einfach und angenehm wie möglich zu gestalten. Ohne weitere Umschweife, legen wir los!
Lassen Sie uns mit einem kleinen geistigen Aufwärmtraining beginnen. Angenommen, wir haben ein Fahrzeug mit zwei ECUs (Electronic Control Units – das sind kleine eingebettete Geräte, die Eingabedaten von z. B. Sensoren aufnehmen, verarbeiten und weiterleiten). Sie möchten, dass sie miteinander Informationen austauschen – was ist der einfachste Weg, sie zu verbinden? Ich gebe Ihnen ein paar Sekunden zum Nachdenken…
Zeit ist um. Die richtige Antwort ist ein Kabel 😅 Einfach, aber effektiv! Und wenn es mehr ECUs gibt? Dann verbinden Sie sie erneut mit einem Kabel – und das war’s! Dieser Ansatz wurde in der Automobilindustrie bis in die 1980er Jahre verwendet. Doch diese Lösung hatte viele Nachteile, also wurde eine intelligentere Methode entwickelt.
So wurde der CAN-Bus von der Firma Bosch entwickelt, um der zunehmenden Komplexität elektronischer Systeme in Fahrzeugen gerecht zu werden. Da Autos immer fortschrittlicher wurden, benötigten Hersteller eine Möglichkeit, verschiedene ECUs – wie jene für Motorsteuerung, Getriebe, Bremsen und Infotainment – miteinander zu verbinden, ohne dass eine übermäßige Verkabelung erforderlich war. Im Laufe der Zeit wurde der CAN-Bus zum Standard nicht nur in der automobilen HMI-Software und Sicherheitssystemen, sondern fand auch Anwendung in der industriellen Automatisierung, einigen medizinischen Geräten und anderen Bereichen, die einen Echtzeit-Datenaustausch erfordern.
Auf dem unten abgebildeten Foto sehen Sie den Beginn dieser Technologie – das erste Auto, das den CAN-Bus verwendete: der Mercedes-Benz W140 aus dem Jahr 1991.
Um den steigenden Anforderungen an eine effiziente und zuverlässige Kommunikation zwischen elektronischen Steuergeräten (ECUs) gerecht zu werden, wurde der CAN-Bus als leichtgewichtige, aber robuste Netzwerklösung entwickelt.
Im Gegensatz zur herkömmlichen Punkt-zu-Punkt-Verkabelung, die Fahrzeuge komplexer und schwerer machte, führte der CAN-Bus eine vereinfachte Methode für den Datenaustausch zwischen ECUs über einen gemeinsamen Kommunikationskanal ein.
Diese Architektur reduzierte nicht nur die Verkabelung, sondern erhöhte auch die Systemzuverlässigkeit und Fehlertoleranz. Dank seiner Effektivität in der Echtzeitkommunikation etablierte sich der CAN-Bus schnell als Industriestandard – zuerst im Automobilbereich und später in der industriellen Automatisierung, in medizinischen Geräten und anderen Bereichen, die eine schnelle und deterministische Datenübertragung erfordern.
Der CAN-Bus nutzt eine differentielle Signalübertragung mit zwei speziellen Leitungen: CAN High (CAN_H) und CAN Low (CAN_L). Diese beiden Leitungen arbeiten zusammen, um Störungen zu reduzieren und die Zuverlässigkeit zu erhöhen. Wenn ein logisches „0“ (dominantes Bit) gesendet wird, steigt die Spannung auf CAN_H, während CAN_L sinkt. Wird ein logisches „1“ (rezessives Bit) gesendet, befinden sich beide Leitungen auf demselben Spannungsniveau.
Werfen wir einen Blick auf den Aufbau der bereits erwähnten Electronic Control Units (ECUs). Eine ECU besteht aus drei Hauptkomponenten:
Mikrocontroller (MCU): Verarbeitet CAN-Nachrichten und führt Steuerlogik aus.
Im Inneren des MCUs befindet sich ein integrierter CAN-Controller, der für die logische Verarbeitung der CAN-Bus-Kommunikation zuständig ist.
CAN-Transceiver: Wandelt digitale Signale vom MCU in differentielle Signale auf dem CAN-Bus um und umgekehrt.
Electronic Control Units ECU
ECUs kommunizieren über den CAN-Bus, indem sie Nachrichten in Form von CAN-Frames übertragen und empfangen, die einer standardisierten Struktur folgen.
Ein CAN-Bus-Frame ist eine strukturierte Nachricht, die zur Kommunikation zwischen Geräten in einem CAN-Netzwerk verwendet wird. Sie besteht aus mehreren Schlüsselbereichen. Hier ist die Struktur eines standardmäßigen CAN-Bus-Datenframes:
CAN-Bus-Frame-Struktur
Der CAN-Bus ist ein Broadcast-System, bei dem alle Knoten jede Nachricht empfangen, aber nur relevante Nachrichten verarbeiten. Er verwendet keine globale Uhr, sondern setzt auf Bit-Level-Synchronisation, bei der Signalübergänge die Knoten im Takt halten.
Um die Stabilität zu gewährleisten, fügt das Bit-Stuffing nach jeweils fünf identischen Bits ein entgegengesetztes Bit ein, um eine korrekte Synchronisation sicherzustellen. Arbitration verhindert Kollisionen – nur der Knoten mit der niedrigsten ID (höchste Priorität) setzt die Übertragung fort, während andere sofort stoppen.
Die Knoten verwenden außerdem eine dynamische Resynchronisation, bei der sie ihre Taktung anpassen, wenn sie unerwartete Übergänge erkennen.
In der Beschreibung der Frame-Struktur haben einige der Bits unterschiedliche Werte, je nach verwendeter Protokollversion. Die folgenden aktuellen Protokollversionen sind verfügbar:
Neben der Übertragung von eigentlichen Informationen gibt es im CAN-Bus verschiedene Arten von Frames, die sich in ihrer Funktion unterscheiden, aber eine ähnliche Struktur haben:
Automobil- und Nutzfahrzeuge – Der CAN-Bus ist ein zentrales Kommunikationssystem in modernen Fahrzeugen. Er verbindet Steuergeräte (ECUs) für Motor, Getriebe, ABS, Airbags, Klimaanlage und Infotainment. Er ermöglicht Echtzeit-Diagnosen, reduziert Wartungskosten und steigert die Effizienz.
Industrielle Automatisierung – In der Produktion und Automatisierung verbindet der CAN-Bus Maschinen, Sensoren und Steuerungen, um den reibungslosen Betrieb von Fertigungslinien und Robotern zu gewährleisten.
Öffentlicher Verkehr und Bahnwesen – Der CAN-Bus wird in Zügen, Straßenbahnen und Bussen zur Steuerung von Antriebssystemen, zur Fahrzeugüberwachung und für Fahrgastinformationssysteme eingesetzt.
Branchen, die den CAN-Bus nutzen
Dank seiner Vielseitigkeit und Robustheit bleibt der CAN-Bus ein zentraler Kommunikationsstandard in vielen Branchen – von der Automobilindustrie bis zum Gesundheitswesen und darüber hinaus!
Als Entwickler, der mit Embedded-Systemen arbeitet, habe ich den CAN-Bus als eines der zuverlässigsten und einfachsten Kommunikationsprotokolle kennengelernt – sobald man sich mit seinen Eigenheiten vertraut gemacht hat. Im Gegensatz zu RS-232 oder RS-485, wo man oft mit Punkt-zu-Punkt-Verbindungen und zusätzlichem Verkabelungsaufwand zu kämpfen hat, ist der CAN-Bus mit seinem Multi-Node-Aufbau auf nur zwei Leitungen ein echter Game-Changer.
Verglichen mit Ethernet mag der CAN-Bus etwas altmodisch wirken, da er niedrigere Datenraten bietet. Aber für Echtzeitanwendungen ist er unschlagbar. Wenn man an einem ECU-System arbeitet, bei dem eine verzögerte Nachricht möglicherweise einen Autounfall verursachen könnte, gewährleistet der deterministische Charakter des CAN-Bus, dass kritische Daten genau dann übertragen werden, wenn sie benötigt werden. Ethernet hingegen eignet sich hervorragend für die Übertragung großer Datenmengen, ist jedoch nicht ideal, wenn jede Millisekunde zählt.
Dann gibt es noch LIN, das man als die einfachere und kostengünstigere Variante des CAN-Bus betrachten kann – ausreichend für Funktionen wie Sitzverstellungen, aber nicht für sicherheitskritische Systeme geeignet.
Wie Sie vielleicht bereits wissen, bietet das Qt-Framework eine Reihe von Bibliotheken zur Implementierung verschiedener Kommunikationsformate – und der CAN-Bus bildet da keine Ausnahme. Im Qt Serial Bus-Modul steht eine Reihe von Klassen zur Verfügung, um die CAN-Bus-Kommunikation in Ihrer Anwendung zu implementieren.
Abgesehen von den offensichtlichen Vorteilen der Verwendung von Qt in Ihrem Projekt (ja, Qt-Entwicklungsdienstleistungen sind genau das, was Scythe anbietet), gibt es drei Hauptvorteile bei der Verwendung von Qt CAN-Bus:
Hohe Abstraktionsebene – Qt bietet eine intuitive API für die CAN-Kommunikation und macht es überflüssig, direkt mit Low-Level-Treibern, Dateideskriptoren oder ioctl-Aufrufen zu arbeiten. Stattdessen kann man mit QCanBusDevice Verbindungen herstellen und Frames strukturiert senden/empfangen. Das macht den Code übersichtlicher, leichter wartbar und portierbar. Außerdem ermöglicht es ein einfaches Umschalten zwischen verschiedenen CAN-Bus-Versionen, indem lediglich die Verbindungsparameter angepasst werden.
Eingebaute CAN-Bus-Unterstützung – Qt unterstützt nativ mehrere CAN-Backends, darunter SocketCAN (Linux), PeakCAN und TinyCAN. Dadurch kann Ihre Anwendung mit minimalen Änderungen auf verschiedenen Plattformen laufen. Beispielsweise können Sie ein Test-Tool unter Linux mit SocketCAN entwickeln und dieselbe Anwendung unter Windows mit PeakCAN einsetzen, indem Sie lediglich den Backend-Namen wechseln. Diese Flexibilität macht Qt ideal für plattformübergreifende Entwicklungen mit unterschiedlichen Hardwareanforderungen.
Effizientes ereignisgesteuertes Modell – Das Signal-Slot-Mechanismus von Qt passt perfekt zur CAN-Kommunikation, da es ermöglicht, Nachrichten in Echtzeit asynchron zu verarbeiten. Anstatt den Bus ständig nach neuen Daten abzufragen, kann Ihre Anwendung automatisch auf eingehende Frames reagieren. Beispielsweise kann in einem Fahrzeug-Telemetriesystem ein Signal ein Live-Tachometer aktualisieren, sobald ein neuer Geschwindigkeitswert empfangen wird. In einer industriellen Automatisierungsumgebung könnte ein CAN-Frame mit Temperaturdaten sofort einen Alarm auslösen, wenn ein Grenzwert überschritten wird – und so für Echtzeit-Reaktionsfähigkeit sorgen.
Die Qt CAN-Bus-API bietet eine strukturierte Möglichkeit, mit CAN-Bus-Hardware zu interagieren. Sie umfasst mehrere Schlüsselklassen:
Seit Qt 6.5 gibt es zusätzliche Klassen, die die Handhabung von CAN-Nachrichten noch effizienter machen:
Nachdem wir alle geplanten theoretischen Aspekte besprochen haben, ist es Zeit für die praktische Demonstration. Dieses Mal habe ich mich entschieden, etwas Code aus einem früheren Blogbeitrag wiederzuverwenden, in dem ich einen Parksensor gebaut habe. Falls Sie diesen noch nicht gelesen haben, nehmen Sie sich jetzt einen Moment Zeit, um sich mit ihm vertraut zu machen. Wir werden nur die Benutzeroberfläche (UI) verwenden, also keine Sorge – es wird ganz einfach.
Das Konzept ist folgendes: Wir haben eine App, die mit dem Parksensor verbunden ist. Diese Anwendung zeigt mithilfe einer grafischen Benutzeroberfläche und akustischer Signale die Entfernung zum nächsten Hindernis an. Um das besser zu verstehen, werfen Sie einen Blick auf unseren LinkedIn-Beitrag, in dem wir dieses einfache System in Aktion zeigen.
Ursprünglich haben wir einen Ultraschallsensor verwendet, der an einen ESP32 angeschlossen war und per Bluetooth Low Energy mit der Anwendung kommunizierte. Leider hat das Board, das ich kürzlich verwendet habe, keinen CAN-Bus-Anschluss. Deshalb habe ich beschlossen, die Hardware mit einem virtuellen CAN-Port zu simulieren und Linux-Tools zum Senden und Empfangen von CAN-Nachrichten zu verwenden.
Falls Sie Qt für die Entwicklung nutzen und einen CAN-Bus für Tests benötigen, aber keine physische Hardware zur Verfügung haben, bietet Linux eine einfache Möglichkeit, eine virtuelle CAN-Schnittstelle mithilfe von SocketCAN zu erstellen. Dadurch können Sie das Senden und Empfangen von CAN-Frames testen, ohne zusätzliche Geräte anschließen zu müssen.
Um einen virtuellen CAN-Port einzurichten, führen Sie die folgenden Befehle im Terminal aus:
sudo modprobe vcan # Lädt das virtuelle CAN-Modul sudo ip link add dev vcan0 type vcan # Erstellt eine virtuelle CAN-Schnittstelle mit dem Namen vcan0 sudo ip link set up vcan0 # Aktiviert die virtuelle CAN-Schnittstelle
Sobald die virtuelle CAN-Schnittstelle aktiviert ist, können Sie die Tools cansend und candump verwenden, um die CAN-Kommunikation zu testen:
candump vcan0 # Überwacht alle Frames auf vcan0
cansend vcan0 123#10 # Sendet einen Frame mit der ID 123 und der Nutzlast 0x10
Was den UI-Code betrifft, so bleibt er derselbe wie im Beispiel mit Bluetooth. Der einzige Unterschied besteht darin, dass wir statt BLEController nun CANBusController verwenden. Werfen wir einen Blick darauf, wie diese Klasse aufgebaut ist.
CANBusController::CANBusController(QObject *parent) : QObject(parent), m_device(nullptr) { m_device = QCanBus::instance()->createDevice("socketcan", "vcan0"); if (m_device) { connect(m_device, &QCanBusDevice::framesReceived, this, &CANBusController::processReceivedFrame); } else { qWarning() << "Kann die CAN-Bus-Schnittstelle nicht öffnen, Fehler: " << m_device->errorString(); } }
void CANBusController::connectToCANBus() { if (m_device) { m_device->connectDevice(); } }
Im Konstruktor erstellen wir eine Instanz des QCanBusDevice-Objekts mit der Methode createDevice. Hier übergeben wir zwei Argumente: den Namen des Plugins und den Namen der Schnittstelle. Da wir einen virtuellen Port verwenden, lautet der Plugin-Name socketcan, und der Portname ist in unserem Fall vcan0. Falls wir unsere Anwendung mit einem physischen Gerät testen möchten, müssen wir lediglich den Plugin- und den Portnamen ändern – Qt übernimmt den Rest für uns! Um das Gerät mit dem CAN-Bus zu verbinden, rufen wir einfach m_device->connectDevice() auf. Werfen wir nun einen Blick auf die Methode processReceivedFrame, die alle eingehenden Frames verarbeitet.
void CANBusController::processReceivedFrame() { if (!m_device) return; while (m_device->framesAvailable()) { QCanBusFrame frame = m_device->readFrame(); uint16_t frameId = frame.frameId(); QByteArray payload = frame.payload(); qDebug() << "ID: " << QString::number(frameId, 16).toUpper() << " Daten: " << payload.toHex().toUpper(); if (frame.frameId() == DISTANCE_FRAME_ID && !frame.payload().isEmpty()) { int distance = static_cast(frame.payload()[0]); setDistance(distance); } } }
Diese Methode ist mit dem Signal QCanBusDevice::framesReceived verbunden. Sie wird jedes Mal aufgerufen, wenn CAN-Bus-Frames empfangen werden. In der Methode dekodieren wir zunächst den empfangenen Frame in eine ID und eine Nutzlast und geben die Daten in der Konsole aus. Anschließend überprüfen wir, ob die ID mit einer vordefinierten Konstante übereinstimmt. Eine solche Filterung kann auch durch das Festlegen von CAN-Bus-Verbindungsparametern erfolgen, aber für dieses Demo-Beispiel habe ich es bewusst einfach gehalten. Sobald wir sicher sind, dass der Frame die richtige Frame-ID hat, dekodieren wir dessen Inhalt. CAN-Bus-Daten werden normalerweise im hexadezimalen Format gespeichert, daher führen wir die entsprechenden Umwandlungen durch und setzen die Variable `distance`.
Das Senden von Daten ist ebenfalls sehr einfach. Angenommen, wir möchten einen Fehler-Frame senden, der eine Fehlerbeschreibung als Nutzlast (ein String mit bis zu 8 Zeichen) enthält. Dazu genügt folgender Code:
void CANBusController::sendMessage(const QString &data) { if (!m_device) return; uint frameId = ENGINE_MALFUNCTION_FRAME_ID; QByteArray payload = data.toUtf8(); QCanBusFrame frame(frameId, payload); if (!m_device->writeFrame(frame)) { qWarning() << "Fehler beim Senden des Frames"; } }
In der folgenden Demonstration können Sie sehen, wie die Anwendung funktioniert. Denken Sie daran, dass die gesendeten und empfangenen Daten im hexadezimalen Format vorliegen (deshalb wird beim Senden von 100#10 der Abstand auf 16 gesetzt, da 0x10 (HEX) = 16 (DEC) ist).
Zum Abschluss noch ein kleines Rätsel: Wenn Sie die Fehler-Senden-Schaltfläche drücken, wird eine Nachricht gesendet. Können Sie entschlüsseln, was ihr Inhalt ist? 🕵️♂️
Viel Spaß und viel Freude beim Lesen der kommenden Artikel!
Nach der Lektüre dieses Artikels haben Sie sicherlich erkannt, wie wichtig der CAN-Bus als Technologie ist. Das gezeigte Beispiel ist natürlich sehr einfach – in der Realität sind Projekte, die diese Kommunikationsform nutzen, weitaus komplexer. Falls Sie Unterstützung bei der Implementierung dieser Lösung in Ihrem Projekt benötigen, zögern Sie nicht, uns zu kontaktieren – wir helfen Ihnen gerne bei jedem Embedded-Software-Problem!
Kommen wir zur Sache: Es ist eine Herausforderung, Top-Qt-QML-Entwickler zu finden. Helfen Sie sich selbst und starten Sie die Zusammenarbeit mit Scythe Studio – echten Experten im Qt C++ Framework.
Entdecken Sie unsere Fähigkeiten!Da die Gesundheitsbranche immer mehr Daten generiert, liegt die Herausforderung nicht mehr nur in der Datensammlung, sondern in der Interpretation. […]
Produkte aus der STM32-Familie sind seit langer Zeit ein beliebtes Ziel für eingebettete Qt-Anwendungen. Eine der beliebtesten Optionen war über […]
Eingebettete Systeme sind das Rückgrat der modernen Technologie und treiben alles an – von IoT-Geräten und industrieller Automatisierung bis hin […]