Zum Inhalt springen

← Hardware-Anschluss | Inhaltsverzeichnis | Weiter: I2C-Kommunikation →

UART-Kommunikation

Detaillierte Beschreibung des UART-Protokolls zur Steuerung von DimmerLink.




Verbindungsparameter

Parameter Wert
Baudrate 115200
Datenbits 8
Parität Keine (N)
Stoppbits 1
Format 8N1

ℹ️ Hinweis: Die UART-Schnittstelle ist sofort nach dem Einschalten verfügbar.




Befehlsformat

Alle Befehle beginnen mit dem Startbyte 0x02 (STX — Start of Text):

python
┌──────────┬──────────┬──────────┬──────────┐
│  START   │   CMD    │   ARG1   │   ARG2   │
│   0x02   │  1 byte  │ optional │ optional │
└──────────┴──────────┴──────────┴──────────┘

⚠️ Wichtig: Ohne das Startbyte 0x02 wird der Befehl nicht verarbeitet!




Befehlstabelle

Befehl Code Format Beschreibung
SET 0x53 ('S') 02 53 IDX LEVEL Helligkeit einstellen
GET 0x47 ('G') 02 47 IDX Helligkeit abfragen
CURVE 0x43 ('C') 02 43 IDX TYPE Dimmkurve einstellen
GETCURVE 0x51 ('Q') 02 51 IDX Kurventyp abfragen
FREQ 0x52 ('R') 02 52 Netzfrequenz abfragen
RESET 0x58 ('X') 02 58 Software-Reset
SWITCH_I2C 0x5B ('[') 02 5B Auf I2C umschalten


Parameter

  • IDX — Dimmer-Index (0–7, aktuelle Version unterstützt nur 0. Werte 1–7 sind für zukünftige Mehrkanalversionen reserviert)
  • LEVEL — Helligkeit 0–100 (Prozent)
  • TYPE — Kurventyp: 0=LINEAR, 1=RMS, 2=LOG



Antwortcodes

Code Name Beschreibung
0x00 OK Befehl erfolgreich ausgeführt
0xF9 ERR_SYNTAX Ungültiges Format oder unbekannter Befehl
0xFC ERR_NOT_READY EEPROM-Schreibfehler
0xFD ERR_INDEX Ungültiger Dimmer-Index
0xFE ERR_PARAM Ungültiger Parameterwert



Befehlsbeschreibungen


SET — Helligkeit einstellen

Format: 02 53 IDX LEVEL

python
Example: 02 53 00 32  → Set dimmer 0 to 50%
Response: 00          → OK
LEVEL Helligkeit
0x00 (0) 0% — aus
0x32 (50) 50%
0x64 (100) 100% — volle Helligkeit


GET — Aktuelle Helligkeit abfragen

Format: 02 47 IDX

python
Example: 02 47 00     → Request dimmer 0 brightness
Response: 00 32       → OK, level 50%

📝 Hinweis: GET gibt den Wert in Prozent (0–100) zurück, genau wie SET.


CURVE — Dimmkurve einstellen

Format: 02 43 IDX TYPE

TYPE Kurve Anwendung
0 LINEAR Universell
1 RMS Glühlampen, Halogen
2 LOG LED (entspricht der Augenwahrnehmung)
python
Example: 02 43 00 01  → Set RMS curve for dimmer 0
Response: 00          → OK


GETCURVE — Kurventyp abfragen

Format: 02 51 IDX

python
Example: 02 51 00     → Request dimmer 0 curve type
Response: 00 00       → OK, type LINEAR


FREQ — Netzfrequenz abfragen

Format: 02 52

python
Example: 02 52        → Request frequency
Response: 00 32       → OK, 50 Hz (0x32 = 50)
Or:      00 3C       → OK, 60 Hz (0x3C = 60)


RESET — Software-Reset

Format: 02 58

python
Example: 02 58        → Reset device
(no response — device reboots)


SWITCH_I2C — Auf I2C umschalten

Format: 02 5B

python
Example: 02 5B        → Switch interface to I2C
Response: 00          → OK (last UART response)

Nach erfolgreicher Ausführung wird UART deaktiviert und das Gerät wechselt in den I2C-Modus. Die weitere Steuerung erfolgt ausschließlich über I2C an Adresse 0x50 (oder konfigurierter Adresse).

📝 Hinweis: Der Modus wird im EEPROM gespeichert und nach einem Neustart wiederhergestellt.




Codebeispiele


Arduino

cpp
// Use Serial1 for boards with multiple UARTs (Mega, Due, ESP32)
// Or SoftwareSerial for Uno/Nano

// For Arduino Mega, Due, ESP32 — use Serial1, Serial2
// For Arduino Uno/Nano — use SoftwareSerial (see example below)
#define DIMMER_SERIAL Serial1

