Cloud deep neural network controller [en]

The Cloud DNNC is a project to replace the PID controller from the most common control systems: simple in simple out (SISO) systems with first order plus dead time FOPDT and second order plus dead time (SOPDT) system behavior. Since the DNNC does not require any parameterization, it is very easy to use and no in-depth knowledge of the given process parameters is necessary. By considering the process as a black box, it is even possible to provide a cloud controller as a service. Otherwise a model of the process and controller parameters derived from it would be required.

Of course, the question of what makes sense immediately arises, since process security goes hand in hand with the availability of my server service. Therefore, everyone should be clear: this service is a playground. You are welcome to connect your simulated or real process to the controller and carry out various tests. I do not guarantee service availability. I would then be happy to receive your experience reports so that I can further optimize the controller.

The neural network is permanently optimized in the cloud on various CPU and GPU resources. I will inform you about updates and improvements of the DNNC on this blog.

My final goal is to port the network to a CortexM4 microcontroller. The “deep” in deep neural network is therefore limited by the resources of such a microcontroller.

The following graphic shows the closed control loop:


It is actually as simple as it looks. Basically, the service expects an HTTP GET request with the setpoint (setpoint SP) and the actual process value (y (t)). The controller output (u (t)) that is to be applied to the actuator is returned. In order that everything from level to temperature control can be covered, the input and output variables must be scaled and transmitted without units. The value ranges of the DNNC should always be used from 0 to 100%. The same procedure can be found in many industrial controllers.

Process example: temperature control for soldering furnace

Temperature range: 0 ° C to 260 ° C => 0% = 0 ° C, 50% = 130 ° C
Actuator: Triac with full wave control (0 to 50) => 50% = 25 full waves

The DNNC will suggest a manipulated variable with a lot decimal places, but in many cases this can simply be rounded. However, it should not be pushed so far that the DNNC is used as a two-point controller (> 50% = on, <= 50% off); this can work but gives poor controller results.

Comparison of PID and DNNC:


As can be seen, the DNNC loses out against a well-coordinated PID controller, but it can score if the process changes and most processes do: Filters become clogged with dirt, flow temperatures are different, fill quantities vary, etc. The selected parameters in the graph show the generalization of the controller.

In principle, any programming language can be used with the help of the HTTP API. I provide a Python script with a class and an example to simulate a process system using the scipy package:

If you want to control a real process with Hardware in the Loop (HIL), you are cordially invited. Please note the ping times of approx. 70 ms lead to another dead time. It also occasionally happened that requests received a timeout + retransmit and the response came from the server only after four seconds. I therefore recommend regulating “lazy” processes and sending inquiries every second or fewer.

Function and behavior of the controller

The neural network receives the input and output values ​​of the process system as inputs and tries to „estimate“ the further behavior. It therefore approaches the task and is inferior to a controller with a known process model with regard to control speed. With varying process parameters, the DNNC has a clear advantage. However, the possible process parameters also have their limits.

The design of the DNNC is a compromise between covering additional process parameters or faster setpoint tracking. If the narrow parameters for a given process are known, a “specialist system” could easily be learned. However, this has also been possible for a long time with Matlab tools and some other systems.

As already mentioned, the DNNC starts with no knowledge of the process when sending the first control variable. As a result, it can only try a very small actor output, there is a risk that the process gain is very high and the dead time is long. As result a large overshoot would be likely. After the DNNC has got a „feeling“ for the dead time of the system after 4 to 5 values, the control variable can be managed more aggressively.

The neural network is trained with the help of reinforcement learning in the Amazon (AWS) cloud. In regular stages, I have several hundred systems evaluated and use them to calculate an average. I plot the systems that got an (abstract) rating below 0 and compare the system parameters.

A few numbers to get a feeling for the rating function:

  • If the control output is randomly varied between 0 and 100%, the rating is -835.
  • If the setpoint 0.0 is specified and the controller remains at 0.0 u (t), a best value of 904 can be achieved.
  • Systems that have a large time constant and high damping cannot achieve a rating above 0, in spite of the perfect controller.

The grid score for the currently hosted network from 02.02.2020 ( DNNCv1.0 ) = 319.7 :


DNNCv1.0 – Grid Score < 0 Systems

Dead times with four time steps and more should therefore be avoided. Optimizations for this are still ongoing. If you look halfway through the graph, you will see: Brown and purple on the way to the 100% setpoint were rated poorly (<0.0), even though the controller was almost fully open. Accordingly, the evaluation scale is certainly in need of improvement, but is sufficient to compare different training processes.


Furthermore, it should be considered that these systems are difficult to control (Tu / Tg <1/5) and that a well tuned PID is already reaching its limit:

Just looking at the worst system is frustrating too. Here are all systems with a GridScore of over 500:


DNNCv1.0 – Grid Score> 500 systems

As you can see, no „setpoint 100 %“ system reaches this score, for purely mathematical / physical reasons.


Process controller without parameterization? Only half the truth!

In fact, no tuning parameters need to be set, but scaling is necessary. This has a large influence on the stability of the DNNC. The route reinforcement refers to the scaled area. If, for example, a heating coil is available that could heat a water pipe to 100 ° C and it is only a matter of keeping a pipe free of ice (setpoint ~ 4 ° C), it would be more appropriate to set the control value range of the DNNC (0 to 100%) only to 10 or use 20% heating power to stay in the stable gain section. Otherwise the process path can also be scaled from -10 to 100 ° C, but this leads to somewhat poorer setpoint tracking.

In addition to the scaling that has an impact on the route gain, the time behavior must also be considered. If the trace heating mentioned above (which certainly does not become a water heater, as I exaggerated) shows, only after two hours in the work area, no controller values ​​should be requested from the server every minute. The dead time until there is a temperature change at the sensor would be much longer than four time steps in this example.

So the user needs a rough clue about his process and maybe he even has to record a step response. Is the DNNC just a bluff? Ultimately, this is decided by practical use! The DNNC starts to regulate a very wide range of process parameters in order to be able to cover a great deal for everything from seconds to days, from oversized to undersized actuators. This requires scaling with some background knowledge of the process.


The DNNC will continue to be optimized by me and will be updated occasionally. I will see in the next few weeks how stable my web service will run if there are many inquiries. Here I still lack experience.

A Jupyther notebook is already being planned, which will present a few simulations and should still close some user knowledge gaps. In addition, I have not yet shown how robust the DNNC reacts with 1% measurement noise and load jump, etc.



Unfortunately, the DNNC was unable to regulate the cooling water of our fuel rods. Where can I claim the costs caused by the super meltdown?

Please use this service at your own risk and set sensible critical switch-off thresholds beforehand.

My self balancing robot keeps falling over. What am I doing wrong?

  1. no PTxDT system – could work, but not tested
  2. I estimate the offline version of the controller with 200 µs computing time on a CortexM4. For this online version, I recommend trying less gravity.

Is the project open source?

No, the controller itself is not open source. However, I will publish some marginal areas of it, for example the simulation of PTxDT systems with Python and later the framework of my flask backend. So it remains interesting for hobbyists.

Can the DNNC also be optimized according to the actuating energy?

There is currently no effort on my part to do so. Possibly. an additional low-pass filter can be inserted between the DNNC output and the actuator, but this will lower the control quality.

