Skip to content

Commit

Permalink
Allow using multiple EasyDMX instances by utilizing multiple serial c…
Browse files Browse the repository at this point in the history
…ontrollers
  • Loading branch information
tesa-klebeband committed Oct 27, 2024
1 parent 445a859 commit 02fe1e5
Show file tree
Hide file tree
Showing 3 changed files with 38 additions and 19 deletions.
9 changes: 2 additions & 7 deletions include/easydmx.h
Original file line number Diff line number Diff line change
Expand Up @@ -26,12 +26,6 @@
#include <stdarg.h>
#include <vector>

#ifndef UART_NUM_2
#define DMX_UART_NUM UART_NUM_1
#else
#define DMX_UART_NUM UART_NUM_2
#endif

#define UART_BUF_SIZE (1024 * 2)

/**
Expand Down Expand Up @@ -132,8 +126,9 @@ class EasyDMX {
* @param mode The mode of the DMX driver. Can be Transmit, Receive, Both or BothKeepRx. Depending on the mode, the pins can be set to NoRx or NoTx.
* @param rx_pin The pin connected to the RO pin of the max485. If mode is set to Transmit, this pin has to be set to NoRx.
* @param tx_pin The pin connected to the DI pin of the max485. If mode is set to Receive, this pin has to be set to NoTx.
* @return 0 if the initialization was successful, -1 otherwise.
*/
void begin(DMXMode mode, int rx_pin, int tx_pin);
int begin(DMXMode mode, int rx_pin, int tx_pin);

/**
* Stops the DMX driver and its associated tasks.
Expand Down
2 changes: 1 addition & 1 deletion library.json
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
{
"name": "EasyDMX",
"version": "1.1.0",
"version": "1.2.0",
"description": "EasyDMX is a library designed for sending and receiving DMX512 with an ESP32, aimed at providing simplicity and ease of use",
"keywords": "dmx, stage, lighting",
"repository":
Expand Down
46 changes: 35 additions & 11 deletions src/easydmx.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -18,10 +18,34 @@

#include <easydmx.h>

/**
* List of UART numbers in descending order. This way the UART used typically for serial communication is used last.
* If 3 (for some chips only 2) EasyDMX instances are required, the Arduino Serial library shouldn't be used anymore.
*/
const int UART_MAP[] = {
#ifndef UART_NUM_2
UART_NUM_1,
UART_NUM_0
#else
UART_NUM_2,
UART_NUM_1,
UART_NUM_0
#endif
};

int next_uart = 0;
int dmx_uart_num;

/**
* Starts the DMX driver with the given pins.
*/
void EasyDMX::begin(DMXMode mode, int rx_pin, int tx_pin) {
int EasyDMX::begin(DMXMode mode, int rx_pin, int tx_pin) {
if (next_uart >= sizeof(UART_MAP) / sizeof(UART_MAP[0])) {
return -1;
}

dmx_uart_num = UART_MAP[next_uart++];

this->rx_pin = rx_pin;
this->tx_pin = tx_pin;
this->mode = mode;
Expand All @@ -33,9 +57,9 @@ void EasyDMX::begin(DMXMode mode, int rx_pin, int tx_pin) {
.parity = UART_PARITY_DISABLE,
.stop_bits = UART_STOP_BITS_2,
.flow_ctrl = UART_HW_FLOWCTRL_DISABLE};
uart_param_config(DMX_UART_NUM, &uart_config);
uart_set_pin(DMX_UART_NUM, tx_pin, rx_pin, UART_PIN_NO_CHANGE, UART_PIN_NO_CHANGE);
uart_driver_install(DMX_UART_NUM, UART_BUF_SIZE * 2, UART_BUF_SIZE * 2, 20, &uart_queue, 0);
uart_param_config(dmx_uart_num, &uart_config);
uart_set_pin(dmx_uart_num, tx_pin, rx_pin, UART_PIN_NO_CHANGE, UART_PIN_NO_CHANGE);
uart_driver_install(dmx_uart_num, UART_BUF_SIZE * 2, UART_BUF_SIZE * 2, 20, &uart_queue, 0);

// Based on the operating mode, create the appropriate task
if (mode == DMXMode::Transmit || mode == DMXMode::Both || mode == DMXMode::BothKeepRx) {
Expand Down Expand Up @@ -115,13 +139,13 @@ uint8_t EasyDMX::getChannelTx(int channel) {
void* EasyDMX::dmxTxTask() {
uint8_t start_code = 0;
while (true) {
uart_wait_tx_done(DMX_UART_NUM, 1000); // Wait for the UART to finish sending
uart_set_line_inverse(DMX_UART_NUM, UART_SIGNAL_TXD_INV); // Invert the TX line for the break (LOW)
uart_wait_tx_done(dmx_uart_num, 1000); // Wait for the UART to finish sending
uart_set_line_inverse(dmx_uart_num, UART_SIGNAL_TXD_INV); // Invert the TX line for the break (LOW)
ets_delay_us(100); // Wait for the break to be sent
uart_set_line_inverse(DMX_UART_NUM, 0); // Revert the TX line back to normal (HIGH)
uart_set_line_inverse(dmx_uart_num, 0); // Revert the TX line back to normal (HIGH)
ets_delay_us(14); // Wait for the Mark After Break (MAB) to finish
uart_write_bytes(DMX_UART_NUM, (const char*)&start_code, 1); // Send the start code
uart_write_bytes(DMX_UART_NUM, (const char*)dmx_data_tx + 1, 512); // Send the DMX data
uart_write_bytes(dmx_uart_num, (const char*)&start_code, 1); // Send the start code
uart_write_bytes(dmx_uart_num, (const char*)dmx_data_tx + 1, 512); // Send the DMX data
}
}

Expand All @@ -139,7 +163,7 @@ void* EasyDMX::dmxRxTask() {
if (xQueueReceive(uart_queue, (void*)&event, portMAX_DELAY)) { // Wait for an event to be received
memset(data, 0, UART_BUF_SIZE); // Clear the data buffer
if (event.type == UART_DATA) { // Check if the event is a data event
uart_read_bytes(DMX_UART_NUM, data, event.size, portMAX_DELAY); // Read the data from the UART
uart_read_bytes(dmx_uart_num, data, event.size, portMAX_DELAY); // Read the data from the UART

if (state == DMXStateRx::Break) { // Handle a break, reset the state and the current address
if (data[0] == 0) {
Expand All @@ -158,7 +182,7 @@ void* EasyDMX::dmxRxTask() {
}
}
} else { // Either break, idle or other events (such as errors)
uart_flush(DMX_UART_NUM); // Flush the UART buffer
uart_flush(dmx_uart_num); // Flush the UART buffer
xQueueReset(uart_queue); // Reset the queue
state = (event.type == UART_BREAK) ? DMXStateRx::Break : DMXStateRx::Idle; // Set the state based on the event type
}
Expand Down

0 comments on commit 02fe1e5

Please sign in to comment.