Hi there! I've built a MIDI to DMX converter around an Arduino Nano board and written a simple program that converts MIDI note and velocity information into DMX light Channel and Intensity information. It's largely based on this project: MIDI to DMX using Arduino with a few slight changes - I used an H11L1 IC for the MIDI side, added some LEDs for power and MIDI data indicators. The code uses DmxSimple.h and MIDI.h libraries.
After some troubleshooting I've got the project built and working, but I had to add a bit of code that doesn't make any sense to me and I'm trying to figure out why it's needed and/or if I did something wrong.
I'm controlling two lights with four personalities each (1: Intensity 2: Red 3: Green 4: Blue), so I'm using DMX Channels 1-8. My code turns the intensity of both lights to 255 when it boots up, then cycles through each color light to test that they're all working.
The code then translates MIDI Note and Velocity info to DMX Channel and Intensity info respectively. So if you play MIDI note 2 on a keyboard (or through my DAW) at velocity 127 it turns on light channel 2 (red on light fixture 1) at intensity 255. All well and good, works like it should.
However...
For the longest time I couldn't get the second light fixture to work. Eventually I discovered that after I played MIDI note 12, so, sending some information, any value, to DMX channel 12, then the second light would work without any further issue. I've added a line to turn channel 12 to full intensity when the device boots up, and now it works as originally expected. This makes no sense to me, since DMX channel 12 is out of the scope of both the code I've written and the fixture I'm using.
Here's my code:
// MIDI to DMX converter / controller
#include <MIDI.h>
#include <DmxSimple.h>
#include <avr/pgmspace.h>
#include <millisDelay.h>
// Define global variables
#define POWER_LED 3
#define TEMPO_LED 8
#define DMX_OUT 13
#define DMXCHANNELS 8
// Local variables
bool initialized;
bool tempoLedOn;
int tempoLedCycles;
millisDelay ledDelay1;
millisDelay ledDelay2;
millisDelay ledDelay3;
millisDelay ledDelay4;
millisDelay ledDelay5;
millisDelay ledDelay6;
millisDelay ledDelay7;
// Create instance of MIDI library with default name, serial port and settings
MIDI_CREATE_DEFAULT_INSTANCE();
// Program setup, runs once:
void setup() {
// Setup LEDs
pinMode(POWER_LED, OUTPUT);
pinMode(TEMPO_LED, OUTPUT);
digitalWrite(POWER_LED, HIGH);
digitalWrite(TEMPO_LED, HIGH);
// Timers for boot cycle/light test
ledDelay1.start(1000);
ledDelay2.start(1100);
ledDelay3.start(1200);
ledDelay4.start(1300);
ledDelay5.start(1400);
ledDelay6.start(1500);
ledDelay7.start(1600);
// Setup MIDI behavior
MIDI.begin(16); // Sets the MIDI channel to 16
MIDI.setHandleNoteOn(OnMidiNoteOn); // Sets the response to a 'Note On' MIDI event to the MIDINoteOn function
MIDI.setHandleNoteOff(OnMidiNoteOff); // Sets the response to a 'Note Off' MIDI event to the MIDINoteOff function
// Setup DMX behavior
DmxSimple.usePin(DMX_OUT);
DmxSimple.maxChannel(8);
// !!! ??? WHY DO I NEED THIS ??? !!! //
DmxSimple.write(12, 255);
// Turn on the lights to test them
DmxSimple.write(1, 255);
DmxSimple.write(2, 255);
DmxSimple.write(3, 255);
DmxSimple.write(4, 255);
DmxSimple.write(5, 255);
DmxSimple.write(6, 255);
DmxSimple.write(7, 255);
DmxSimple.write(8, 255);
}
// Program loop, runs continuously:
void loop() {
// Dim lights and tempo LED after a second
if (ledDelay1.justFinished()) {
digitalWrite(TEMPO_LED, LOW);
//DmxSimple.write(1, 255);
DmxSimple.write(2, 0);
DmxSimple.write(3, 0);
DmxSimple.write(4, 0);
//DmxSimple.write(5, 255);
DmxSimple.write(6, 0);
DmxSimple.write(7, 0);
DmxSimple.write(8, 0);
}
if (ledDelay2.justFinished()) {
digitalWrite(TEMPO_LED, HIGH);
DmxSimple.write(2, 255);
DmxSimple.write(6, 255);
}
if (ledDelay3.justFinished()) {
digitalWrite(TEMPO_LED, LOW);
DmxSimple.write(2, 0);
DmxSimple.write(6, 0);
}
if (ledDelay4.justFinished()) {
digitalWrite(TEMPO_LED, HIGH);
DmxSimple.write(3, 255);
DmxSimple.write(7, 255);
}
if (ledDelay5.justFinished()) {
digitalWrite(TEMPO_LED, LOW);
DmxSimple.write(3, 0);
DmxSimple.write(7, 0);
}
if (ledDelay6.justFinished()) {
digitalWrite(TEMPO_LED, HIGH);
DmxSimple.write(4, 255);
DmxSimple.write(8, 255);
}
if (ledDelay7.justFinished()) {
digitalWrite(TEMPO_LED, LOW);
DmxSimple.write(4, 0);
DmxSimple.write(8, 0);
}
// MIDI Read to for 'handler' functions
MIDI.read();
}
// Function for MIDI Note On behavior:
void OnMidiNoteOn(byte channel, byte pitch, byte velocity) {
if (pitch != 1 && pitch != 5) {
//DmxSimple.write(1, 255);
//DmxSimple.write(5, 255);
DmxSimple.write(pitch, velocity * 2);
}
digitalWrite(TEMPO_LED, HIGH);
}
// Function for MIDI Note Off behavior:
void OnMidiNoteOff(byte channel, byte pitch, byte velocity) {
if (pitch != 1 && pitch != 5) {
//DmxSimple.write(1, 255);
//DmxSimple.write(5, 255);
DmxSimple.write(pitch, 0);
}
digitalWrite(TEMPO_LED, LOW);
}
I also tried removing all the boot-up light-check code in case that was somehow causing the problem, but it didn't help, I still needed to send MIDI note 12 info to the device before channels 5-8 would work. Similarly, reassigning the light fixtures' channels didn't make a difference - the problem followed whichever light was assigned to channels 5-8.
Hoping someone out there knows what I did wrong and/or what I could do more right?
Thanks!