Veröffentlicht unter Allgemein | Kommentar hinterlassen

Cloud Deep Neural Network Controller [de]

Der Cloud DNNC ist ein Projekt um den PID-Regler aus den am häufigsten auftretenden Regelstrecken abzulösen: Eingrößensysteme mit PT1DT und PT2DT Streckenverhalten (~PTxDT). Da der DNNC keine Parametrierung erfordert, ist er sehr einfach anzuwenden und es ist kein tieferes Wissen über die gegebenen Prozessparameter nötig. Durch die Betrachtung des Prozesses als Blackbox, ist es überhaupt möglich ein Cloud Controller als Service bereitzustellen. Andernfalls bedürfte es ein Modell des Prozesses und daraus abgeleitete Reglerparameter.

Natürlich kommt sofort die Frage nach der Sinnhaftigkeit auf, da die Prozesssicherheit mit der Verfügbarkeit meines Serverdienstes einhergeht. Darum sollte jedem klar sein: Dieser Service ist eine Spielwiese. Gern könnt ihr euren simulierten oder echten Prozess mit dem Controller verbinden und verschiedene Versuche fahren. Eine Serviceverfügbarkeit garantiere ich nicht. Ich würde mich anschließend über eure Erfahrungsberichte freuen, damit ich den Controller weiter optimieren kann.

Das Neuronale Netzwerk wird in der Cloud auf verschiedenen CPU und GPU-Ressourcen permanent optimiert. Ich werde auf dieser Seite über Updates und Verbesserungen des DNNCs informieren.

Mein finales Ziel ist eine Portierung des Netzwerkes auf einen CortexM4 Mikrocontroller. Das „Deep“ in Deep Neural Network ist also durch die Ressourcen eines solchen Mikrocontrollers limitiert. Erst in dieser Entwicklungsstufe ist der Controller sinnvoll einsetzbar.

Folgende Grafik zeigt den geschlossenen Regelkreis:


So einfach, wie es aussieht, ist es tatsächlich auch. Im Grunde erwartet der Service eine HTTP GET Anfrage mit dem Sollwert (Setpoint SP) und dem Istwert (y(t)). Zurückgegeben wird die Stellgröße (u(t)), die auf das Stellglied anzuwenden ist. Damit von Füllstands- bis Temperaturregelung alles abdeckt werden kann, müssen die Ein- und Ausgangsgrößen skaliert und einheitenlos übertragen werden. Die Wertebereiche des DNNCs sind immer von 0 bis 100 % anzuwenden. Selbes Vorgehen ist bei viele Industriecontrollern zu finden.

Prozessbeispiel: Temperaturregelung für Lötofen

Temperaturbereich: 0°C bis 260°C => 0 % = 0°C, 50 % = 130 °C
Stellglied: Triac mit Vollwellensteuerung ( 0 bis 50) => 50 % = 25 Vollwellen

Der DNNC wird einen Stellwert mit vielen Nachkommastellen vorschlagen, jedoch kann dieser in vielen Fällen einfach gerundet werden. Es sollte jedoch nicht so weit getrieben werden, dass der DNNC als Zweipunktregler eingesetzt wird (> 50 % = an, <= 50 % aus); dies kann funktionieren, gibt jedoch schlechte Regelergebnisse.

Gegenüberstellung PID und DNNC:


Wie zu erkennen ist, hat der DNNC gegen ein gut abgestimmten PID-Regler das Nachsehen, jedoch kann er punkten, wenn der Prozess sich ändert und das tun die meisten Prozesse: Filter setzen sich mit Schmutz zu, Vorlauftemperaturen sind unterschiedlich, Füllmengen variieren etc. Die gewählten Parameter im Graphen zeigen gut die Generalisierung des Reglers.

Mit Hilfe des HTTP APIs kann im Prinzip jede Programmiersprache zum Einsatz kommen. Ich stelle ein Python-Script mit einer Klasse zur Verfügung und einem Beispiel um ein Prozesssystem mit Hilfe vom scipy-package zu simulieren:

Wer einen echten Prozess mit Hardware in the Loop (HIL) ansteuern will, ist herzlich dazu eingeladen. Bitte beachtet die Ping-Zeiten von ca. 70 ms führen zu einer weiteren Totzeit. Auch kam es gelegentlich vor, dass requests einen timeout + retransmit erfahren haben und erst nach vier Sekunden die Antwort vom Server kam. Ich empfehle daher „gemütliche“ Prozesse zu regeln und sekündliche oder weniger Anfragen zu versenden.

Funktion und Verhalten des Reglers

Das Neuronale Netzwerk erhält die Ein- und Ausgangswerte des Prozesssystems als Eingänge und versucht den weiteren Verlauf „abzuschätzen“. Es tastet sich also an die Aufgabe heran und ist demnach einem Regler mit bekanntem Prozessmodel im Hinblick auf Regelgeschwindigkeit unterlegen. Bei variierenden Prozessparametern ist der DNNC klar im Vorteil. Die möglichen Prozessparameter haben jedoch auch ihre Grenzen.

Die Auslegung des DNNC ist eine Kompromiss zwischen der Abdeckung weiterer Prozessparameter oder schnellerem Setpoint-Tracking. Sind bei einem gegeben Prozess die engen Parameter bekannt, könnte problemlos ein „Spezialisten-System“ angelernt werden. Dies geht jedoch auch schon länger mit Matlab-Tools und einigen anderen Systemen.

Wie schon erwähnt, startet der DNNC beim Senden des ersten Stellwertes mit keinem Wissen über den Prozess. Folglich kann er nur einen sehr kleinen Stellwert versuchen, es besteht die Gefahr, dass die Streckenverstärkung sehr hoch ist und die Totzeit groß. Demnach wäre ein großes Überschwingen wahrscheinlich. Nachdem der DNNC nach 4 bis 5 Werten ein „Gefühl“ für die Totzeit des Systems bekommen hat, kann der Stellwert aggressiver geführt werden.

Das Neuronale Netzwerk wird mit Hilfe von Reinforcement Learning in der Amazon (AWS) Cloud traniert. In regelmäßigen Etappen lasse ich mehrere hundert Systeme bewerten und berechne daraus  einen Mittelwert. Die Systeme, die eine (abstrakte) Bewertung unter 0 bekommen haben, plotte ich und vergleiche die Streckenparameter.

Ein paar Zahlen, um ein Gefühl für die Bewertungsfunktion zu bekommen:

  • Wird der Stellausgang zufällig zwischen 0 und 100 % variiert, ergibt sich ein Bewertung von -835.
  • Wenn der Sollwert 0.0 vorgegeben wird und der Controller bei 0.0 u(t) bleibt, kann ein Bestwert von 904 erreicht werden.
  • Systeme, die eine große Zeitkonstante und hohe Dämpfung aufweisen, können teils trotz perfektem Kontroller nicht über eine Bewertung von 0 kommen.

Der Grid Score für das aktuell gehostete Netzwerk vom 02.02.2020 ( DNNCv1.0 ) = 319,7:


DNNCv1.0 – Grid Score < 0 Systeme

