ArtNet naar DMX-converter op basis van ESP32: Upgrade je oude DMX-systeem
op
Het ArtNet protocol heeft de DMX standaard naar het netwerk gebracht. De nieuwe ArtNet systemen zijn natuurlijk backwards compatible met de DMX standaard, maar niet andersom. Wat moet je dan doen met een oud DMX systeem? Met de interface in dit artikel kun je het upgraden en compatibel maken met deze nieuwe standaard.
Het idee voor dit project ontstond bijna spontaan toen ik nadacht over de achterwaartse compatibiliteit van de ArtNet standaard. Een universum in zowel ArtNet als DMX bestaat uit 512 kanalen, en de waarden van elk kanaal variëren van 0 tot 255. De meeste van de nieuwste generatie afstandsbediende systemen (RDM's) die in de entertainmentindustrie worden gebruikt zijn compatibel met beide protocollen, maar hoe om te gaan met systemen die hun werk nog steeds uitstekend doen maar alleen het DMX-signaal ontvangen? Het eenvoudigste idee is om het signaal extern om te zetten van ArtNet naar DMX via een draadloos, compact en herconfigureerbaar apparaat.
ArtNet naar DMX converter: Hardware
Het hele project is opgebouwd rond een 38-pins versie van de ESP32-module, getoond in Figuur 1, terwijl het eenvoudige schema is afgebeeld in Figuur 2. Dit board werd gekozen vanwege de hoge rekencapaciteit en het on-board geheugen, de lage kosten, het kleine formaat en de grote gebruikersgroep. Ik heb een 5 V step-down DC/DC converter gebruikt voor de voeding.
Voor het DMX-gedeelte zijn twee TTL-DMX converters, compleet met connectoren, online te vinden (Figuur 3), maar tegen een zeer hoge prijs vergeleken met die van de andere componenten. We hebben daarom besloten om twee TTL-naar-RS-485 converters (Figuur 4) en twee female 3-pin XLR paneelconnectoren te gebruiken. Tot slot hebben we een DC paneel voedingsconnector nodig en een plastic behuizing om het geheel in te bouwen.
Verbindingen maken: Vereenvoudigd schema ontwerp
Ik heb oorspronkelijk een printplaat gemaakt voor dit project, waarbij de 30-pins versie van de ESP32 is inbegrepen (zie Figuur 5), maar de eenvoud van de schakeling maakt het mogelijk om het project ook zonder printplaat uit te voeren, door in plaats daarvan de verbeterde 38-pins module te gebruiken. Het aansluitschema staat in Figuur 6. Laten we beginnen met het voedingsgedeelte. De op het paneel gemonteerde DC plug wordt aangesloten op de ingang van de DC/DC converter. De 5 V uitgang hiervan wordt verbonden met VIN op de ESP32 module (pin 19) en met de VCC-pinnen van beide RS-485 modules. Dezelfde verbinding moet worden gemaakt voor de GND-pinnen van de drie boards, die worden verbonden met de massa van de DC/DC converter.
Wat de signalen betreft, elke module heeft drie ingangen: De RE en DE pinnen van module A moeten worden verbonden met IO4 (pin 26) van de ESP32 module, terwijl de DI pin van de A transceiver moet worden verbonden met IO17 (pin 28) van de ESP32. De uitgang van elke transceiver moet worden aangesloten op een XLR-connector als volgt: pinnen A en B van de MAX485 moeten worden verbonden met respectievelijk pin 3 en pin 2 van de connector. Pin 1 van de connector kan worden verbonden met massa.
Sketch
De sketch voor dit project is gebaseerd op de ArtNetWiFiNeopixel GitHub sketch van rstephan en Mitch Weisbord's DMX_Write. Je kunt de sketch van dit project rechtstreeks downloaden van de GitHub repository van dit project.
Zoals altijd zullen we het als geheel analyseren, verdeeld in verschillende listings, en enkele belangrijke punten van de code bespreken. Listing 1 laat de gebruikte bibliotheken zien samen met de netwerkconfiguratie. Laten we er wat dieper op ingaan. Verschillende variabelen die nuttig zijn voor het compileren van de sketch zijn opgenomen in de Arduino.h bibliotheek, samen met de toevoeging van verschillende andere bibliotheken die basisfunctionaliteitsklassen bevatten, zoals stdlib, stdio, string, enz.
#include <Arduino.h>
#include <esp_dmx.h>
#include "ArtnetWifi.h"
#include <WiFi.h>
#include <ESPmDNS.h>
#include <WiFiUdp.h>
#include <ArduinoOTA.h>
//#define DHCP_DISABLED
#ifdef DHCP_DISABLED
IPAddress local_IP(192, 168, 1, 154);
IPAddress gateway(192, 168, 1, 1);
IPAddress subnet(255, 255, 255, 0);
IPAddress primaryDNS(192, 168, 1, 1); //optional
IPAddress secondaryDNS(1, 1, 1, 1); //optional
#endi
De esp_dmx.h bibliotheek bevat de instructies voor het verzenden van signalen naar de TTL-to-RS-485 module.
Dan hebben we de ArtnetWifi.h en WiFi.h bibliotheken voor respectievelijk het ontvangen van ArtNet packets en het beheren van de verbinding met het netwerk. De bibliotheken ESPmDNS.h, WiFiUdp.h en ArduinoOTA.h zijn voor het draadloos laden van firmware (OTA) en het opgeven van een netwerknaam voor de interface met behulp van het mDNS-protocol.
Dan volgt een #define DHCP_DISABLED: met deze instructie kiezen we of we een statisch IP-adres instellen of dat we alles delegeren aan de DHCP-server (de regel uitcommentariëren). Als we besluiten om een statisch IP adres te gebruiken, is het noodzakelijk om alle gerelateerde parameters op te geven zoals IP adres, de gateway en het subnet waartoe het behoort. Je kunt bovendien de DNS-servers kiezen. Als we ervoor kiezen om een dynamisch IP te gebruiken, is het nog steeds nuttig (maar niet essentieel) om het IP-adres van de ESP32 te weten.
Tabel 1: Aansluitingen van ESP32 naar RS-485-A module.
ESP32 Pin | MAX485 Pin |
---|---|
4 | DE |
17 | DI |
4 | RE |
Tabel 2: Aansluitingen van ESP32 naar RS485-B module
ESP32 Pin | MAX485 Pin |
---|---|
21 | DE |
19 | DI |
21 | RE |
Daar leggen we later meer over uit. Listing 2 toont de globale variabelen. De objecten met betrekking tot de WiFiUDP en ArtnetWifi bibliotheken worden in eerste instantie aangemaakt. Vervolgens worden in de stringconstanten ssid en password de naam van het Wi-Fi-netwerk waarmee de ESP verbinding maakt en het wachtwoord gedefinieerd. De ESP pinnen waarop beide RS-485 transceivers worden aangesloten staan in Tabel 1 en Tabel 2.
WiFiUDP UdpSend;
ArtnetWifi artnet;
const char* ssid = "MyArtNetNetwork";
const char* password = "MyArtNetNetwork";
/* Laten we eerst de hardware pinnen definiëren die we gebruiken met onze ESP32. We moeten definiëren welke pin gegevens verzendt en welke pin gegevens ontvangt. DMX-schakelingen moeten ook vaak worden ingesteld wanneer we gegevens verzenden en wanneer we gegevens ontvangen. We kunnen dit doen door een enable pin te definiëren.*/
int transmitPinA = 17;
int receivePinA = 16; //Not connected
int enablePinA = 4;
int transmitPinB = 21;
int receivePinB = 16; //Not connected
int enablePinB = 19;
/* Controleer goed of deze pinnen compatibel zijn met je ESP32! Sommige ESP32's, zoals de ESP32-WROVER serie, staan niet toe dat je gegevens leest of schrijft op pinnen 16 of 17, dus het is altijd goed om de handleidingen te lezen.*/
/* Laten we vervolgens beslissen welke DMX-poort we gaan gebruiken. De ESP32 heeft 2 of 3 poorten. Poort 0 wordt meestal gebruikt om seriële gegevens terug te sturen naar je seriële monitor, dus die poort moeten we niet gebruiken. Laten we poort 1 gebruiken! */
dmx_port_t dmxPortA = 1;
dmx_port_t dmxPortB = 2;
/* Nu willen we onze DMX-gegevens ergens opslaan. Omdat een enkele packet van DMX-gegevens tot 513 bytes lang kan zijn, willen we dat onze array minstens zo lang is. Deze bibliotheek weet dat de maximale DMX pakketgrootte 513 is, dus we kunnen de arraygrootte invullen met DMX_PACKET_SIZE. */
byte dataA[DMX_PACKET_SIZE];
byte dataB[DMX_PACKET_SIZE];
//ArtNet settings const int startUniverse = 0;
// CHANGE FOR YOUR SETUP most software this is 1,
//some software send out artnet first universe as 0.
const int maxUniverses = 2;
const int numberOfChannels = 1024;
bool universesReceived[maxUniverses];
bool sendFrame = 1;
int previousDataLength = 0;
Voor elk van de modules hebben we de ontvangstpin op 16 gezet, hoewel deze niet echt zijn aangesloten en geen nut hebben in ons ontwerp. Verder zijn de te gebruiken ESP32 poorten gespecificeerd. We gebruiken poort 1 en 2 voor respectievelijk universe A en universe B. De gegevens voor de twee DMX-universes worden ingekapseld in twee byte-arrays, dataA en dataB, waarvan de grootte wordt gedefinieerd in DMX_PACKET_SIZE (gedefinieerd in esp_dmx.h met een waarde van 513). Tenslotte worden alle variabelen gedefinieerd die worden gebruikt voor het verwerken van ArtNet pakketten.
Dan is er de constante startUniverse. Deze geeft aan vanuit welk universum we willen beginnen met het beschouwen van gegevens. Deze moet worden aangepast als we van plan zijn een installatie te maken met meerdere ontvangers uit verschillende universes. Het kan ook nodig zijn om deze aan te passen in gevallen waarin het programma dat packets verstuurt een nummering heeft die begint met 1 in plaats van 0. Vervolgens worden constanten gedefinieerd met betrekking tot het maximale aantal universes, kanalen en andere variabelen die worden gebruikt om toestanden en proceslussen te bewaken.
Listing 3 toont de functie setup(). De seriële poort wordt eerst geïnitialiseerd op 115.200 bits per seconde om debuggen van het board mogelijk te maken, zoals het verifiëren van het verkregen IP. Vervolgens wordt het netwerk geconfigureerd (DHCP of statisch, afhankelijk van de keuze in listing 1). Als er een fout optreedt, wordt er een bericht verzonden via de seriële poort. Als alles goed gaat, wordt het IP van het board naar de seriële poort verstuurd. Vervolgens wordt de hostnaam ESP32-ArtNetto-DMX-Converter ingesteld, die wordt weergegeven in de Board Manager sectie van de verschillende IDE's. Deze functie is erg handig om een apparaat te kunnen herkennen tussen vele apparaten in een "vloot". Vervolgens wordt OTA firmware upgrades geïnitialiseerd en daarna komt de ArtNet bibliotheek.
void setup() {
/* Start the serial connection back to the computer so that we can log
messages to the Serial Monitor. Let's set the baud rate to 115200. */
Serial.begin(115200);
// Setup wifi
WiFi.mode(WIFI_STA);
#ifdef DHCP_DISABLED
//Comment to use DHCP instead of static IP
if (!WiFi.config(local_IP, gateway, subnet, primaryDNS, secondaryDNS)) {
Serial.println("STA Failed to configure");
}
#endif
WiFi.begin(ssid, password);
delay(1000);
Serial.println("\nConnecting");
while (WiFi.status() != WL_CONNECTED) {
Serial.print(".");
delay(100);
}
Serial.println("\nConnected to the WiFi network");
Serial.print("Local ESP32 IP: ");
Serial.println(WiFi.localIP());
// Port defaults to 3232
// ArduinoOTA.setPort(3232);
// Hostname defaults to esp3232-[MAC]
ArduinoOTA.setHostname("ESP32-ArtNet-to-DMX-Converter");
// No authentication by default
// ArduinoOTA.setPassword("admin");
// Password can be set with it’s md5 value as well
// MD5(admin) = 21232f297a57a5a743894a0e4a801fc3
// ArduinoOTA.setPasswordHash("21232f297a57a5a743894a0e4a801fc3");
ArduinoOTA
.onStart([]() {
String type;
if (ArduinoOTA.getCommand() == U_FLASH)
type = "sketch";
else // U_SPIFFS
type = "filesystem";
// NOTE: if updating SPIFFS this would be the
// place to unmount SPIFFS using SPIFFS.end()
Serial.println("Start updating " + type);
})
.onEnd([]() {
Serial.println("\nEnd");
})
.onProgress([](unsigned int progress, unsigned int total) {
Serial.printf("Progress: %u%%\r", (progress / (total / 100)));
})
.onError([](ota_error_t error) {
Serial.printf("Error[%u]: ", error);
if (error == OTA_AUTH_ERROR)
Serial.println("Auth Failed");
else if (error == OTA_BEGIN_ERROR)
Serial.println("Begin Failed");
else if (error == OTA_CONNECT_ERROR)
Serial.println("Connect Failed");
else if (error == OTA_RECEIVE_ERROR)
Serial.println("Receive Failed");
else if (error == OTA_END_ERROR)
Serial.println("End Failed");
});
ArduinoOTA.begin();
artnet.setArtDmxCallback(onArtNetFrame);
artnet.begin("ESP32-ArtNet-to-DMX-Converter");
/* Set the DMX hardware pins to the pins that we want to use. */
dmx_set_pin(dmxPortA, transmitPinA, receivePinA, enablePinA);
dmx_set_pin(dmxPortB, transmitPinB, receivePinB, enablePinB);
/* Nu kunnen we het DMX stuurprogramma installeren! We vertellen hem welke DMX poort hij moet gebruiken en welke interrupt prioriteit hij moet hebben. Als je niet zeker weet welke interrupt prioriteit je moet gebruiken, kun je de macro DMX_DEFAULT_INTR_FLAG gebruiken om de interrupt in te stellen op de standaard instellingen.*/
dmx_driver_install(dmxPortA, DMX_DEFAULT_INTR_FLAGS);
dmx_driver_install(dmxPortB, DMX_DEFAULT_INTR_FLAGS);
Tenslotte worden de ESP-uitgangspinnen en seriële poort ingesteld die aan elke transceiver worden toegewezen en wordt de prioriteit van de interrupts die worden gebruikt gedefinieerd. Listing 4 bevat het hele deel met betrekking tot de functie onArtNetFrame(). Eerst wordt gecontroleerd of de waarde van elk van de ontvangen universes behoort tot de universes waarin we geïnteresseerd zijn. Als dit het geval is, wordt de vlag van de corresponderende cel van de array op 1 gezet. Vervolgens wordt gecontroleerd of alle vereiste universes zijn ontvangen; zo niet, dan wordt de functie afgesloten. Vervolgens controleren we of elk van de ontvangen kanalen behoort tot universe A of universe B en wordt opgenomen in de corresponderende matrix.
void onArtNetFrame(uint16_t universe, uint16_t numberOfChannels,
uint8_t sequence, uint8_t* dmxData) {
sendFrame = 1;
// Store which universe has got in
if ((universe - startUniverse) < maxUniverses)
universesReceived[universe - startUniverse] = 1;
for (int i = 0; i < maxUniverses; i++) {
if (universesReceived[i] == 0) {
//Serial.println("Broke");
sendFrame = 0;
break;
}
}
// read universe and put into the right array of data
for (int i = 0; i < numberOfChannels; i++) {
if (universe == startUniverse)
dataA[i + 1] = dmxData[i];
else if (universe == startUniverse + 1)
dataB[i + 1] = dmxData[i];
}
previousDataLength = numberOfChannels;
dmx_write(dmxPortA, dataA, DMX_MAX_PACKET_SIZE);
dmx_write(dmxPortB, dataB, DMX_MAX_PACKET_SIZE);
dmx_send(dmxPortA, DMX_PACKET_SIZE);
dmx_send(dmxPortB, DMX_PACKET_SIZE);
dmx_wait_sent(dmxPortA, DMX_TIMEOUT_TICK);
dmx_wait_sent(dmxPortB, DMX_TIMEOUT_TICK);
// Reset universeReceived to 0
memset(universesReceived, 0, maxUniverses);
}
Vervolgens worden de gegevens van elk universe in de respectievelijke zendbuffers geplaatst en wordt gewacht tot de verzending is voltooid. Tot slot worden de flags met betrekking tot de ontvangen universes gereset. Listing 5 is de kortste en bevat alleen de loop() functie. Binnen de lus wordt gecontroleerd of de ESP correct is aangesloten op het netwerk en als dat het geval is, worden ArtNet pakketten ontvangen en verwerkt.
void loop() {
if ((WiFi.status() == WL_CONNECTED)) {
artnet.read();
}
}
Assemblage: Van prototype tot uiteindelijke bouw
Nu is het tijd om de converter op te bouwen. Volg gewoon de eerder getoonde aansluitingen in Figuur 6. Vergeet niet dat je bij de RS-485 transceivers de DE en RE pinnen moet overbruggen. Bereid vervolgens de XLR-connectoren voor door de drie draden te solderen (Tabel 3).
Tabel 3: RS485 Module naar XLR verbindingen.MAX485 Pin | DMX Signaal | XLR Connector Pin |
---|---|---|
GND | Gnd/Shield | 1 |
A | Data+ | 3 |
B | Data- | 2 |
Voor elke connector boor je in het plastic doosje twee gaten voor de schroeven en een groter gat voor de socket. Boor het laatste gat voor de DC connector waaraan je eerder twee draden hebt gesoldeerd. Verbind nu de draden van de DC plug met de ingang van de DC-DC converter. De uitgang hiervan wordt verbonden met de voeding van de ESP32 en de twee transceivers, met behulp van jumpers en een paar schroefklemmen. Laad de firmware, doe de behuizing dicht, sluit de voeding aan en ga dan verder met de configuratie van de besturingssoftware.
Software Configuratie: ArtNet Fixtures met MagicQ
Er bestaan veel programma's om ArtNet systemen te beheren: open source, freemium en betaald. Onder de gratis software (of gratis voor niet-commercieel gebruik) die we menen te moeten aanbevelen is ongetwijfeld MagicQ, geproduceerd door Chamsys. In dit geval zullen we ons beperken tot het gebruik van MagicQ. Het is een cross-platform (Windows, Mac en Ubuntu) gratis te downloaden programma waarmee je tot 256 universes kunt besturen, pixel mapping kunt beheren en HD video kunt afspelen op maximaal 8 lagen.
We registreren ons op de website en downloaden het installatieprogramma. Zodra de installatie is voltooid, hebben we verschillende applicaties van de suite: Open MagicQ PC en wacht tot een scherm verschijnt, zoals in Figuur 7. Klik op Simple generic console. In het nieuwe scherm dat verschijnt, gaan we naar het menu en selecteren Setup → DMX I/O. In het scherm dat verschijnt, zoals in Figuur 8, kunnen we de uitgangen van de verschillende DMX-universes instellen. Voor het Out Type item kiezen we Art-Net en Art 0 als Out Uni item. Het kritieke deel van de configuratie komt wanneer we de Unicast en Unicast2 items moeten kiezen.
Deze ingangen worden gebruikt om aan te geven naar welke IP-adressen we onze packets gaan zenden. Stel dat we verbonden zijn met een netwerk met een 24-bits subnet (255.255.255.0) en daarom IP XXX.XXX.XXX.255 willen versturen, dan kunnen we dit laatste adres invoeren en er zeker van zijn dat alle apparaten in het netwerk packets zullen ontvangen. Als we daarentegen willen voorkomen dat alle apparaten in het netwerk overspoeld worden, kunnen we direct het IP van het betreffende apparaat instellen, maar in dit geval raden we aan om een statisch IP te gebruiken.
We hebben deze configuratie toegepast op het ArtNet 2 universe, dat hetzelfde als Universe 1 gebruikt als gegevensbron, door het in te stellen in de kolom copy. Je kunt zien dat we het localhost adres van de PC hebben ingesteld in het Unicast 2 veld. We hebben deze configuratie ingevoerd zodat we de werkelijke packet verzending kunnen controleren in debug-software zoals ArtNetominator, die je hier kunt downloaden. We hebben deze optie niet ingevoerd voor Universum 1 omdat, door IP broadcast te gebruiken, packets automatisch "teruggaan" naar de PC.
Ga nu met de cursor naar rechtsboven en klik op Single, de schuifregelaars verschijnen zoals in Figuur 9.
Om de packet verzending te starten, selecteren we enable en bevestigen dit. Laten we nu een eenvoudige configuratie van de opstelling uitvoeren, door ongeveer halverwege het scherm naar links te gaan en op Testshow te klikken. Op het scherm zien we een lange reeks cellen die de fabrikanten van de apparatuur vertegenwoordigen, zoals in Figuur 10. We selecteren de fabrikant en alle beschikbare voorgeconfigureerde modellen verschijnen.
Nadat we onze keuze hebben gemaakt, zien we een venster zoals in Figuur 11, waarin we ofwel individuele schuifregelaars voor basiscommando's hebben, of een aantal macro's die een mix van commando's weergeven over een bepaalde periode. Test de werking om er zeker van te zijn dat de apparaten en software correct zijn geconfigureerd. Om de mogelijkheden van de applicatie ten volle te benutten, raden we aan om online trainingssessies te volgen die gratis toegankelijk zijn.
ArtNet naar DMX converter: laatste opmerkingen
We hebben de werking van het systeem onder verschillende omstandigheden getest en vonden verschillende problemen, afhankelijk van de gebruikte access points. Het kan zelfs gebeuren dat - afhankelijk van het access point - de kaart na een paar uur in een fouttoestand komt en we hem handmatig moeten resetten. Dit kan gebeuren, aangezien dit een hobbyistische oplossing is, maar door van apparaat te wisselen wordt het probleem opgelost, waardoor de kaart enkele dagen probleemloos werkt. Verder raden we aan om een speciaal netwerk te gebruiken om mogelijke systeemcrashes te voorkomen.
DMX Upgrade: Componentenlijst
Condensatoren
- C1, C4 = 100 nF, keramisch
- C2, C3 = 220 µF, 16 V, elektrolytisch
- C5 = 10 µF, 63 V, elektrolytisch
Modules
- U1, U2 = TTL naar to-RS-485 converter
- U3 = ESP32
- U4 = MP1584 step-down DC/DC converter, 5 V
Diversen
- DMX1, DMX2 = XLR connector, female, printplaat type
- PWR = DC connector, female, printplaat type
- 4× 2-pin strip connector, female, pitch 2.54 mm
- 4× 4-pin strip connector, female, pitch 2.54 mm
- 2× 15-pin strip connector, female, pitch 2.54 mm
- 4× 2-pin strip connector, male, pitch 2.54 m
- PCB S1716 (102 × 61 mm)
Opmerkingen van de redactie: Geïnteresseerd in ESP32 en zelfbouw projecten? Dit project verscheen oorspronkelijk in Elettronica IN.
Discussie (0 opmerking(en))