← Подключение оборудования | Содержание | Далее: Обмен по I2C →
Обмен по UART
Подробное описание протокола UART для управления DimmerLink.
Параметры подключения
| Параметр | Значение |
|---|---|
| Скорость (Baud Rate) | 115200 |
| Биты данных | 8 |
| Чётность | Нет (N) |
| Стоп-биты | 1 |
| Формат | 8N1 |
ℹ️ Примечание: Интерфейс UART доступен сразу после подачи питания.
Формат команд
Все команды начинаются со стартового байта 0x02 (STX — Start of Text):
┌──────────┬──────────┬──────────┬──────────┐
│ START │ CMD │ ARG1 │ ARG2 │
│ 0x02 │ 1 byte │ optional │ optional │
└──────────┴──────────┴──────────┴──────────┘
⚠️ Важно: Без стартового байта
0x02команда не будет обработана!
Таблица команд
| Команда | Код | Формат | Описание |
|---|---|---|---|
| SET | 0x53 ('S') | 02 53 IDX LEVEL |
Установить яркость |
| GET | 0x47 ('G') | 02 47 IDX |
Получить яркость |
| CURVE | 0x43 ('C') | 02 43 IDX TYPE |
Установить кривую диммирования |
| GETCURVE | 0x51 ('Q') | 02 51 IDX |
Получить тип кривой |
| FREQ | 0x52 ('R') | 02 52 |
Получить частоту сети |
| RESET | 0x58 ('X') | 02 58 |
Программный сброс |
| SWITCH_I2C | 0x5B ('[') | 02 5B |
Переключиться на I2C |
Параметры
- IDX — индекс диммера (0–7, текущая версия поддерживает только 0. Значения 1–7 зарезервированы для будущих многоканальных версий)
- LEVEL — яркость 0–100 (в процентах)
- TYPE — тип кривой: 0=LINEAR, 1=RMS, 2=LOG
Коды ответов
| Код | Имя | Описание |
|---|---|---|
| 0x00 | OK | Команда выполнена успешно |
| 0xF9 | ERR_SYNTAX | Неверный формат или неизвестная команда |
| 0xFC | ERR_NOT_READY | Ошибка записи в EEPROM |
| 0xFD | ERR_INDEX | Неверный индекс диммера |
| 0xFE | ERR_PARAM | Недопустимое значение параметра |
Описание команд
SET — Установить яркость
Формат: 02 53 IDX LEVEL
Example: 02 53 00 32 → Set dimmer 0 to 50%
Response: 00 → OK
| LEVEL | Яркость |
|---|---|
| 0x00 (0) | 0% — выключено |
| 0x32 (50) | 50% |
| 0x64 (100) | 100% — полная яркость |
GET — Получить текущую яркость
Формат: 02 47 IDX
Example: 02 47 00 → Request dimmer 0 brightness
Response: 00 32 → OK, level 50%
📝 Примечание: GET возвращает значение в процентах (0–100), так же как и SET.
CURVE — Установить кривую диммирования
Формат: 02 43 IDX TYPE
| TYPE | Кривая | Применение |
|---|---|---|
| 0 | LINEAR | Универсальная |
| 1 | RMS | Лампы накаливания, галогенные |
| 2 | LOG | LED (соответствует восприятию глаза) |
Example: 02 43 00 01 → Set RMS curve for dimmer 0
Response: 00 → OK
GETCURVE — Получить тип кривой
Формат: 02 51 IDX
Example: 02 51 00 → Request dimmer 0 curve type
Response: 00 00 → OK, type LINEAR
FREQ — Получить частоту сети
Формат: 02 52
Example: 02 52 → Request frequency
Response: 00 32 → OK, 50 Hz (0x32 = 50)
Or: 00 3C → OK, 60 Hz (0x3C = 60)
RESET — Программный сброс
Формат: 02 58
Example: 02 58 → Reset device
(no response — device reboots)
SWITCH_I2C — Переключение на I2C
Формат: 02 5B
Example: 02 5B → Switch interface to I2C
Response: 00 → OK (last UART response)
После успешного выполнения UART отключается, устройство переходит в режим I2C. Дальнейшее управление — только по I2C по адресу 0x50 (или настроенному адресу).
📝 Примечание: Режим сохраняется в EEPROM и восстанавливается после перезагрузки.
Примеры кода
Arduino
// 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 с SoftwareSerial (для Uno/Nano)
#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);
}
⚠️ Примечание: SoftwareSerial на Arduino Uno/Nano может работать нестабильно на скорости 115200. При возникновении ошибок связи рекомендуем использовать интерфейс I2C или плату с аппаратным UART (Arduino Mega, ESP32).
Python (pyserial)
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)
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)
Для тех, кто не знаком с HEX
HEX (шестнадцатеричная система) — способ записи чисел.
| Десятичное | HEX | Примечание |
|---|---|---|
| 0 | 0x00 | Ноль |
| 50 | 0x32 | Пятьдесят |
| 100 | 0x64 | Сто |
| 255 | 0xFF | Максимум для 1 байта |
Как перевести число в HEX
Python:
level = 50
hex_value = hex(level) # '0x32'
print(f"50 in HEX = {hex_value}")
Arduino:
int level = 50;
Serial.print("50 in HEX = 0x");
Serial.println(level, HEX); // Prints "32"
Шпаргалка: яркость в HEX
| Яркость | HEX | Команда SET |
|---|---|---|
| 0% (выкл.) | 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 |
Вспомогательная функция для формирования команд
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:
void sendSetCommand(uint8_t level) {
uint8_t cmd[] = {0x02, 0x53, 0x00, level};
Serial1.write(cmd, 4);
}
// Usage
sendSetCommand(75); // 75%
Отладка
Проверка связи
Отправьте команду запроса частоты:
TX: 02 52
RX: 00 32 (OK, 50 Hz)
Типичные ошибки
| Проблема | Причина | Решение |
|---|---|---|
| Нет ответа | Отсутствует стартовый байт | Добавьте 0x02 в начало |
| Нет ответа | Неверная скорость | Проверьте 115200 |
| Нет ответа | Интерфейс в режиме I2C | Переключитесь обратно на UART |
| 0xF9 | Неизвестная команда | Проверьте код команды |
| 0xFC | Ошибка записи в EEPROM | Повторите команду |
| 0xFE | Недопустимый параметр | level > 100 или curve > 2 |
Терминальные программы
For debugging you can use:
- Windows: RealTerm (HEX mode), SSCOM
- Linux: picocom, minicom
- Cross-platform: PuTTY, CoolTerm
What's Next?
- Интерфейс I2C — альтернативный способ управления
- Примеры кода — готовые скрипты
- FAQ — устранение неполадок
← Подключение оборудования | Содержание | Далее: Обмен по I2C →