Totzeiten mit vier Zeitschritten und darüber sollten demnach noch vermieden werden. Optimierungen hierzu sind noch im Gange. Wer bei dem Graphen noch halbwegs durchsieht, stellt fest: Braun und Lila auf dem Weg zum 100 % Sollwert wurden schlecht (< 0.0 ) bewertet, obwohl der Regler nahezu voll aufgesteuert hat. Demnach ist der Bewertungsmaßstab sicherlich verbesserungsbedürftig, aber ausreichend um verschiedene Trainingabläufe zu vergleichen.

Weiterhin sollte bei den Systemen bedacht werden, dass diese schon zu den schwer regelbaren Systemen zählen (Tu/Tg < 1/5) und auch ein abgestimmter PID schon an seine Grenze stößt:

Nur die schlechtesten System anschauen ist auch frustrierend. Hier noch alle System mit einem GridScore von über 500:


DNNCv1.0 – Grid Score > 500 Systeme

Wie man sieht, erreicht kein „Sollwert 100 %“ System diesen Score, aus rein mathematischen/physikalischen Gründen.

Prozess-Controller ohne Parametrierung? Nur die halbe Wahrheit!

In der Tat müssen keine Tuning-Parameter eingestellt werden, jedoch ist eine Skalierung nötig. Dies hat einen entscheidenden Einfluss auf die Stabilität des DNNCs. Die Streckenverstärkung bezieht sich auf den skalierten Bereich. Steht z.B. eine Heizwendel zur Verfügung, die eine Wasserleitung auf 100 °C erhitzen könnte und es geht nur darum eine Rohrleitung eisfrei zu halten (Sollwert ~ 4 °C), wäre es geeigneter den Stellwertbereich des DNNCs (0 bis 100 %) nur auf 10 oder 20 % Leistung der Heizung anzuwenden, um in der stabilen Streckenverstärkung zu bleiben. Andernfalls kann die Prozessstrecke auch von -10 bis 100 °C skaliert werden, dies führt jedoch zu etwas schlechterem Sollwert-Tracking.

Zusätzlich zur Skalierung die Einfluss auf die Streckenverstärkung hat, muss auch das Zeitverhalten betrachtet werden. Kommt die bereits oben angesprochene Begleitheizung (die sicher nicht zum Durchlauferhitzer wird, wie von mir übertrieben dargestellt), erst nach zwei Stunden in den Arbeitsbereich, sollten keine Reglerwerte im Minutentakt vom Server abgefordert werden. Die Totzeit bis sich eine Temperaturänderung am Sensor ergibt, wäre an diesem Beispiel viel höher als vier Zeitschritte.

Damit benötigt der Anwender einen groben Anhaltspunkt über seinen Prozess und vielleicht muss er sogar eine Sprungantwort aufnehmen. Ist der DNNC nur eine Mogelpackung? Das entscheidet letztendlich der Praxiseinsatz! Der DNNC tritt an, um einen sehr weiten Bereich von Prozessparametern auszuregeln, um für möglichst alle Bereiche von Sekunden bis Tagen, von überdimensioniertem bis unterdimensioniertem Aktor Vieles abdecken zu können. Dafür wird eine Skalierung mit etwas Hintergrundwissen über den Prozess nötig.


Der DNNC wird weiterhin von mir optimiert werden und gelegentlich geupdatet. Ich werde wohl in den nächsten Wochen sehen wie stabil mein Webservice läuft, wenn viele Anfragen kommen sollten. Hier fehlt es mir noch an Erfahrungswerten.

In Planung ist schon ein Jupyther-Notebook, dass ein paar Simulationen präsentiert und noch einige Anwender-Wissenslücken schließen soll. Außerdem habe ich noch gar nicht gezeigt, wie robust der DNNC bei 1 % Messrauschen und Lastsprung reagiert usw.



Das Kühlwasser unserer Brennstäbe konnte der DNNC leider nicht regeln. Wo kann ich die Kosten, die durch den Super-GAU entstanden sind, einfordern?

Bitte diesen Service auf eigene Verantwortung verwenden und zuvor sinnvolle kritische Abschaltschwellen festlegen.

Mein self balancing robot fällt immer wieder um. Was mache ich falsch?

1. kein PTxDT System – könnte funktionieren, jedoch nicht getestet

2. Die Offline-Version des Reglers wird von mir mit 200 us Rechenzeit auf einem CortexM4 abgeschätzt. Für diese Onlineversion empfehle ich es mit weniger Gravitation zu versuchen.

Ist das Projekt open source?

Nein, der Regler an sich ist nicht open source. Jedoch werde ich einige Randbereiche davon veröffentlichen, z.B. die Simulation von PTxDT Systemen mit Python und später das Gerüst meines Flask Backends. Somit bleibt es auch für Hobbyisten weiterhin interessant.

Kann der DNNC auch nach der Stellenergie optimiert werden?

Derzeit gibt es meinerseits keine Bestrebungen dahingehend. Evtl. kann man einen zusätzlichen Tiefpassfilter zwischen Ausgang DNNC und Aktor einbringen, der jedoch die Regelgüte senken wird.

Veröffentlicht unter Allgemein | Kommentar hinterlassen

memcpy speed with newlib

Kurzer Hinweis zur newlib auf einem ARM CortexM.

Es wird ganz gern auf einem CortexM die newlib nano verwendet (siehe STM32 CubeMX etc.). Jedoch sollte man sich bewusst werden, dass für ein paar lächerliche KB Flash die Performance einer Funktion ganz rapide abnimmt: memcpy

Da memcpy z.B. auch im FreeRTOS und in so ziemlich jeder anderen Bibliothek intensiv verwendet wird, kann dies ein ziemlicher Performance-Killer sein.

Beispiel auf einem STM32H7 mit 400 MHz takt (200 MHz RAM Anbindung, D-Cache off) 1024 Byte memcpy vom Flash zum RAM:

eigene memcpy64: 3,8 us

memcpy ohne linker option „-specs=nano.specs„: 5,8 us

eigene memcpy32: 5,8 us

memcpy mit linker option „-specs=nano.specs„: 25 us

Der STM32H7 besitzt einen 64 Bit großen AXI-BUS und kann auch den Flash mit nur zwei wait states lesen, daher ist die 64 Bit Variante die schnellste. Für das „Schlachtschiff“ H7 könnte die newlib demnach noch etwas optimiert werden.

Wird die newlib im nano-Format eingesetzt, wird jedes Byte einzeln angefasst. Ansonsten wird auf einen Blocktransfer gewechselt. Siehe:

Deutlich zu sehen, dass die Performance um das 4 bis 5 fache gesteigert werden kann. Besonders praktisch ist es, wenn das RTOS beim Queue befüllen kürzer in der critical section verbringt.

Dieser weiterführende Blogbeitrag hat weniger dramatische Performance-Einbrüche festgestellt:

Veröffentlicht unter Allgemein | 1 Kommentar

Funkklingel mit Bestandsklingelanlage verbinden

In unserer neuen Wohnung haben wir eine Video-Klingelanlage von TCS. Benötigt wird die Anlage mit Videofunktion nicht wirklich, da wir im Erdgeschoss wohnen und unseren eigene Haustür haben, also ohne Etagentür.

Nun haben wir aber auch Garten auf der anderen Hausseite und bei zugezogener Balkontür hören wir die Klingel nicht. Lösung wäre an den TSC-Bus einen TSC-Funkgong anzulernen, das wäre für 120 € möglich.

