logo elektroda
logo elektroda
X
logo elektroda

TuyaMCU-Protokoll - Kommunikation zwischen Mikrocontroller und Wi-Fi-Modul

p.kaczmarek2 1692 0
WERBUNG
  • Blockdiagramm der Zusammenarbeit von MCU und Wi-Fi-Modul.
    Hier werde ich die Theorie und Praxis der Implementierung der TuyaMCU-Protokollunterstützung vorstellen. TuyaMCU ist ein UART-basiertes Protokoll, das zur Kommunikation des Wi-Fi-Moduls mit dem Hauptmikrocontroller des Tuya-Geräts verwendet wird. Dieses Protokoll wird in vielen IoT-Produkten verwendet, u. a. in Dimmern, Temperatur-/Feuchtigkeitssensoren usw. mit LCD-Display, in Heizungs- und Jalousiesteuerungen und sogar in Haushaltsgeräten (z. B. Fritteuse von Blitzwolf). Ich werde die TuyaMCU-Unterstützung hier auf der WiFi-Modulseite in Programmiersprache C programmieren. Ich werde sowohl das Lesen (Parsen) von Paketen als auch deren Senden realisieren. Codefragmente aus diesem Thema sind Teil meines OpenBK7231T-Projekts, das auf Github verfügbar ist.

    TuyaMCU - Grundlagen
    TuyaMCU ist eine Methode, ein Wi-Fi-Modul (es kann ein Modul mit ESP8266 sein, wie TYWE3S, oder ganz anders, wie WB3S mit BK7231T) mit einem Mikrocontroller (zum Beispiel MM32F003) zu kommunizieren. Diese Kommunikation erfolgt über den UART, d. h. über zwei Signale, RX zu TX und TX zu RX. Die Standard-Baudrate beträgt 9800.
    Die TuyaMCU ermöglicht es, die Steuerungsaufgaben des IoT-Geräts auf zwei Chips aufzuteilen - das Wi-Fi-Modul, das für die Kommunikation mit der Außenwelt zuständig ist, und den Mikrocontroller, der sich im Allgemeinen um die anderen Dinge kümmert (z. B. LCD-Display, Tasten, Drehgeber, Dimmer, Triac-Steuerung usw.).
    Nicht alle Tuya IoT-Geräte verwenden die TuyaMCU, da manchmal das WiFi-Modul selbst ausreicht und kein zusätzlicher Mikrocontroller benötigt wird. Es gibt zwei Betriebsmodi von TuyaMCU. In einem Fall hat das Wi-Fi-Modul immer noch einige Aufgaben:
    Schaltplan eines Wi-Fi-Moduls mit Signalpegelumwandlung.
    Im zweiten Fall werden die meisten Dinge vom Mikrocontroller erledigt und das Wi-Fi-Modul sorgt nur für die Kommunikation:
    Blockdiagramm der Zusammenarbeit von MCU und Wi-Fi-Modul.
    Die Schaltpläne enthalten eine UART-Signalpegelanpassung, die jedoch im Allgemeinen nicht erforderlich ist, da sowohl die MCU als auch das Wi-Fi-Modul mit 3,3 V arbeiten.
    Die TuyaMCU ist ein binäres Protokoll, d. h. nach dem Vorschauen einer UART-Kommunikation, werden wir "Zeichen" sehen, es ist kein "pure ASCII", das wir mit bloßem Auge lesen können.
    Nachrichten, die in beide Richtungen gesendet werden, sind in Pakete unterteilt.
    Die Struktur des Pakets ist in beiden Richtungen identisch:
    FeldLänge (Bytes)Beschreibung  
    Header2Wert immer 0x55AA
    Version1Die Version des Protokolls kann sich je nach Kommunikationsrichtung ändern
    Befehl1Art des Pakets (Inhalt)
    Datenlänge2Die Größe des Dateninhalts des Pakets in Bytes
    DatenxPaketdaten, Anzahl der im vorherigen Feld angegebenen Bytes
    Prüfsumme1Prüfsumme des Pakets als Rest der Summe aller vorherigen Felder bis 256 (ich werde den Algorithmus später vorstellen)

    Die Befehle umfassen u. a:
    BefehlBeschreibung
    0x00Sog. "heartbeat", d. h. die regelmäßige Aufrechterhaltung der Kommunikation - Meldung, dass das Gerät immer noch funktioniert
    0x01Anfrage über Information zum Gerät
    0x02Anfrage über den Betriebsstatus des Wi-Fi-Moduls
    0x03Informationen zur Wi-Fi-Netzwerkverbindung
    0x04Paket, das das Wi-Fi-Modul auf einen bestimmten Konfigurationsmodus zurücksetzt
    0x05Paket, das das Wi-Fi-Modul auf einen bestimmten Konfigurationsmodus zurücksetzt
    0x06Einstellen des Gerätezustands (z. B. Einschalten des Relais, Einstellen der Helligkeit des Dimmers)
    0x07Ermitteln des Gerätestatus (wie oben, auch zum Ermitteln von z. B. Temperatur oder Luftfeuchtigkeit)
    0x1CErmitteln der aktuellen Uhrzeit für den Kalender

    Diese Tabelle ist nicht vollständig. In der Regel werden nur einige wenige Befehle verwendet.
    Einer der wichtigeren Befehle ist 0x06/0x07, er enthält auch eine spezielle Datenunterstruktur, die ich unten zeige:
    FeldLänge (Bytes)Bedeutung
    dpID 1 Funktionsbezeichner (abhängig vom Gerätetyp)
    Datentyp 1 Gibt den Datentyp des Pakets an, gemäß der etwas weiter dargestellten Aufzählung (integer, enum, string, usw.)
    Länge 2Datenlänge
    Daten x Datenfeld mit der zuvor angegebenen Länge

    Der dpID, oder Funktions-/Variablenindex, hat je nach Gerät unterschiedliche Bedeutungen. Wenn wir ein bestimmtes Gerät (z. B. TH06 Thermometer/Hygrometer) unterstützen wollen, muss er erraten, dass z. B. dpID = 1 die Temperatur ist, dpID = 2 die Luftfeuchtigkeit, usw. usw.
    Dasselbe gilt für Tasmota - auch hier müssen wir dies bei der Konfiguration des Geräts manuell angeben.
    Versprochene Datentypen:
    NameCode Beschreibung
    DP_TYPE_RAW0x00 Keine festgelegte Bedeutung
    DP_TYPE_BOOL0x01 Byte, das einen booleschen Ausdruck darstellt (wahr oder falsch)
    DP_TYPE_VALUE0x02 Vier-Byte-Ganzzahlwert
    DP_TYPE_STRING0x03Beschriftung (Zeichenfolge) ASCII
    DP_TYPE_ENUM0x04Wert der Aufzählung
    DP_TYPE_BITMAP0x05Bitmap (Bild)

    Theoretisch erfordert das TuyaMCU-Protokoll eine Initialisierung durch Meldung der Version und des Betriebsmodus des Geräts, aber in der Praxis scheint mir dies nicht notwendig zu sein – weder Tasmota noch meine Firmware führen derzeit eine vollständige Aushandlung mit dem Mikrocontroller durch, im Grunde werden die Daten auf einmal nur gesendet und empfangen.
    Nachfolgend ein Diagramm der TuyaMCU-Zustände laut Tuya:
    Blockdiagramm des Kommunikationsprozesses des Wi-Fi-Moduls mit der MCU.
    Etwas später werde ich die erfassten TuyaMCU-Pakete (kurz nach dem Start des Geräts) präsentieren, deren Reihenfolge mit dem Diagramm übereinstimmt.

    TuyaMCU - Beispiel für einen Dimmer auf TYWE3S
    Schauen wir uns das erste Beispielprodukt an, aufgeteilt in ein Wi-Fi-Modul und einen Mikrocontroller. Es wird ein Wi-Fi gesteuerter Dimmer sein, WF-DS01:
    WiFi-Dimmer-Schalter in einer offenen Box auf einer Holzoberfläche. Kabelloser WLAN-Dimmer und Bedienungsanleitung.
    Nahaufnahme einer runden Leiterplatte mit elektronischen Bauteilen. Runde Leiterplatte mit verschiedenen elektronischen Komponenten und einem Modul mit der Bezeichnung TYWE3S.
    Schaltplan:
    Schaltplan des WF-DS01 TUYA-Dimmers.
    Elektrischer Schaltplan des TUYA WF-DS01 Dimmers.
    Im Inneren befinden sich das TYWE3S (Wi-Fi-Modul mit ESP) und der Mikrocontroller MM32F003. Wir haben hier auch einen dritten Chip, der die Touch-Tasten unterstützt.

    TuyaMCU - Beispiel für einen Dimmer auf WB3S
    Ein etwas anderer Dimmer - EDM-01-AA-EU KER_V1.6. In früheren Versionen wurde er mit RTL8710BN realisiert, jetzt ist er mit WB3S. Fotos von innen:
    Bild des Inneren eines elektronischen Geräts mit sichtbarer Leiterplatte und Komponenten.
    Schaltplan, von mir skizziert:
    Schaltplan mit WB3S-Modul und LED-Leiste.
    Im Inneren befindet sich der SC95F861X:
    Diagramm des SC95F8613-ICs mit beschrifteten Pins.
    Hier sehen wir, dass der SC95F861 praktisch die gesamte Beleuchtungssteuerung übernimmt - die RESET-Taste ist mit ihm verbunden, die LEDs 1-12 zur Anzeige des Beleuchtungsniveaus sind angeschlossen, sowie das Nullerkennungssignal für den Dimmer und die Triac-Steuerung selbst (im Schaltplan als PWM bezeichnet).

    TuyaMCU – Beispiel für Uhr/Thermometer – TH06
    Das dritte Beispiel für ein Gerät, das TuyaMCU verwendet, es könnte die Uhr/das Thermometer/Hygrometer/Kalender TH06 sein:
    Intelligentes Thermometer und Hygrometer mit Diagrammen auf einem Telefonbildschirm.
    Der Mikrocontroller im Inneren ist nicht beschriftet und das Wi-Fi-Modul ist WB3S. Der große Chip in der Mitte ist der Display-Controller TM1621B.
    Leiterplatte mit montierten elektronischen Bauteilen und einem Modul mit der Bezeichnung WB3S.
    Dennoch werde ich an dieser Stelle anhalten. Ich werde TH06 als praktische Demonstration verwenden.
    Man muss mit dem Erfassen von Paketen beginnen.
    Wir erfassen Pakete, indem wir einfach die RX-Leitung unseres UART-Konverters zuerst mit TX und dann mit RX von der Platine verbinden (beide Leitungen funktionieren).
    TuyaMCU verwendet Baud 9800.
    Auf der Computerseite verwende ich RealTerm und die Option Capture:
    Screenshot des RealTerm-Programms zur Erfassung von seriellen Daten.
    Die gesammelten Daten selbst können in einem freien Hex-Viewer, z. B. xvi32, analysiert werden, oder die RealTerm-Optionen können so eingestellt werden, dass die Bytes als ASCII (für Menschen lesbar) gespeichert werden, und dann reicht ein Notizbuch:
    Screenshot eines Hex-Editors, der Binärdaten und entsprechende ASCII-Texte anzeigt.
    Bei einer so großen Anzahl von Bytes kann man sich leicht verirren. Der Einfachheit halber habe ich die Ergebnisse in Word übertragen, wo ich den Hintergrund der einzelnen Datenabschnitte farblich markieren konnte, d. h. Kopfzeile, Typ, Länge, Prüfsumme usw. hervorheben konnte:
    Tabelle mit erfassten Datenpaketen vom TXD1-Pin des WB3S, die Header, Version, Befehl, Länge und Prüfsumme enthalten.
    Auf diese Weise habe ich die gesamte "Unterhaltung" des WB3S mit dem Mikrocontroller erfasst, Daten in beide Richtungen. Ich werde sie im nächsten Abschnitt analysieren.

    TH06 – Paketinhalte in der Praxis
    Ich habe die unten gezeigten Pakete gleich nach der Inbetriebnahme des Geräts zusammengestellt, so dass sie auch den anfänglichen Verbindungsaufbau und das Paket mit dem Mikrocontroller-Deskriptor enthalten.
    HINWEIS: Einige weniger bekannte (weniger wichtige) Pakettypen habe ich hier weggelassen. Vollständige Kommunikation im .doc-Anhang.
    Zunächst sendet das Modul mit Wi-Fi einen "heartbeat" und die MCU antwortet darauf:
    Diagramm zur Darstellung der Struktur eines Datenpakets, das von einem WiFi-Modul an die MCU gesendet wird.
    Diagramm zeigt eine Nachricht, die vom MCU an das WiFi-Modul gesendet wird, mit Header, Version, Befehl, Länge, Daten und Prüfsumme.
    Dann sendet das Wi-Fi-Modul „Query product information“ und die MCU antwortet darauf:
    Diagramm einer Nachricht vom Wi-Fi-Modul an das MCU.
    Screenshot zeigt hexadezimale Daten, die vom MCU an das WiFi-Modul gesendet werden.
    Die Antwort der MCU enthält ASCII-Text, genauer gesagt im JSON-Format:
    
    {"p":"7akwzwfwhukkdsib","v":"1.0.0","m":0}
    

    Dann sendet das Wi-Fi-Modul „Query WiFi information“:
    Datenpaket, das vom Wi-Fi-Modul an MCU im Textformat gesendet wird.
    Diagramm, das die Datenstruktur zeigt, die vom MCU an das Wi-Fi-Modul gesendet wird.
    Die Antwort darauf beinhaltet auch die Rolle der Pins (wo ist RESET usw.).
    Dann fragt das Wi-Fi-Modul den Status des Geräts ab, genauer gesagt die Temperatur- und Luftfeuchtigkeitswerte (diese werden von der MCU ausgeführt):
    Segment einer Nachricht vom Wi-Fi-Modul an die MCU mit beschriebenen Feldern.
    Daraufhin können mehrere Pakete kommen. Bei diesem Gerät sind es drei, zwei davon zeige ich hier:
    Diagramm zeigt Datenpakete vom MCU zum WiFi-Modul.
    Die so gewonnenen Temperaturinformationen gehen dann an die Tuya-Cloud, so dass man auch Diagramme erstellen, diese aus der Ferne ablesen kann usw. In die andere Richtung ist noch Kommunikation übrig - die Uhrzeit wird vom Wi-Fi-Modul von den NTP-Servern abgerufen und mit dem folgenden Paket an die MCU gesendet:
    Diagramm des Kommunikationsrahmens zwischen Wi-Fi-Modul und MCU.

    UART - Ringpuffer für Datenempfang
    In diesem Schritt fangen wir bereits an, das Programmieren zu üben. Wir werden ein Programm für das Wi-Fi-Modul schreiben, das auf dem WB3S oder TYWE3S (ESP8266) läuft. Aber grundsätzlich ist ein UART-Ringpuffer auf beiden Seiten notwendig.
    Der Puffer ist am Prozess des Datenempfangs vom UART beteiligt. Der UART-Interrupt gibt Zeichen für Zeichen an den Puffer weiter, und wir leeren den Puffer über eine externe Funktion, wenn sich das gesamte Paket darin angesammelt hat. Die Daten im Ringpuffer werden in einer Schleife gespeichert (daher der Name), und seine Länge sollte viel größer sein als die Länge des gesamten Pakets, das wir erwarten zu empfangen.
    Für die Dauer des Lesens aus dem Ringpuffer sollten wir z. B. UART-Interrupts deaktivieren (oder einen Mutex verwenden).
    Was braucht man, um einen solchen Puffer zu beschreiben?
    Es werden vier Variablen benötigt:
    - Puffer selbst (Byte-Array)
    - die Größe dieses Arrays
    - der Zeichenindex "in" des Eingangs, d. h. wo wir das nächste vom UART empfangene Zeichen schreiben
    - der Zeichenindex des Ausgangs, "out", d. h. wo der Cursor Daten ausliest
    Code: C / C++
    Melde dich an, um den Code zu sehen

    HINWEIS: Abhängig von der Sprache, in der wir schreiben (C++ oder C), lohnt es sich natürlich zu erwägen, es in eine Struktur oder Klasse zu packen. Die Initialisierung des Puffers ist einfach - es wird Speicher für den Puffer zugewiesen und die Cursor werden gesetzt:
    Code: C / C++
    Melde dich an, um den Code zu sehen

    Ich habe das Hinzufügen zum Puffer in zwei Funktionen aufgeteilt, es ist das, was den UART-Interrupt auslöst, wenn wir ein Zeichen empfangen:
    Code: C / C++
    Melde dich an, um den Code zu sehen

    Die Bedingung im verschachtelten if durchläuft in einer Schleife den Index, wenn das Ende des Puffers erreicht ist. Das erste if prüft, ob noch Platz im Puffer ist (bei Bedarf wird er freigegeben, dann „verliert es Zeichen“, die Bedingung >= ist etwas übertrieben, da es unmöglich ist, dass der Puffer mehr Zeichen enthalten kann als seine volle Größe). test_ty_read_uart_data_to_buffer wird vom UART-Interrupt aufgerufen.
    Und Funktionen, die das Lesen aus dem Puffer ermöglichen:
    Code: C / C++
    Melde dich an, um den Code zu sehen

    Hier haben wir drei separate Funktionen:
    - die Funktion zum Abrufen der aktuellen Puffergröße (die Differenz zwischen dem Schreib- und dem Leseindex, in einer Schleife),
    - eine Funktion zum 'Erspähen' eines bestimmten Bytes im Puffer, ausgehend vom Leseindex
    - und eine Funktion, die die N Bytes, die wir bereits geladen haben, „verbraucht“ (überspringt).
    Wir werden diese Funktionen im nächsten Abschnitt verwenden.

    Grundlegendes Parsing des Pakets und Zurückweisung fehlerhafter Daten
    Wir haben bereits einen Ringpuffer, wissen aber noch nicht, wie wir das gesamte Paket erkennen können. Wir müssen wissen, wo ein Datenabschnitt beginnt und wo er endet.
    Zu diesem Zweck ist es nützlich, die Struktur des Pakets und seine Kennung (0x55AA) zu kennen.
    So sieht die Funktion aus, die vom Hauptprogramm regelmäßig in einer Schleife ausgeführt wird:
    Code: C / C++
    Melde dich an, um den Code zu sehen

    Hier sehen wir die folgenden Vorgänge:
    - die Funktion überspringt den "Müll", der vor dem Header des nächsten Pakets steht, d. h. 0x55AA (zwei Bytes)
    - Die Funktion prüft, ob das gesamte Paket bereits im Puffer verfügbar ist (konstruiert seine Länge aus den Len-Feldern - zwei Bytes - seiner Daten)
    - wenn bereits ein komplettes Paket vorhanden ist, kopiert die Funktion dessen Daten 'nach außen' und verbraucht Bytes aus dem Ringpuffer
    Nutzung der Funktion:
    Code: C / C++
    Melde dich an, um den Code zu sehen

    Die Funktion TuyaMCU_ProcessIncoming ist im Folgenden zu implementieren, ihr Argument ist im Grunde das gesamte bereits getrennte TuyaMCU-Paket.
    Code: C / C++
    Melde dich an, um den Code zu sehen

    Die obige Funktion besteht in erster Linie aus Sicherheitsmaßnahmen, darunter:
    - Überprüfung des Headers von Datenpaket
    - Prüfung, ob die in den Daten angegebene Länge mit der tatsächlichen Länge übereinstimmt
    - Berechnen und Prüfen der Prüfsumme (ob es keine Störungen, kein "Bitflip" gab)
    Darüber hinaus bestimmt sie dann den Pakettyp und wählt mithilfe des Switch-Blocks geeignete Funktionen zur Paketverarbeitung (z. B. Gerätestatus) aus.

    Senden der Informationen ans Gerät
    Alle Pakete haben die gleiche Grundstruktur, so dass wir sie mit einer Funktion versenden können, die unter anderem automatisch die Prüfsumme der Daten berechnet und die Werte in die entsprechenden Felder (z. B. Pakettyp) einträgt:
    Code: C / C++
    Melde dich an, um den Code zu sehen

    "payload_len" wird besonders behandelt, weil es ein "Wort"-Typ ist, ein Zwei-Byte-Wort, und wir es in Bytes aufteilen müssen. Die Prüfsumme wird sehr einfach berechnet und nutzt den Byte-Überlauf.

    Senden der Informationen ans Gerät (Beispiel für das Senden von Datum/Uhrzeit an ein Display)
    Im Grunde habe ich ein solches Paket bereits in dem Abschnitt über die Analyse der erfassten Kommunikation mit TH06 gezeigt.
    So sieht die Funktion aus, die es erstellt:
    Code: C / C++
    Melde dich an, um den Code zu sehen

    Das An­wen­dungs­bei­spiel:
    Code: C / C++
    Melde dich an, um den Code zu sehen

    Das Ergebnis:
    Digitaluhr mit Anzeige von Temperatur, Datum und Uhrzeit.


    Datenpaket zum Gerätestatus
    Das Gerätestatuspaket erfordert ein wenig mehr Verarbeitung als ein gewöhnliches Paket. Der Gerätestatus umfasst z. B. Temperaturwerte, Luftfeuchtigkeit, Status von Relais, Tasten usw. Die Statusvariablen haben einmalige Indexe (dpID), die ich bereits zu Beginn erwähnt habe, außerdem haben sie Typen (DP_TYPE_RAW, DP_TYPE_STRING, usw.) und Datengrößen.
    Theoretisch kann ein Statuspaket mehrere Variablen enthalten, aber in TH06 wird es in drei Pakete (je eine Variable) aufgeteilt.
    Hier ist die Funktion, die ein solches Paket parst:
    Code: C / C++
    Melde dich an, um den Code zu sehen

    Die Funktion zeigt an dieser Stelle nur die erfassten Informationen an und verarbeitet sie nicht weiter. Dennoch ist sie in der Lage, Temperatur und Luftfeuchtigkeit korrekt aus dem TH06 zu "extrahieren", was ich in meiner Firmware für den BK7231T (OpenBK7231T) getestet habe.
    Zunächst muss ich jedoch manuell eine Abfrage des Gerätestatus senden (der Screenshot zeigt das Webpanel des Wi-Fi-Moduls):
    Screenshot einer Log-Konsole mit Fehler- und Verbindungsinformationen.
    Dann erhalte ich 3 Pakete, Temperatur- und Luftfeuchtigkeitswerte im Screenshot markiert:
    Ein Logauszug mit Debug-Meldungen und Informationen zum Status von TuyaMCU.
    230, also 23,0 Grad und 24 (% Luftfeuchtigkeit). Dies stimmt mit den Werten auf dem Display überein (naja, die Temperatur hatte sich bereits um den Bruchteil eines Grads geändert, bevor ich das Foto gemacht habe):
    Digitales Uhrendisplay mit Temperaturanzeige 23,3°C, Luftfeuchtigkeit 24%, Wochentag Mittwoch, Uhrzeit 8:08 Uhr und Datum 15. Juli 2012.
    Auf diese Weise können wir über TuyaMCU sowohl Daten senden als auch empfangen. Wir sind in der Lage, den Status des Geräts zu lesen und zu setzen.

    Zusammenfassung
    Die Kenntnis des TuyaMCU-Protokolls kann in vielen Situationen nützlich sein - sowohl wenn wir unser Gerät so konfigurieren wollen, dass es mit Tasmota (wenn es auf dem ESP8266 realisiert ist) oder mit meiner Firmware (wenn es auf dem BK7231T/BK7231N/XR809 realisiert ist) arbeitet, als auch wenn wir unsere eigene Firmware für solche Produkte schreiben oder bestehende überarbeiten wollen (TuyaMCU ist einfach auf dem ESP ohne zusätzliche Besonderheiten zu betreiben, es gibt sogar solche Projekte auf github, z. B. WThermostatBeca). Dies kann uns helfen, das gekaufte Gerät unabhängig von den Servern des Herstellers zu machen, ihm mehr Funktionalität hinzuzufügen und es mit Geräten aus einem anderen Ökosystem zu verbinden, mit denen es normalerweise nicht kompatibel war.
    Ich werde meine TuyaMCU-Implementierung weiterentwickeln, es ist nicht die endgültige Version, und außerdem habe ich mehrere Probleme im Artikel ausgelassen (z. B. das Deaktivieren von Interrupts/Semaphoren, die im Tuya SDK enthalten sind – siehe tuya_common/src/driver/tuya_uart.c von). tuya-iotos-embeded-sdk-wifi-ble-bk7231t).
    Zusätzliche Materialien:
    - Repository meiner Firmware für BK7231T und ähnliche (dafür habe ich TuyaMCU implementiert)
    - Bibliothek TuyaMCU für Arduino
    - Tasmota-Dokumentation zu TuyaMCU
    - "Getting started guide" von Tuya
    - Quellcode für TuyaMCU-Unterstützung von Tasmota
    Ich füge meine .doc-Datei mit den erfassten TH06-Paketen bei (einige entschlüsselt, einige nicht).

    Cool? DIY-Rangliste
    Hilfreicher Beitrag? Kauf mir einen Kaffee.
    Hast du ein Problem mit Arduino? Stelle bei uns eine Frage. Besuche unser Arduino-Forum.
    Über den Autor
    p.kaczmarek2
    Moderator Smart Home
    Offline 
    p.kaczmarek2 hat 11907 Beiträge geschrieben mit der Bewertung 9979, und dabei 571 Mal geholfen. Er ist seit 2014 bei uns.
  • WERBUNG
WERBUNG