Archiv des Autors: Jonas

Nanoleaf Lines | Protokoll Reverse Engineering

Es war Anfang 2022, Pandemie und ich hatte nichts zu tun. Daher habe ich mir zu dem Zeitpunkt die noch relativ neuen Nanoleaf Lines gekauft. Nicht um sie an die Wand zu hängen, sondern um herauszufinden wie diese untereinander kommunizieren.

Die Lines bestehen aus Modulen, die immer gleich sind und an einander gereiht werden um verschiedene Formen zu bilden. Dabei gibt es verschiedene Typen von Modulen. LED Module, Verbinder und Taster. Prinzipiell kann jedes Modul an jeder Stelle verbaut werden.

2022 habe ich angefangen und bin schon relativ weit gekommen. Ich hatte das Ziel eigene kompatible Module zu bauen. Dies hat auch gut geklappt. Allerdings gab Chipmangel und ein Wechsel auf einen anderen Chip war auch keine Option.

Nun ist es 2024, Chips sind wieder verfügbar und das eingestaubte Projekt muss fortgeführt werden.

Systemdaten

  • 42V Netzteil – Spannungs wird durch alle Module durchgeschleift
  • Wlan Controller – kommuniziert mit der App bzw. offene API
  • Modulkommunikation: 3.3V UART, 1M BAUD, 8N1 Single Wire Half Duplex

LED Modul

Das LED Modul hat 2 Anschlüsse mit je 3 Pins (42V, GND, UART). Es besitzt 2x 12 RGB LED und 2x 12 White LED. Diese beiden Gruppen sind jeweils in Reihe geschaltet und können vom Controller unterschiedlich angesteuert werden. Das Modul besitzt des weiteren eine Touchfläche auf der Oberseite. Damit können Gesten erkannt werden.

Das Modul kann in beiden Richtungen eingebaut werden, die Einbaurichtung wird bei der Initialisierung automatisch erkannt.

An ein LED Modul kann immer nur ein 6-eckiger Verbinder angesteckt werden.

Verbinder (Connector/ Puck)

Die Verbinder haben 6 äußere Anschlüsse, jeder Anschluss hat die gleichen 3 Pins (42V, GND, UART). Außerdem gibt es Anschlüsse für ein Tasterbedienteil, dies wird auf den Verbinder geclipst. An jeden der 6 Anschlüsse kann ein LED Modul angeschlossen werden und somit der Aufbau erweitert werden. So können verschiedene Formen entstehen.

Der Verbinder hat keine Richtungsvorgabe, jeder Anschluss kann in jeder Richtung verbaut werden. Eine Erkennung der Ausrichtung passiert während der Initialisierung.

Kommunikation

Reset

Mit einem Reset Befehl werden alle Module resettet und sind dann „unkonfiguriert“.

Initialisierung
  • Struktur erkennen: Dafür wird ein Befehl vom Modul empfangen und an die anderen Module weitergeleitet. Jedes Modul antwortet darauf und gibt seinen Anschluss Pin zurück sowie welche Module an anderen Pins angeschlossen sind. Der Controller kann aus der Struktur der Antwort erkennen wie die Module zusammengesteckt sind.
  • Version: Sobald die Struktur des Netzwerkes bekannt ist fragt der Controller jedes Modul an welche Version es hat. Durch einen „Header“ weiß das jeweilige Modul ob es angesprochen ist. Ansonsten wird es durchgeleitet. Eine Antwort erhält 2 Versionsnummern in ASCII und einen CRC.
  • Seriennummer: Ähnlich wie bei der Version liefert hier jedes Modul seine Seriennummer + CRC zurück. Die Seriennummer ist die UID vom Mikrocontroller.

Mit diesen 3 Schritten ist die Initialisierung abgeschlossen. Der Controller weiß wie die Struktur aussieht und kennt alle Modul Versionen. Daraufhin kann der Controller entscheiden Updates durchzuführen oder den Normalbetrieb aufzunehmen.

Zyklische Abfrage

Bei der zyklischen Abfrage liefern LED Module den Wert der Touchfläche, und die Verbinder den Wert der eventuell aufgesteckten Taster zurück. Mit einem dritten Wert können Module sich „neu“ anmelden, falls sie neu angesteckt wurden. Daraufhin wird die Initialisierung erneut durchgeführt. Jede Modul antwortet mit 2 Bytes.

Farbbefehle