Oder ein kleiner Hack?

Lösung: Obi Funkgong für 16 €, also fast ein zehntel des Preises! Nur ist ein weiterer Klingelknopf mit der Aufschrift „Garten“ wenig schön. Die Sprechanlage hat jedoch die bei uns ungenutzte Funktion, das Türschloss zu betätigen. Ein Ausgang mit 12-24 V Wechselspannung. Schon mal besser als nichts. Im Datenblatt der Sprechanlage findet sich auch die Tastenkombination für das „Installer Menu“. Darin kann eine bestimmte Funktion freigeschalten werden: immer wenn jemand Klingelt summt die Tür bzw. das Türschloss. Dies ist z.B. für Arztpraxen geeignet, die Ihre Kunden zu den Sprechzeiten hereinlassen möchten.

Mein Gedanke war zuerst: Die 12 V AC versorgen den Funktaster mit Spannung und der Taster wird einfach gebrückt. Ein kurzer Test zeigt: es wird eine Flanke am Taster benötigt, sonst klingelt nichts. Also Batterie einlegen bei gedrückten Knopf ergibt keine Reaktion.

Ich hätte eine Verzögerungsschaltung mit einem Tiefpass bauen können, aber ich hab mich dafür entschieden die Batterie beizubehalten. Die einfache Schaltung in Worten sieht nun so aus:

– Wechselspannung mit einfacher Diode gleichrichten

– Kondensator zur Glättung

– Basisvorwiderstand eines NPN weit in der Übersteuerung bestimmen + NPN über den Funktaster löten. Da dieser beim Drücken das Signal (3,3 V – Pullup) auf GND zieht.

– Drähte an GND und Diodeneingang. Fertig!

Ohne viel Text zieht der Hack dann so aus:

Wer die Schaltungserklärung nicht versteht, kann gern einen Kommentar dalassen, dann erstelle ich noch einen Schaltplan, wenn ich nicht gerade mit dem Handy auf dem Blog schreibe.

Veröffentlicht unter Allgemein | Kommentar hinterlassen

Flaschenwärmer Dilemma – Nespresso Aeroccino Hack

Leider komme ich in nächster Zeit nicht mehr so häufig zum Bloggen, da meine Frau und ich unsere beiden Zwillingsmäuse versorgen müssen. Man kann sich vorstellen, hier ist viel zu tun. Um so schlimmer, wenn es an so einfachen Dingen scheitert: möglichst schnell und effektiv die Milch auf 37 °C zu erhitzen!

Prinzipiell gibt es zwei verschiedene Systeme im unteren Preissegment auf dem Markt. Entweder man lässt im Flaschenwärmer Wasser verdampfen und die aufsteigende warme Luft erwärmt die Milch/Pre-Nahrung oder es ist ein Wasserbad das recht zügig warm wird. Leider muss man Milch aus dem Kühlschrank und Wasser mit Zimmertemperatur und unterschiedliche Füllmengen beachten. Dadurch wurde unsere Milch immer zu warm (42 °C) oder auch mal zu kalt. Nach den 3,5 Minuten ist man also mit herunterkühlen beschäftigt.

Das Wasserbadsystem bringt die Pfütze Wasser schnell zum Kochen. Nach ca. 4,5 Minuten ist die Milch gut temperiert. Leider muss man fast die ganze Zeit daneben stehen und messen, wann man die Milch herausnehmen kann. Zum Ende gewinnt die Milch in 2 Sekunden 1 Grad. Da muss man wachsam sein und kann sich nicht nebenher noch um andere Sachen kümmern. Was bei Schlafmangel und schreienden Kindern im Hintergrund nicht wirklich einfach ist. Wenn man Pech hat, ist man in der Spüle wieder mit herunterkühlen beschäftigt.

Im 21. Jahrhundert soll es keinen ordentlichen Flaschenwärmer geben? Uns würde es ja auch genügen, wenn man den Inhalt wärmen kann, ohne dabei wie ein Wachhund daneben stehen zu müssen.

So kam ich darauf unseren Nespresso Milchaufschäumer zu modifizieren. Der Aufschäumer hat auch einen zweiten Aufsatz, der die Milch nur rühren kann. Da Babys Milchschaum mit Spucken quittieren, sollte man auch besser nur diesen Aufsatz verwenden 😉 Weiterhin lässt sich der Aufschäumer ganz wunderbar reinigen und mit kochendem Wasser einmal am Tag desinfizieren.

Das Problem war natürlich, dass die Milch auf ca. 60°C erhitzt wird. Also aufgeschraubt und die Schaltung analysiert: Die Heizung wird mit 230 V betrieben und über ein 9 V Relais eingeschalten. Das Rührwerk besteht aus einem 9 V DC Motor, der per Transistor zugeschalten wird. Die 9 V werden von einem nicht galvanisch getrenntem Schaltnetzteil bereitgestellt und für den Mikrocontroller ATTINY44A mit einem 78L05 auf 5 V heruntergeregelt. Die Temperaturmessung erfolgt über einen NTC und 47 kOhm Spannungsteiler an den Analogeingang eins des Tinys.

Obwohl es mich reizen würde ein neues Programm für den Tiny zu schreiben, fehlt mir leider hierfür die Zeit. Mein Angriffspunkt war gefunden: der Spannungsteiler des NTCs. Dazu musste ich erst herausfinden welche Kennlinie der NTC aufweißt. Dazu habe ich genau zwei Messpunkte aufnehmen können:

  • kochendes Wasser 100 °C:
  • aktuelle Zimmertemperatur 25 °C (ja es wird hier im Sommer warm :-/):

Mit Hilfe dieser praktischen Tabelle von dieser Seite, konnte ich recht einfach den B-Wert des NTCs bestimmen und direkt die ADC-Rohrwerte ablesen. Ein hoch auf den Autor dieser Seite/Tabelle.

Für meine Versuche habe ich die 47 kOhm entfernt und ein langes Kabel mit einem 250 kOhm Spindelpotentiometer angelötet. Als ich mit der Tabelle die neue grobe Richtung ausgemacht habe (ca. 110 kOhm) konnte ich die ersten Tests fahren.

Der neue „Milchaufwärmer“ ist bei unterschiedlichen Füllmengen etwas am driften. Es ist klar, dass beim Abschalten von 100 ml (min -> sonst spritzt der Rühraufsatz) Flüssigkeit noch viel mehr nachgeheizt wird, als bei 250 ml (max -> sonst läuft es über). Für mich ist der neue Widerstand 125.600 Ohm ideal (120 k + 5,6 k in Serie). 250 ml werden auf ca. 38,5 °C erwärmt und kühlen beim Gießen in die Fläschchen auf ca. 37 °C herunter. Weiterhin hat der ATTINY ADC pro Grad noch ca. 8 Digits und nichts geht im Rauschen des ADCs unter!



Ein kleiner Wermutstropfen ist die Hysterese. Wird ca. 33 °C warme Flüssigkeit eingegossen, springt die Heizung nicht an. Dies ist aber auch kein UseCase für uns. Bei abgekochtem Wasser mit Zimmertemperatur (bis 28 °C) ist es kein Problem.