void setup() {
    DIMMER_SERIAL.begin(115200);
}

// Set brightness (0-100%)
bool setLevel(uint8_t level) {
    uint8_t cmd[] = {0x02, 0x53, 0x00, level};
    DIMMER_SERIAL.write(cmd, 4);

    delay(10);
    if (DIMMER_SERIAL.available()) {
        return DIMMER_SERIAL.read() == 0x00;
    }
    return false;
}

// Get current brightness (returns 0-100%)
int getLevel() {
    uint8_t cmd[] = {0x02, 0x47, 0x00};
    DIMMER_SERIAL.write(cmd, 3);

    delay(10);
    if (DIMMER_SERIAL.available() >= 2) {
        uint8_t status = DIMMER_SERIAL.read();
        uint8_t level = DIMMER_SERIAL.read();
        if (status == 0x00) {
            return level;
        }
    }
    return -1;
}

// Set curve (0=LINEAR, 1=RMS, 2=LOG)
bool setCurve(uint8_t curve) {
    uint8_t cmd[] = {0x02, 0x43, 0x00, curve};
    DIMMER_SERIAL.write(cmd, 4);

    delay(10);
    if (DIMMER_SERIAL.available()) {
        return DIMMER_SERIAL.read() == 0x00;
    }
    return false;
}

// Get mains frequency (50 or 60 Hz)
int getFrequency() {
    uint8_t cmd[] = {0x02, 0x52};
    DIMMER_SERIAL.write(cmd, 2);

    delay(10);
    if (DIMMER_SERIAL.available() >= 2) {
        uint8_t status = DIMMER_SERIAL.read();
        uint8_t freq = DIMMER_SERIAL.read();
        if (status == 0x00) {
            return freq;
        }
    }
    return -1;
}

void loop() {
    setLevel(50);   // 50%
    delay(2000);
    setLevel(100);  // 100%
    delay(2000);
}


Arduino mit SoftwareSerial (für Uno/Nano)

cpp
#include 

SoftwareSerial dimmerSerial(10, 11);  // RX, TX

void setup() {
    Serial.begin(115200);
    dimmerSerial.begin(115200);

    Serial.println("DimmerLink ready");
}

bool setLevel(uint8_t level) {
    uint8_t cmd[] = {0x02, 0x53, 0x00, level};
    dimmerSerial.write(cmd, 4);

    delay(10);
    if (dimmerSerial.available()) {
        return dimmerSerial.read() == 0x00;
    }
    return false;
}

void loop() {
    if (setLevel(50)) {
        Serial.println("Set to 50%: OK");
    } else {
        Serial.println("Set to 50%: ERROR");
    }
    delay(3000);
}

⚠️ Hinweis: SoftwareSerial auf Arduino Uno/Nano kann bei 115200 Baud instabil sein. Bei Kommunikationsfehlern empfehlen wir die Verwendung der I2C-Schnittstelle oder eines Boards mit Hardware-UART (Arduino Mega, ESP32).


Python (pyserial)

python
import serial
import time

class DimmerLink:
    def __init__(self, port, baudrate=115200):
        try:
            self.ser = serial.Serial(port, baudrate, timeout=0.1)
        except serial.SerialException as e:
            print(f"Connection error to {port}: {e}")
            print("Check:")
            print("  - Is USB-UART adapter connected?")
            print("  - Correct port? (Windows: COM3, Linux: /dev/ttyUSB0)")
            raise

    def set_level(self, level):
        """Set brightness 0-100%"""
        cmd = bytes([0x02, 0x53, 0x00, level])
        self.ser.write(cmd)
        resp = self.ser.read(1)
        return len(resp) > 0 and resp[0] == 0x00

    def get_level(self):
        """Get brightness 0-100%"""
        cmd = bytes([0x02, 0x47, 0x00])
        self.ser.write(cmd)
        resp = self.ser.read(2)
        if len(resp) == 2 and resp[0] == 0x00:
            return resp[1]
        return None

    def set_curve(self, curve_type):
        """Set curve: 0=LINEAR, 1=RMS, 2=LOG"""
        cmd = bytes([0x02, 0x43, 0x00, curve_type])
        self.ser.write(cmd)
        resp = self.ser.read(1)
        return len(resp) > 0 and resp[0] == 0x00

    def get_frequency(self):
        """Get mains frequency (50 or 60 Hz)"""
        cmd = bytes([0x02, 0x52])
        self.ser.write(cmd)
        resp = self.ser.read(2)
        if len(resp) == 2 and resp[0] == 0x00:
            return resp[1]
        return None

    def close(self):
        self.ser.close()