Es gibt unterschiedliche Farbbefehle. Zum einen spezifisch auf ein Modul zugeschnittene Befehle als auch „globale“ Befehle, wie z.b. Helligkeit.

  • Helligkeit: Hier wird die Helligkeit für das ganze Netzwerk gesetzt
  • Farbe: Beim Farb-Command wird die Einstellung für jedes Modul übertragen. Jeder Farb-Command besteht aus einem Längenbyte und dem Payload. Es wird immer das ganze Netzwerk übertragen. Es gibt verschiedene Commands. Diese Werden in umgekehrter Reihenfolge gesendet. Die letzten Daten gehören zum ersten Modul. Dadurch werden die Daten bis zum letzten Modul immer kürzer. Für die Verbinder gibt es immer ein 2 Byte (Länge + Payload) langen „Platzhalter“. Für LED Module, die die Farbe nicht ändern sollen gibt es einem Dummy Command mit 3 Bytes (Länge + Dummy links + Dummy rechts).

Weiteres Vorgehen

Der aktuelle Stand ist. Der Code für die Kommunikation ist komplett fertig. Sowohl meine selbst gebauten Verbinder sowie LED-Module funktionieren und verhalten sich wie originale Module. Erkennung von neu angesteckten Modulen funktioniert noch nicht vollständig. Dies ist aber ein eher kleines Problem, da dies für den Normalbetrieb nicht benötigt wird.

Der nächste Schritt ist das decodieren der Farbbefehle und der Farbabgleich der LEDs.

uModbus | Modbus RTU Slave für Microcontroller

Letztes Jahr gab es eine kleine Herausforderung bei der Heimautomatisierung. Wie verbinde ich möglichst günstig einen Mikrocontroller mit meinem Server? Die Hardware war schon vorhanden und sollte nur erweitert werden.

Eine UART Schnittstelle gab es am Mikrocontroller. Daher entschied ich mich für eine simple Modbus RTU Kommunikation. Es musste ein Slave implementiert werden. Ich benötigte nur eine einzige Funktion „Read Holding Registers“. Also habe ich erstmal nur diese implementiert. Dies lief nun ca. 6 Monate ohne Störungen durch.

Ich habe nun die letzten Tage noch weiteren Funktionen implementiert und meinen Code auf Github gestellt. Link ist unten zu finden. Außerdem eine kurze Anleitung wie der Slave für eigene Projekte eingebunden werden kann.


uModbus Slave | Einbindung in eigene Projekte

Binde einfach die 4 Dateien modbusConf.h, modbusSlave.h, modbusSlave.c und modbusio.c in dein Projekt ein.

Folgende Function Codes wurden umplementiert:

  • 0x01 Read Coils
  • 0x02 Read Discrete Inputs
  • 0x03 Read Holding Registers
  • 0x04 Read Input Registers
  • 0x05 Write Single Coil
  • 0x06 Write Single Registers
  • 0x0F Write Multiple Coils
  • 0x10 Write Multiple Holding Registers

Konfiguration

Die Konfiguration wird in modbusConf.h gemacht.

  • BUFFERLENGTH – Größe des Send und Receive Buffers. Modbus Spezifikation Max. 256.
  • MAX_DISCRETE_INPUTS – Maximale Anzahl an Discrete Inputs
  • MAX_COILS – Maximale Anzahl an Coils
  • MAX_INPUT_REGISTERS – Maximale Anzahl an Input Registers
  • MAX_HOLDING_REGISTERS – Maximale Anzahl an Holding Registers

Wenn die Anzahl an Daten 0 ist werden die dazugehörigen Funktionen nicht kompiliert und bei einer Anfrage wird ein „Illegal Function Code“ zurück gesendet.

Einbindung

Binde die modbusSlave.h in dein Projekt ein. Außerdem musst du folgende Variablen erstellen.

  • mbDataMapping modbusData – hier stehen deine Daten drin. Inputs / Coils / Input Registers und Holding Registers
  • mbComm modbusComm – dies wird zur Kommunikation benutzt. Send/Receive Buffer usw.

Im Programm muss dann nur noch zyklisch modbusSlaveCyclic(&modbusComm ,&modbusData) aufgerufen werden.

Anpassung an die Hardware

Die Anpassung an die entsprechende Hardware muss in modbusio.c vorgenommen werden.

Rufe receiveModbusByte(&modbusComm, — emfpangenes Byte–) für jedes empfangene Byte auf und übergeben das entsprechende Byte