Möchte man nach dem erhitzen noch Pre-Nahrung einrühren ist es ideal die Taste für zwei Sekunden zu drücken, dann springt nur der Rührer ohne Heizung an und man kann die passenden Messlöffel dazu geben. Andererseits muss man das Gerät dann wieder ausspülen und man kann natürlich auch das Fläschchen schütteln.

Wie bei allen Flaschen- und Milchwärmern gilt natürlich Kopf einschalten! Das Gerät kann 1000 mal funtionieren und dann die Milch viel zu heiß machen. Fühlen und Nachmessen bleibt also auch bei dieser Konstruktion pflicht.

Hinweise zum Öffnen:

Für die Spezialschrauben auf der Unterseite lässt sich recht einfach ein passender Schlitzschraubendreher finden. Nach dem Aufschrauben (Schrauben fallen nicht heraus) bitte nur mit der Hand den metallenen Teil nach oben ziehen. Der Taster bleibt drin und darf nicht versucht werden vorher herauszubekommen, da ihr ihn sonst beschädigt. Das Unterteil und das Oberteil sind nur durch einen O-Dichtring und zwei Steckkontakten gehalten. Es sollte auch nicht zu sehr oder gar nicht gedreht werden, beim herausziehen.


Meine Frau und ich sind absolut zu frieden. Wir können innerhalb von 25 Sekunden auf Knopfdruck die kühlschrankkalte Milch auf 38 °C erwärmen und müssen dazu nicht mal daneben stehen, da es passend abschaltet. In die Fläschchen kippen, noch mal nachmessen und fertig! Das spart Nerven!


Der umgebaute Aeroccino ist von seinem orginalem Kollegen nicht zu unterscheiden.

Veröffentlicht unter Allgemein | 6 Kommentare

SQL Injection

In diesem Beitrag soll es kurz um meine Erfahrungen mit SQL Injection gehen. Es hat also mal gar nichts mit Elektronik zu tun.

Ich bin eher durch Zufall über dieses Thema gestolpert und habe es bei einigen Seiten im „Vorbeisurfen“ mal angetestet. Es ist schon erschreckend wie viele Seiten davon betroffen sind. Hatte ich eine Seite gefunden, wollte ich natürlich wissen ob und wie weit offen das Fenster nun steht.

Ist das schon „Hacken“?

Ich bin immer technisch interessiert und gebe Informationen gern kostenfrei (hier) weiter, um die Welt vielleicht ein Stück besser zu machen. Als Hacker würde ich mich wohl nicht bezeichnen wollen. Es ist aber sehr interessant bei der Injection herauszufinden, wie die hinterlagerte Datenbank tickt und wie sie aufgebaut ist. Es ist spannender als jedes Sudoku und Kreuzworträtsel zu gleich und trotzdem ähnlich kniffelig. Dabei ist es mir auch völlig egal welche Daten dort gehalten werden, da ich kein Interesse an den Daten selbst habe. Die meisten Daten sind über die Webseite eh schon frei zugänglich, dann geht es eher darum auf einen anderen Weg diese wieder abrufen zu können.

Für nicht technisch versierte (und für sich selbst?) sollte man vielleicht ein Vergleich heranziehen: Man schaut durch die Nachbarschaft und entdeckt gegen 22 Uhr abends ein offenes Fenster. Steht das Fenster wirklich offen? Sollte ich den Nachbarn lieber warnen? Man schaut also genauer hin. Vielleicht muss man ein fremdes Grundstück betreten oder benutzt ein Tool, wie z.B. ein Fernglas, um ganz sicher zu gehen. Hat man zweifelsfrei die Sicherheitslücke erkannt schaut man durch das Fenster, um hineinzurufen „Entschuldigung! Ihr Fenster steht für alle zugänglich offen. Sie sollten es lieber schließen!“. Wahrscheinlich wird sich der Nachbar auch etwas über ihren Besuch wundern…

So in etwa stell ich mir den Sachverhalt vor. Vielleicht sieht es der Staatsanwalt aber auch ganz anders? Aber das ist ein anderes Thema…

Damit es Sicherheitslücken bei der Datenübergabe geben kann, muss es eine Webseite sein die mit Datenbankzugriffen arbeitet. Eine statische HTML-Seite läuft also nicht Gefahr ein Datenleck zu besitzen. Meist sind es mittelgroße Seiten, die nicht auf einem gut bekannten Framework beruhen, sondern der Betreiber viel eigene bzw. externe IT-Leistung hineinsteckt hat. Ist die Seite wiederum zu groß und hat viele Benutzer, könnt ihr euch den Versuch sparen. Bei Facebook haben sicher schon Andere etwas gefunden und es wurde gefixt. Außerdem können sich solche Seiten Sicherheit etwas kosten lassen, aber wir kommen vom Thema ab.

Beim Besuch einer Webseite versuche ich immer mal gelegentlich ein „‚“ oder auch ein „““ in eine Textfeld oder Textbox einzugeben. Hat der Ersteller der Webseite aus Unwissenheit oder einfach nur aus Versehen die Daten dieses Textfelds unverändert an den Datenbankaufruf weitergereicht, dann wird sich die Webseite merkwürdig verhalten. Es kommt zu Fehlern oder leeren Seiten, aber nicht zu einem geordneten „Ihr Suchbegriff wurde nicht gefunden“ oder „Ihre Benutzer oder Kennwort ist falsch“.  Im schlechtesten Fall bekommt man eine ausführliche Fehlermeldung aus der Datenbank. Ich sage schlechtesten Fall, da wir nicht hacken wollen sondern ehe entrüstet über diese grobe Sicherheitslücken sind!


Microsoft OLE DB Provider for ODBC Drivers Fehler "80040e07'
[Microsoft][ODBC SQL Server Driver][SQL Server]Fehler beim Konvertieren einer Zeichenfolge in ein Datum und/oder eine Uhrzeit.

Das Rätzel welcher Datenbankserver auf der Internetseite verwendet wird ist nun schon gelöst. Interessant, was bietet denn die Seite sonst noch? Da ist doch sicher noch mehr schlechte Programmierung. Ah, ein Benutzername- und Passwortfeld… Wir befreien uns aus dem String des Benutzernamens mit „“ und fügen ein „“ hinzu. Im Benutzer steht nun „‚““ und im Passwort ein nettes „hallo„. Dies führt zu Fehlermeldung:

Kein schließendes Anführungszeichen nach der Zeichenfolge '' and Pwd='hallo''.

Jetzt sind es schon drei gravierende Verstöße: Die Seite lässt SQL Injection zu, der Datenbankserver informiert sauber über seinen Zustand und die Passwörter werden im Klartext gespeichert. Der Webseiten-Admin kann also regulär alle Passwörter der Benutzer sehen. Zur Speicherung von Passwörtern sollte immer nur gehashte Werte verwenden!

Aufgrund der gewonnen Informationen kann sich nun einfach ohne gültiges Passwort eingeloggt werden, da wir annehmen können das das SQL Query wie folgt aussieht:

SELECT * FROM table_name WHERE user='Basti' and Pwd='hallo'

Derzeit nicht bekannt ist der Tabellenname oder ob wirklich „user“ verwendet wird. Ob alle Spalten der Tabelle mit „*“ gewählt wurden ist auch noch nicht klar.

