f0dmx

here is how i built a wireless isolated dmx controller that takes osc input. the box uses an esp8266 to create a wifi access point that one can connect to with a laptop (or phone or whatever). opensound control messages sent to the box are converted into standard dmx commands. multiple clients can be connected and send dmx commands at the same time.

f0dmx 1

f0dmx 2

below is arduino code for the esp8266, bom, the kicad schematics and some supercollider test code.

// * install OSC from https://github.com/CNMAT/OSC
// * install WiFiManager from https://github.com/tzapu/WiFiManager
// * install LXESP8266UARTDMX from https://github.com/claudeheintz/LXESP8266DMX
// * select board: "Generic ESP8266 Module" 160 MHz

#include <ESP8266WiFi.h>
#include <DNSServer.h>
#include <ESP8266WebServer.h>
#include <ESP8266mDNS.h>
#include <Ticker.h>
#include <WiFiManager.h>
#include <WiFiUdp.h>
#include <OSCMessage.h>
#include <OSCData.h>
#include <LXESP8266UARTDMX.h>

#define CONFIG_PIN 0   //gpio0 to gnd to reset wifi
#define PORT 19998  //EDIT osc input port
#define OUTPORT 57120 //EDIT osc output port (only used at startup for announcement)
char *espname = "f0dmx";

Ticker ticker;
IPAddress outIp;
WiFiUDP Udp;

void setup() {
  delay(10);
  pinMode(CONFIG_PIN, INPUT);
  pinMode(LED_BUILTIN, OUTPUT);
  ticker.attach(0.6, tick);

  WiFi.hostname(espname);
  wifi_station_set_hostname(espname);
  WiFiManager wifiManager;
  wifiManager.setAPCallback(configModeCallback);
  if (!wifiManager.autoConnect(espname)) {
    ESP.reset();
    delay(1000);
  }
  MDNS.begin(espname);  //make .local work
  outIp = WiFi.localIP();
  Udp.begin(PORT);
  OSCMessage msg("/ready"); //announcement
  msg.add(espname);
  msg.add(int(outIp[0]));
  msg.add(int(outIp[1]));
  msg.add(int(outIp[2]));
  msg.add(int(outIp[3]));
  msg.add(PORT);
  outIp[3] = 255;  //use broadcast ip x.x.x.255
  Udp.beginPacket(outIp, OUTPORT);
  msg.send(Udp);
  Udp.endPacket();
  yield();
  msg.empty();

  ESP8266DMX.startOutput();

  ticker.detach();
  digitalWrite(LED_BUILTIN, LOW);   //debug
}

void tick() {
  int state = digitalRead(LED_BUILTIN);
  digitalWrite(LED_BUILTIN, !state);  //debug
}
void configModeCallback(WiFiManager *myWiFiManager) {
  ticker.attach(0.15, tick);
}

void dmx(OSCMessage &msg) {
  int chan, value;
  for (byte i = 0; i < msg.size(); i = i + 2) {
    chan = getIntCast(msg, i);
    value = getIntCast(msg, i + 1);
    ESP8266DMX.setSlot(chan, value);
  }
}

int getIntCast(OSCMessage &msg, int index) {  //support for both integers and floats
  if (msg.isInt(index)) {
    return msg.getInt(index);
  }
  return int(msg.getFloat(index));
}

void start(OSCMessage &msg) {
  ESP8266DMX.startOutput();
}

void stop(OSCMessage &msg) {
  ESP8266DMX.stop();
}

void loop() {
  OSCMessage oscMsg;
  int packetSize = Udp.parsePacket();
  if (packetSize) {
    while (packetSize--) {
      oscMsg.fill(Udp.read());
    }
    if (!oscMsg.hasError()) {
      oscMsg.dispatch("/dmx", dmx);
      oscMsg.dispatch("/start", start);
      oscMsg.dispatch("/stop", stop);

      tick();
    }
  }

  //--wifi
  if (digitalRead(CONFIG_PIN) == LOW) {  //reset pin
    WiFiManager wifiManager;
    wifiManager.resetSettings();
    wifiManager.setAPCallback(configModeCallback);
    wifiManager.autoConnect(espname);
    ticker.detach();
    digitalWrite(LED_BUILTIN, LOW); //debug
  }
}

bill of material...

1       dcdc            ROE-0505S       reichelt
1       xlr female      XLR 3KU         reichelt
1       optocoupler     6N 137          reichelt
1       ic              SN 75176BP      reichelt
1       box             BOPLA KS 420    reichelt
1       resistor        10K
1       resistor        470
3       resistor        10
1       resistor        120
2       cap             10uF
1       cap             220uF
1       regulator       LF 33 CV
1       micro           ESP8266-01
1       socket          4x2
1       push button
1       usb cable

f0dmx kicad schematics

example of how to send osc from supercollider to the f0dmx box.

//make sure you are connected to the same wifi network as f0dmx
n= NetAddr("f0dmx.local", 19998);  //the ip and port of the f0dmx box
n.sendMsg(\dmx, 9, 255)  //dmx channel 9, value 255
n.sendMsg(\dmx, 9, 0)
n.sendMsg(\dmx, 7, 100)  //dmx channel 7, value 100
n.sendMsg(\dmx, 7, 0)

n.sendMsg(\stop)  //usually not needed
n.sendMsg(\start)

update 180620: cast floats to integers (getIntCast), increased electrolytic cap value from 100 to 220uF
update 181212: simplified wifi setup with the wifimanager library