From 7d50019e1e695ec50f265282127a769aaff1ce62 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Andreas=20B=C3=B6hler?= Date: Sun, 16 Jan 2022 14:18:31 +0100 Subject: [PATCH] Fix #2 and add more documentation --- README.md | 23 ++++++++++++++--------- components/dmx512/__init__.py | 7 +++++-- components/dmx512/dmx512.h | 4 ++-- components/dmx512/dmx512esp32.cpp | 11 ++++++----- 4 files changed, 27 insertions(+), 18 deletions(-) diff --git a/README.md b/README.md index 6196ec4..a1a1cba 100644 --- a/README.md +++ b/README.md @@ -1,7 +1,7 @@ # esphome-dmx512 -This is a DMX512 custom component for ESPHome that allows ESP32-Arduino-based -devices to control DMX devices via UART (this requires usually an RS485 module). +This is a DMX512 custom component for ESPHome that allows Arduino-based +devices to control DMX devices via UART (this requires usually an RS485 module). ESP32 with the IDF-framework is currently not supported. ## Implementation @@ -11,19 +11,24 @@ The implementation is based on other projects: * https://github.com/jakosek/esphome/tree/dmx_no_uart It differs in that it uses the internal UART component but generates the -break signal by detaching and re-attaching the GPIO pin. Since this requires -directly messing around with GPIO pins, it is limited to the Arduino ESP32 core. +break signal by detaching and re-attaching the GPIO pin (on ESP32). + +## Important notes + +DMX only works on hardware UARTs, therefor the number of the UART in use needs to be set. This defaults to 1, as the first UART is usually used for logging purposes. + +On the ESP8266, the only pin you can use is GPIO2. It's TX-only and can easily be used for DMX. ## Configuration -See the provided example file. For the `dmx512` component, some options need -additonal explanation: +See the provided example file for a complete example, including output and light components. For the `dmx512` component, some options need +additional explanation: ``` dmx512: id: dmx uart_id: uart_bus - enable_pin: 33 - tx_pin: 5 + enable_pin: GPIO33 + tx_pin: GPIO5 uart_num: 1 periodic_update: true force_full_frames: false @@ -37,7 +42,7 @@ dmx512: * `enable_pin`: Set this to the pin number the MAX585 enable pins are connected to. Optional * `tx_pin`: Set this to the same pin number as the UART component. This is required - for the generation of the break signal. Defaults to 5. + for the generation of the break signal. Defaults to GPIO5. * `uart_num`: Set this to the internal ESP32 UART number. If only logging is configured, this should be set to 1 (default). * `periodic_update`: If set to false, only state changes are transmitted and the bus is silent in between - violates the specification and may cause some dimmers to turn off diff --git a/components/dmx512/__init__.py b/components/dmx512/__init__.py index 8cdfbe9..eb6ded7 100644 --- a/components/dmx512/__init__.py +++ b/components/dmx512/__init__.py @@ -39,7 +39,7 @@ def _declare_type(value): CONFIG_SCHEMA = cv.Schema({ cv.GenerateID(): _declare_type, cv.Optional(CONF_ENABLE_PIN): pins.gpio_output_pin_schema, - cv.Optional(CONF_TX_PIN, default=5): cv.int_range(min=0,max=39), + cv.Optional(CONF_TX_PIN, default=5): pins.internal_gpio_output_pin_schema, cv.Optional(CONF_UART_NUM, default=1): cv.int_range(min=0, max=UART_MAX), cv.Optional(CONF_PERIODIC_UPDATE, default=True): cv.boolean, cv.Optional(CONF_FORCE_FULL_FRAMES, default=False): cv.boolean, @@ -58,7 +58,10 @@ async def to_code(config): enable = await cg.gpio_pin_expression(config[CONF_ENABLE_PIN]) cg.add(var.set_enable_pin(enable)) - cg.add(var.set_uart_tx_pin(config[CONF_TX_PIN])) + if CONF_TX_PIN in config: + tx_pin = await cg.gpio_pin_expression(config[CONF_TX_PIN]) + cg.add(var.set_uart_tx_pin(tx_pin)) + cg.add(var.set_uart_num(config[CONF_UART_NUM])) cg.add(var.set_periodic_update(config[CONF_PERIODIC_UPDATE])) cg.add(var.set_force_full_frames(config[CONF_FORCE_FULL_FRAMES])) diff --git a/components/dmx512/dmx512.h b/components/dmx512/dmx512.h index 48ba5fa..77586e2 100644 --- a/components/dmx512/dmx512.h +++ b/components/dmx512/dmx512.h @@ -30,7 +30,7 @@ class DMX512 : public Component { void set_enable_pin(GPIOPin *pin_enable) { pin_enable_ = pin_enable; } - void set_uart_tx_pin(int tx_pin) { tx_pin_ = tx_pin; } + void set_uart_tx_pin(InternalGPIOPin *tx_pin) { tx_pin_ = tx_pin; } void set_channel_used(uint16_t channel); @@ -57,7 +57,7 @@ class DMX512 : public Component { uint32_t last_dmx512_transmission_{0}; uint8_t device_values_[DMX_MSG_SIZE]; int uart_idx_{0}; - int tx_pin_{0}; + InternalGPIOPin *tx_pin_{nullptr}; int update_interval_{UPDATE_INTERVAL_MS}; int mab_len_{DMX_MAB_LEN}; int break_len_{DMX_BREAK_LEN}; diff --git a/components/dmx512/dmx512esp32.cpp b/components/dmx512/dmx512esp32.cpp index d7ac7f5..188d4d2 100644 --- a/components/dmx512/dmx512esp32.cpp +++ b/components/dmx512/dmx512esp32.cpp @@ -9,13 +9,14 @@ namespace dmx512 { static const char *TAG = "dmx512"; void DMX512ESP32::sendBreak() { - pinMatrixOutDetach(this->tx_pin_, false, false); - pinMode(this->tx_pin_, OUTPUT); - digitalWrite(this->tx_pin_, LOW); + uint8_t num = this->tx_pin_->get_pin(); + pinMatrixOutDetach(num, false, false); + pinMode(num, OUTPUT); + digitalWrite(num, LOW); delayMicroseconds(this->break_len_); - digitalWrite(this->tx_pin_, HIGH); + digitalWrite(num, HIGH); delayMicroseconds(this->mab_len_); - pinMatrixOutAttach(this->tx_pin_, this->uart_idx_, false, false); + pinMatrixOutAttach(num, this->uart_idx_, false, false); } } // namespace dmx512