Da wo nun Basti steht ist der Einstiegspunkt der Injection. Damit dieser Aufruf Zeilen der Datenbank zurück gib, muss er nur wahr werden. Dazu können wir erst einmal das nervige Passwort (Pwd) mit „“ auskommentieren. Mit der immer wahren Operation user=“ or 1=1 werden alle Zeilen gültig.

Letztendlich geben wir beim Benutzernamen nur ein „‚ or 1=1–“ und erhalten den Zugang eines Benutzers. Dies funktioniert da es die Seite zulässt, wenn gleich mehrere Benutzer mit einen mal gültig sind. Es wird einfach der Erste genommen. Das SQL Query sieht nun so aus:

SELECT * FROM table_name WHERE user='' or 1=1--

Wenn nun ein Benutzer geht, dann gehen sicher auf noch Andere, vielleicht mit mehr Rechten?! In einer Tabelle gibt es immer/oft eine ID-Spalte. Wenn alle Spalten mit „*“ selektiert wurden und wir den Namen der Spalte herausbekommen, dann ist es ganz einfach. Der Versuch zeigt: die Spalte heißt „id„. Damit kann man sich nun als beliebiger Benutzer des Systems anmelden: „gfdgdfgdf‘ or id=5–“ -> wird zu:

SELECT * FROM table_name WHERE user='gfdgdfgdf' or id=5--

Damit habe ich es bei weiteren Versuchen gelassen. Ich habe den Webseitenbetreiber über die Sicherheitslücke informiert, ohne dabei konkret zu werden. Leider habe ich bisher keine Rückmeldung erhalten. Es wäre möglich alle Passwörter mit Email-Adressen aus dem System zu bekommen. Was eine ziemliche Sauerei für die Betroffenen wäre. Da mich aber so etwas nicht interessiert, blieb es bei dieser kleinen Knobelei. Wobei es einem schon zu einfach gemacht wurde!

Weiterhin habe ich sqlmap angetestet. Ein Python-basierendes Tool, um die SQL-Eingabe zu automatisieren. Das führte jedoch bei meinen Tests zu wenigen neuen Erkenntnissen. Außerdem war es nicht mehr nötig seinen Kopf zu benutzten. Vielleicht für schnelle Tests für Admins geeignet, aber nicht für echte Knobler. Jedoch soll es Helfen, wenn Tabellennamen und -spalten aus der Datenbank extrahiert werden sollen. Dazu ist es evtl. nötig jeden Buchstaben einzeln einer Ja/Nein-Abfrage zu unterziehen, also einer ganz schöne Arbeit, die man niemals per Hand eingeben würde.

sqlmap erzeugt riesige lange Datenbankeingaben. Wenn die in den Logs der Datenbankserver landen, fallen diese definitiv auf. Wahrscheinlich wurde auch deshalb eine Woche später die SQL-Sicherheitslücke von einer anderen Webseite entfernt. Auch nicht schlecht!

Meist stellt man die Injection selbst nur fest und kommt dann nicht weiter, entweder weil die Ideen fehlen oder weil es einfach nicht viel weiter geht. Das wichtigste Hilfsmittel ist die offizielle Befehlsdokumentation der einzelnen Datenbank-Systeme und Geduld. Der Vollständigkeit halber sollte ich erwähnen, dass natürlich nicht nur angebotene Textfelder untersucht werden können, auch Dinge die per GET und POST versandt werden sind gerade anfällig. Hierfür gibt es nicht immer ein Eingabefeld.

Veröffentlicht unter Allgemein | Kommentar hinterlassen

Protokolldesign – Kommunikation

Öfter sehe ich Fragen in den Foren, die sich um prinzipielles Protokolldesign drehen. Dabei sollen Daten zwischen zwei Teilnehmern ausgetauscht werden und finden keinen (guten) Ansatz. Dies hat auch meist wenig mit den Programmiererfahrungen zu tun. Zuletzt hatte ich einen gestandenen Hard- und Softwareentwickler eines großen Akkuschrauberherstellers am Telefon: “Nachrichten beliebiger länger über eine UART senden geht so einfach?”


Wenn ihr diesen Blogbeitrag gelesen habt, dann solltet ihr eine Übersicht darüber bekommen haben. Ich werde die möglichen Konzepte dafür nur anschneiden und Beispiele nennen, für weitere tiefergehende Informationen werde ich auf andere Seiten verweisen.

Sychrone Kommunikation

Fangen wir nach dem OSI-Modell ganz unten an: Die Bitübertragungsschicht sollte geklärt werden, bevor das weitere Konzept erstellt wird. Ob eine UART, SPI oder I2C Schnittstelle verwendet wird hängt ganz wesentlich mit dem Entwurf zusammen.

Bei SPI und I2C haben wir eine Schnittstelle nach dem Master/Slave prinzip. Das heißt: Wenn der Master etwas anfragt, dann darf der Slave nur solange senden, wie es dem Master genügt. Allein schon deshalb, weil der Master den Takt/Clock vorgibt.

Daher sind diese Protokoll oft so ausgelegt, dass alle Nachrichten eine feste Länge besitzen. Nur für wenige Pakettypen gibt es Ausnahmen in denen der Master einfach längere Daten abfragen oder senden kann.

Beispiel SPI Temperatursensor

Der Slave wird mit Hilfe der entsprechenden Chip Select (CS) Leitung auf den gemeinsamen Bus geschalten. Der Master beginnt Takt und Daten zu senden. Es ist demnach eindeutig wann eine Nachricht beginnt! Es kann ein Nachrichtenanfang über das CS Signal erkannt werden! (Framing)

Erste Byte: Adressbyte/-register -> Temperaturregister lesen

Zweite Byte: Temperatur High Byte

Dritte Byte: Temperatur Low Byte

Der 16 Bit Temperaturwert ist nun beim Master angekommen.

Beginner Tipp: Der Master muss drei Bytes senden und wird drei Bytes empfangen, da die SPI wie ein Schieberegister arbeitet. Es ist dabei klar, dass nur das Erste gesendete Byte des Masters relevant für den Slave ist (Leseregister) und nur die letzten zwei empfangenen Bytes gültige Temperaturdaten enthalten. Der Rest wird einfach ignoriert und dazu verwendet das Clock Signal weiter zu takten.

Einige SPI-Slaves können nun sofort eine weitere Nachricht verarbeiten, andere erwarten ein kurzes Abschalten des CS. Meine Empfehlung ist jedoch, nach jedem Telegramm das CS zu verwenden. Ein Temperaturlogger der 24 Stunden am Tag jede Sekunde die Temperatur abfragt, könnte auf der Taktleitung schnell ein Glitch bekommen. Damit wäre die gesamte Kommunikation um ein Bit verschoben. Ohne sich über das CS zu synchronisieren würde hier nur noch ein Reset der Baugruppe helfen.

Beispiel I2C Temperatursensor