In MBsendMessage() muss eine Funktion rein an die der SendBuffer und die Länge übergeben werden kann.

MBcheckTimer() muss eine 1 zurückgeben wenn ein ganzer Frame empfangen werden. Laut Spezifikation ist eine Übertragung nach 3,5 Zeichen nach dem letzten Zeichen beendet.

MBTimer() wurde hier genutzt um dynamisch diese 3,5 Zeichen zu gewährleisten. Wird im Beispiel mit 1ms aufgerufen im Systemtimer aufgerufen.

Links

8 bit Keyboard / Synthesizer

Im Zuge meines Studiums war die Aufgabe im 5. Semester ein selbstgewähltes Projekt in der Gruppe zu bearbeiten. Diese sollte über 1 Semester fertiggestellt werden.

Wir haben uns mit 5 Leuten für ein 8 bit Synthesizer Keyboard entschieden.

Es wurde ein altes 49 Tasten Keyboard umgebaut. Die Tasten wurden gemultiplext über i2c Portexpander eingelesen. Die Ausgabe erfolgte über einen 8bit DAC, angebunden per SPI, mit TDA Verstärker. CPU ist ein Atmel SAM G53N19.

Wir haben 8 Channels implementiert, die dynamisch einer Taste zugeordnet werden. Es gibt Rechteck, Dreieck und ein Rauschen. Angelehnt an den NES Soundchip. ADSR kann über Potis eingestellt werden. Zusätzlich gibt es noch einen Arpeggio Modus mit einstellbarer Geschwindigkeit.

Github – BachelorprojectSoundprocessor

SMB-Client auf einer SPS (Bachelorarbeit)

Ich habe von 2014 bis 2018 neben meinem Studium bei einem Softwareentwickler für Automatisierungslösungen gearbeitet. Meist hatte ich irgendwelche spezial Aufgaben wie Bibliotheken schreiben oder Bussysteme konfigurieren. Mein damaliger Chef hatte auch immer wieder Anforderungen wie Datenlogger oder Prüfsysteme mit Protokollen.

Die Frage war immer wie bekommen wir diese Protokolle ohne viel Aufwand auf einen anderen Rechner. Es gibt gerade auf kleinen SPS-Steuerungen kaum Möglichkeiten. Entweder über ein gutes HMI oder einen FTP-Upload. Mein Chef fragte mich also „Warum kann ich das nicht wie bei Windows auf einem Netzwerklaufwerk ablegen“.

Darauf kam ich dann 2017/18 auf die Idee meiner BA. Ich habe das „Server Message Block“- Protokoll für einen Client auf einer CoDeSys-SPS implementiert.

Implementiert wurde aus Mangel an Hardware auf einer Raspberry Pi Soft-SPS. Dies Plattform ist aber am Ende egal solange sie einen Standard TCP/IP Stack zur Verfügung stellt. Darauf aufbauend kam SMB in Version 2 zum Einsatz.

Mit der Implementierung kann man beliebig Große Dateien von einem Netzlaufwerk abholen und senden. Im Rahmen der BA habe ich dies auf mehrere Rechnern getestet. Allerdings hat man hier auch die üblichen Konfigurationsprobleme, die man auch aus privaten Netzwerken kennt. Zusätzliche gab es auf dem internen HMI noch eine Browser Funktion. Diese wurde aber nur „Quick & Dirty“ implementiert.

Die ganze Projekt liegt auf Github und meine BA kann hier runtergeladen werden.

Github – SMB-Client auf einer SPS

Hexapod / 6 DOF Stewart Platform

Ich habe aus Interesse an der Funktion, und der Mathematik dahinter, einen Hexapod gebaut.

Ein Hexapod hat für gewöhnlich 6 feste Punkte am Boden und 6 bewegliche Punkt auf der Plattform. Durch verschieben/rotieren usw. im Raum müssen die Längen der Streben immer wieder neu berechnet und angepasst werden.

In diesem Projekt kamem allerdings Modellbauservos zum Einsatz dadurch sind die unteren Punkte nicht mehr statisch. Dies erforderte komplexere Formel zur Berechnung der Stellwinkel der Servos.

Darauf aufbauend wollte ich noch eine „Ball on Plate“ Funktion implementieren, hatte aber wenig Zeit und auch keine Verfügbarkeit der benötigten Teile.

Der Controller ist ein Ninteno Wii Controller angesprochen per I2C, dieses haben ich gewählt, da es meine ersten Gehversuche mit I2C war.

Code liegt auf Github.