# Usage example
if __name__ == "__main__":
    # Windows: 'COM3', Linux: '/dev/ttyUSB0'
    dimmer = DimmerLink('/dev/ttyUSB0')

    print(f"Mains frequency: {dimmer.get_frequency()} Hz")

    # Smooth brightness change
    for level in range(0, 101, 10):
        if dimmer.set_level(level):
            print(f"Brightness: {level}%")
        time.sleep(0.5)

    dimmer.close()


MicroPython (ESP32, Raspberry Pi Pico)

python
from machine import UART, Pin
import time

class DimmerLink:
    def __init__(self, uart_id=1, tx_pin=17, rx_pin=16):
        self.uart = UART(uart_id, baudrate=115200, tx=Pin(tx_pin), rx=Pin(rx_pin))

    def set_level(self, level):
        """Set brightness 0-100%"""
        cmd = bytes([0x02, 0x53, 0x00, level])
        self.uart.write(cmd)
        time.sleep_ms(10)
        if self.uart.any():
            return self.uart.read(1)[0] == 0x00
        return False

    def get_level(self):
        """Get brightness 0-100%"""
        cmd = bytes([0x02, 0x47, 0x00])
        self.uart.write(cmd)
        time.sleep_ms(10)
        if self.uart.any() >= 2:
            resp = self.uart.read(2)
            if resp[0] == 0x00:
                return resp[1]
        return None

    def set_curve(self, curve_type):
        """Set curve: 0=LINEAR, 1=RMS, 2=LOG"""
        cmd = bytes([0x02, 0x43, 0x00, curve_type])
        self.uart.write(cmd)
        time.sleep_ms(10)
        if self.uart.any():
            return self.uart.read(1)[0] == 0x00
        return False

    def get_frequency(self):
        """Get mains frequency"""
        cmd = bytes([0x02, 0x52])
        self.uart.write(cmd)
        time.sleep_ms(10)
        if self.uart.any() >= 2:
            resp = self.uart.read(2)
            if resp[0] == 0x00:
                return resp[1]
        return None

# Usage example
dimmer = DimmerLink()

print(f"Mains frequency: {dimmer.get_frequency()} Hz")

while True:
    for level in range(0, 101, 10):
        dimmer.set_level(level)
        print(f"Brightness: {level}%")
        time.sleep(0.5)



Für alle, die HEX nicht kennen

HEX (hexadezimal) ist eine Schreibweise für Zahlen.

Dezimal HEX Hinweis
0 0x00 Null
50 0x32 Fünfzig
100 0x64 Hundert
255 0xFF Maximum für 1 Byte


So wandeln Sie eine Zahl in HEX um

Python:

python
level = 50
hex_value = hex(level)  # '0x32'
print(f"50 in HEX = {hex_value}")

Arduino:

cpp
int level = 50;
Serial.print("50 in HEX = 0x");
Serial.println(level, HEX);  // Prints "32"


Helligkeits-HEX-Kurzübersicht

Helligkeit HEX SET-Befehl
0% (aus) 0x00 02 53 00 00
10% 0x0A 02 53 00 0A
25% 0x19 02 53 00 19
50% 0x32 02 53 00 32
75% 0x4B 02 53 00 4B
100% 0x64 02 53 00 64


Hilfsfunktion zum Erstellen von Befehlen

Python:

python
def make_set_command(level_percent):
    """Create SET command from percent"""
    return bytes([0x02, 0x53, 0x00, level_percent])

# Usage
cmd = make_set_command(75)  # 75%
print(f"Command: {cmd.hex()}")  # Prints: 0253004b

Arduino:

cpp
void sendSetCommand(uint8_t level) {
    uint8_t cmd[] = {0x02, 0x53, 0x00, level};
    Serial1.write(cmd, 4);
}

// Usage
sendSetCommand(75);  // 75%



Fehlersuche


Verbindungstest

Senden Sie den Frequenzabfrage-Befehl:

python
TX: 02 52
RX: 00 32  (OK, 50 Hz)


Häufige Fehler

Problem Ursache Lösung
Keine Antwort START-Byte fehlt 0x02 am Anfang hinzufügen
Keine Antwort Falsche Baudrate 115200 prüfen
Keine Antwort Schnittstelle im I2C-Modus Zurück auf UART umschalten
0xF9 Unbekannter Befehl Befehlscode prüfen
0xFC EEPROM-Schreibfehler Befehl wiederholen
0xFE Ungültiger Parameter level > 100 oder curve > 2


Terminalprogramme

For debugging you can use:
- Windows: RealTerm (HEX mode), SSCOM
- Linux: picocom, minicom
- Cross-platform: PuTTY, CoolTerm




What's Next?

← Hardware-Anschluss | Inhaltsverzeichnis | Weiter: I2C-Kommunikation →