Da es keinen CS-Leitung gibt, lauschen alle I2C-Slaves auf dem Bus bis sie aufgerufen werden. Dies passiert wenn der Master die Startkennung gefolgt von der passenden Adresse (z.B. 7-Bit Adresse) sendet (Framing). Danach folgt die passende Registeradresse, wie bei der SPI. Bei I2C gibt es nun einige Control-Bits, um die Kommunikation etwas sicherer zu gestalten. Es gibt ein z.B. ein Bit um ein Lese oder Schreibvorgang anzukündigen und der Slave muss nach jedem gelesenen/geschriebenen Byte ein ACK-Bit senden bzw. setzen. So kann der Master eher die Kommunikation abbrechen, wenn der Slave nicht mehr antwortet und muss nicht die gesamte Nachricht absetzen.

Die Kommunikation ist bei der I2C-Schnittstelle durch die Hardware schon etwas weiter für den Benutzer abstrahiert. Eine einfach Möglichkeit einen nicht antworteten Slave bei einer SPI zu erkennen ist schon schwieriger. Wenn der Temperaturwert nur 0x00 0x00 oder 0xFF 0xFF sein sollte wäre das ein Hinweis.

Asynchrone Kommunikation

Hiermit beenden wir den einfachen Teil und kommen zur “Königsklasse”: die asynchrone Kommunikation mit gleichberechtigten Kommunikationsteilnehmern im Vollduplexbetrieb. Eine UART oder auch CSMA CD, wie Ethernet, wäre dafür ein Beispiel. Dies bringt ganz neue Probleme mit sich:

  • Der Takt aller Kommunikationsteilnehmer sollte recht genau sein. Dies erfordert oft aber nicht immer einen Schwingquarz oder ähnliche Maßnahmen.
  • Es darf zeitgleich gesendet und empfangen werden. Wenn eine Anfrage gesendet wird, kann gerade noch eine verspätete Antwort oder andere Anfrage eingehen. Die Zugehörigkeit ist also erstmal undefiniert.
  • Das von mir schon mehrmals erwähnte Framing ist nicht mehr Problem der Bitübertragungsschicht. Mit Framing ist das Erkennen eines zusammengehörenden Nachrichtenpaketes gemeint.
  • Ein anderer Teilnehmer interessiert sich recht wenig dafür ob gerade Zeit ist, diese Nachricht überhaupt verarbeiten zu können. Ausnahme bildet hier das Handshake-Verfahren bei der UART. Bei der Hardwarevariante werden zusätzliche Leitungen zur Flusskontrolle eingesetzt. Man kann der Gegenstelle also mitteilen: “Halt stopp! Ich komme nicht hinterher”. Was auf den ersten Blick nach einer guten Lösung klingt, ist auch kein Wundermittel für alle Probleme. Irgendwann muss auch die ausgebremste Gegenstelle ihre Daten verwerfen, wenn diese nicht mehr senden kann.

Bleiben wir also bei allen nachfolgenden Betrachtungen bei einer UART mit RX- und TX-Leitungen zwischen zwei Teilnehmern.

Meist wird einer dieser Teilnehmer durch das Protokolldesign die Rolle des Masters und der andere die Rolle des Slaves einnehmen. Mit dem Unterschied zur SPI oder I2C, dass der Slave, wenn er denn was wichtiges zu sagen hat, einfach darauf los senden könnte.

Tipp: Bei den Protokollen wo der Master den Clock treibt (SPI/I²C), wird oft ein extra IRQ Pin verwendet, damit der Slave darauf hinweisen kann, dass er was wichtiges mitzuteilen hat.


Betrachten wir die erste Möglichkeit des Framings und damit zum Telegrammaustausch.

Alle Nachrichten haben eine feste oder sogar die selbe Länge. Wir definieren:

  • per Protokolldef. soll es einen Master und einen Slave geben.
  • der Master sendet immer zwei Byte
  • der Slave antwortet mit einer Nachrichtenlänge abhängig der gesendeten Bytes des Masters


  1. erste Byte: 0x01 für lesender Befehl
  2. zweite Byte: 0x02 für Temperaturregister

Der Slave hat nun zwei Bytes zu senden. Diese werden vom Master empfangen und als Temperaturwerte behandelt. Das Framing wird für den Master bei jeder neuen Nachricht begonnen. Das Framing des Slaves basiert auf dem Intervall von zwei Bytes.

Probleme bei dieser Variante:

  • der Slave kann z.B. beim Start der Schaltung desychronisieren und verwechselt damit die Reihenfolge der zwei Bytes. Der Slave sollte daher über einen zeitbasierenden Reset verfügen: Länger als X ms kein Byte erhalten? Dann kommt als nächstes sicher das erste Byte! Der Master sollte um diese Funktion wissen und etwas Zeit zwischen der Kommunikation lassen.
  • Das Framing des Masters kann durch die asynchrone Kommunikation ebenfalls schief gehen. Sendet der Master gerade seine Anfrage und der Slave beantwortet gerade noch die vorangegangen, kommt es zu Race Conditions die schwer bis gar nicht lösbar sind.
  • Bekommt der Master in der Zeit X keine Antwort oder zu wenig Bytes, muss ein Timeout erfolgen und darf nicht in einer Endlosschleife ewig warten. Dies gilt übrigens für ausnahmslos alle nachfolgenden Beispiele und Möglichkeiten.

Lösungen und Vorteile:

  • Gemütlich kommunizieren! Genug Zeit für die Nachrichtensychronisation belassen und schon treten die oberen Probleme kaum mehr auf.
  • Einfaches Protokolldesign für den Master.
  • Ist jeder Befehl des Masters immer nur ein Byte groß, ist ein Framing beim Slave nicht nötig -> ebenfalls sehr einfaches Protokolldesign des Slaves.

slave device desychronized

Ein Beispiel für dieses Protokolldesign ist mir bei einem Motortreiber bereits begegnet und ebenfalls bei dieser Relaiskarte:


Um zu vermeiden, dass der Slave seine Synchronisation über längere Zeit ohne “Anhaltspunkte” halten muss, kann ein Startbyte und/oder ein Endebyte an die Nachricht angehängt werden.

Dies Framing-Bytes sollten entweder einzigartig oder zumindest leichter wiederzufinden sein. Dazu könnte die Länge der Nutzdaten mit versendet werden. Dies führt zu dem Vorteil, dass Nachrichten ganz unterschiedlicher Länge versendet werden können. Die Empfänger vergleichen auf das Startbyte und geht bei dem nachfolgendem Byte von der Länge der Nachricht bis zum Endebyte aus.

Die Start- und Endebytes dienen dabei der Verifikation und im Fall einer desynchronisierung wird der Empfänger im Datenstrom ein Startbyte suchen.

Nachteile dieser Variante:

  • Das Protokoll kann sich auf ein falsches Byte in den Nutzdaten einschwingen und damit wird ein falsches Längenbyte ansetzen.
  • Ist daraufhin die Länge der Zeichen fälschlich hoch, kann die synchronisierung einige Pakete dauern.
  • Die erneute synchronisierung ist nicht sichergestellt und hängt von den Nutzdaten ab.

Folgende Tabelle stellt eine beispielhafte Nachricht mit binärem Inhalt vor:


Länge Befehl Nutzdaten Endebyte
0x01 0x02 0x11 0x01


Angenommen dies Nachricht wird mehrmals versendet und der Empfänger verliert bei „Befehl“ das Framing, dann versucht er erneut das Startbyte zu finden:

  1. Befehl 0x11 ist kein Startbyte
  2. Nutzdaten 0x01 ist das erkannte Startbyte
  3. Endebyte wird als Länge angenommen, also 2
  4. das neue Endebyte muss sich nun bei Befehl befinden
  5. dort ist kein Endebyte -> Nachricht nicht gültig
  6. neues Startbyte suchen -> Nutzdaten ist das erkannte Startbyte
  7. usw.

Wie zu erkennen ist, würde bei diesem wiederkehrenden Nachrichteninhalte keine erneute Synchronisation erfolgen.

Obwohl ein zusätzliches Endebyte in Kombination mit dem Startbyte und der Länge eine recht niedrige Wahrscheinlichkeit ergibt, dass eine falsche Nachricht durch kommt, ist dieses Protokolldesign nicht bei sensiblen Daten und Anwendungen zu empfehlen.

Da es nur einfache Vergleiche und Zähler enthält, ist es von der Rechenzeit her sehr sparsam und für die schwächsten Mikrocontroller noch gut geeignet.

Bekannte Beispiele sind Protokolle für die LED-Ansteuerung:


oder mit fester Länge bei unterschiedlichen Befehlen:



Ein sehr sicheres Framing erhält man durch Einsatz von eindeutigen Start und Endebytes. Bei einem String ist Beispielsweise die nachfolgende 0x00 immer ein eindeutiges Zeichen für das Ende der Zeichenkette (im Speicher). Ebenfalls sind Zeilenumbrüche wie Carriage Return oder Line Feed (<CR><LF>) ein guter Marker für das Ende einer versendeten Nachricht.

Dies wird zum Beispiel bei den AT-Commands von Funkmodulen und bei den NMEA GPS Module so gehandhabt.

Damit dürfen leider keine binären Daten übertragen werden, sonst besteht die Gefahr, dass diese Terminierungszeichen darin auftauchen.


Also Lösung könnte man die Zahlenwerte in ein String wandeln. Alternativ besteht die Möglichkeit die gesamte binäre Nachricht in ein HEX Zeichenfolge in ASCII Darstellung zu wandeln.

Also z.B.: 64F3ABE1<LF>

Nachteilig wäre der etwas höhere Rechenaufwand und die doppelte Bandbreite, da aus einem Byte zwei werden.

Umgesetzt wird dies ebenfalls bei GSM-AT-Modems, bei der SMS-Codierung als “HEX” ist es dem fehlerbehafteten PDU-Format vorzuziehen.


Eines der stabilsten Protokolle wird leider viel zu selten eingesetzt. Es geht um das Byte Stuffing. Dabei gibt es wieder ein Ende- und/oder Startbyte das einmalig ist. Alle weiteren Daten können binär übertragen werden. Wenn jedoch eines der eindeutigen Zeichen vorkommt, werden diese durch ein sogenanntes Escape-Zeichen und einem definierten Zeichen ersetzt. Durch das zusätzliche Escape-Zeichen, muss dieses Zeichen ebenfalls ersetzt werden. So wird das Protokoll absolut eindeutig.

Ein kleines Problem ist, dass nicht genau gesagt werden kann wie viel Overhead dieses Protokoll hat, da es immer auf die Nutzdaten ankommt. Eine Nachricht die viele Start-, Ende- oder Escapebytes enthält, wird länge alles Nachrichten ohne. Für dieses Problem gibt es ebenfalls Lösungsansätze auf die ich hier jedoch nicht eingehen werde.

Hier ist eine kleine bebilderte Umschau zum Bit und Byte Stuffing:

Tipp: Oft wird das Startbyte gar nicht gebraucht. Im Gegensatz zum Endebyte könnt ihr es gern weglassen. Das Endebyte ist jedoch nötig um die Nachricht abzuschließen und verarbeiten zu können. Würde man sich nur am Startbyte orientieren, müsste zum Auswerten der vorangegangenen Nachricht bis zur nächsten Nachricht gewartet werden.

Empfangsparser erstellen

Das Empfangen von Zeichen sollte immer mit einer Statemachine getan werden. In vielen Anwendungen ist es wichtig, dass der Task nicht blockierend arbeitet und auch weitere Aufgaben vom Controller verarbeitet werden können.

Oft ist es Ratsam eine kleine Software FIFO die empfangenen UART-Zeichen einlesen zu lassen, per Interrupt oder auch DMA. In der Hauptschleife wird nun geprüft ob neue Zeichen zur Verfügung stehen. Sollten Zeichen vorhanden sein, werden diese in den Protokollparser gegeben.


example state machine of a receiver

Wie man sich evtl. denken kann, benötigt dieser Parser einen Puffer der die Größte zu erwartende Nachricht speichern kann. Andernfalls würde der Speicher überlaufen. Dies ist natürlich zuvor immer zu prüfen.

Steht nach dem Startbyte die Nachrichtenlänge, müsste diese eingelesen werden und es wird heruntergezählt. Bei 0 sollte dann ein Endebyte empfangen werden oder es ist etwas schief gegangen.



Viele kleine Mikrocontroller haben schon eine eingebaute CRC-Einheit. Eine an die Nachricht angehängte CRC sollte ein Minimum sein, wenn sensible Anwendungen erstellt werden. Ungültige Nachrichten mit fehlerhaft übertragenem Inhalt werden im einfachsten Fall verworfen.


Somit kommen wir zu einer zweiten Sicherung im Protokolldesign: die Retransmits. Sollte eine Nachricht nach einer bestimmte Zeit nicht beantwortet werden, kann die Nachricht wiederholt werden. Dies muss nicht für jede Nachricht gelten und kann auch dem Benutzer überlassen werden.


Das wiederholte Senden von Nachrichten hat jedoch eine weitere Tücke. Der Sender kann nicht sicherstellen ob die Nachricht bei der Gegenstelle nicht ankam oder ob nur die positive Bestätigung (acknowledge) verloren gegangen ist.

Sollten Nachteile dadurch entstehen, wenn die Gegenstelle zwei aufeinanderfolgende gültige Nachrichten erhält, sollte eine Sequenz ID eingeführt werden. Daran kann erkannt werden, ob die Nachricht nur ein Retransmit darstellt und nur die ACK-Nachricht nachgeholt werden muss oder die übliche Reaktion durchgeführt werden muss.


Der Slave multipliziert eine Zahl immer mit dem Inhalt der Nachricht des Masters und sendet eine Bestätigung, falls die Multiplikation erfolgt ist. Wenn nun das ACK des Slaves verloren geht, sendet der Master die selbe Nachricht erneut, ohne zu wissen das die Multiplikation bereits erfolgt ist. Eine Sequenz ID lässt den Slave erkennen ob er diese Nachricht schon mit einem ACK beantwortet hat oder noch bearbeiten muss.

Eine andere gute Lösung ist es, den Master einfach das Produkt (Faktor * Faktor = Produkt) abfragen zu lassen, um erneut synchronisieren zu können, diesmal jedoch auf einer ganz anderen Ebene.


Ich habe sicher noch einige Varianten vergessen Ich hoffe jedoch die wichtigsten Protokolldesignschritte herausgestellt zu haben. Falls ihr noch Fragen habt, schreib einfach einen Kommentar.

Veröffentlicht unter Allgemein | 2 Kommentare