Reaper DAW triggering Arduinos

Hi,

I would like to know if it's feasible (and if so, how to do it) to have my Reaper's play button acting as a trigger to start several Arduinos programs at the same time and the stop button to stop them.

I need to have them run their programs from the beginning of a track and following it in sync.

Thanks in advance for your help.

Reaper, like most DAWs, can start, stop and synch with external MIDI devices. An Arduino can be programmed to act as an external MIDI device. You won't actually be starting the program on the Arduino(s) because it will have to be running all the time in order to pick up the MIDI commands, but you can arrange for a MIDI command to start a sequence of actions.

So I guess it's possible but probably not exactly easy, though that will also depend on what exactly you want the Arduino(s) to do in synch with Reaper. How much Arduino programming and electronics experience do you have?

Steve

@slipstick Thanks for these explanations !

What I want to do is to have several Arduinos controlling motors and I need these motors to be triggered at certains points of my sound track. That's why I want to have everything to be launch at the same time.

It can also be some sort of button triggering the playback in Reaper and the Arduinos as well. Something like this: https://www.youtube.com/watch?v=ntjO0XXJPhE but with a method to trigger other Arduinos at the same time.

I don't know which one is the easiest or if there is a better way.

To answer you, I'm a beginner. I took some Arduino courses but it's been a while and I forgot a lot of stuff.

How closely synchronised to the sound track do the actions of the Arduinos need to be? If it's just within a second or two you could probably get away with them free running, just using internal timing. In that case you just need a start/stop switch that operates both Reaper play and the Arduinos. Not too difficult to set up.

OTOH if they want to be accurate I would probably do it using MIDI. In Reaper you could set up an additional MIDI track with silent "notes" at all the appropriate trigger points and send that track's MIDI out to the Arduinos to get them each responding to their commands at exactly the right time. There are MIDI libraries that make MIDI access for Arduinos reasonably easy and the hardware is easy enough.

Sounds interesting and with a number of different ways to attack it depending on the precise specifications.

Steve

I would use Reaper to send some control messages to the Arduinos. They listen to the MIDI channel and act on the control message. Note with turning on a motor their will be a bit of inertia so you might want to trigger a beat or two before you want to see the effect.

@slipstick One second or two seems to be quite a bit to work along the sound track... Unless I move my sound track to start one second or two later. Do you think it could work? If so and if this setup is easier, I'll go for that.

The "piano roll timeline triggering" was my first option but it looks way more difficult to do (for accelerations, speeds, direction, etc). Also, I will already have my octophonic sound track playing in Reaper plus 8 channels processing real time audio at the same time in Reaper. So if I add 8+ more MIDI tracks handling my Arduinos I think my 2008 macbook pro will explode. And it also means that I would need to have my Arduinos constantly plugged in my computer...

@Grumpy_Mike See what I said above. And about the delay induced by inertia I will take that into account in my timings.

Thanks for your help guys!

The "piano roll timeline triggering" was my first option but it looks way more difficult to do (for accelerations, speeds, direction, etc)

Why do you say that? I think you are wrong here.

So if I add 8+ more MIDI tracks handling my Arduinos I think my 2008 macbook pro will explode.

No the MIDI traffic over those links will be very sparse.

And it also means that I would need to have my Arduinos constantly plugged in my computer.

Why, if you don't plug them in then they will simply just not work.

Trying to synchronise two free running systems with just a start signal is not going to work, they will drift out of sync in an unrepeatable way due to temperature variations. Do some tests and see for yourself.

There's no reason why you would need 8+ extra tracks (though that is unlikely to be a problem). If your commands to the Arduinos are fairly simple then there's nothing stopping you from using a number of different MIDI commands on a single track. But at some point you are going to have to define exactly what commands you're going to want to send to the Arduinos and what they're doing with them.

And for that matter how you sure are you that you really need lots of Arduinos. It's possible to drive quite a few things with just one of them.

But face it if you want the Arduino(s) actions to be synchronised with sounds playing on the computer that isn't going to happen unless they are connected in some way to the computer.

Steve

@Grumpy_Mike I said that because I'm a beginner... Also, I don't understand what you mean by "drifting out of sync due to temperature variations". Arduinos have an internal clock right? So why would the timings in my code be messed up? I'm confused.

@slipstick You're right about the number of tracks. I got my wires crossed. If you don't consider the Reaper playback part, the commands I want my Arduinos to execute are pretty simple (that's why I already am able to code them myself, more or less (I don't think they're really optimized...)). It's just basic motor controls + LEDs lighting at the same time. But that said, I truly need one Arduino per "machine".

I will try to explain what I want to achieve in a more detailed way:

-I have an octophonic sound track in Reaper. -I want to build 8 modular machines. By "modular" I mean that I will make 8 "bases" with an Arduino, a guitar preamp and a DI box in each one of them and then make several interchangeables "trays" to put and connect on top of them. They will have motors (solenoides, stepper, servo, DC, etc, depending of the needs of each machine) I want to connect to the Arduino and piezo mics to the preamp in this base. -Picked up sounds will go from my DI boxes into my audio interface, to 8 channels in Reaper handling them in real time and mapping them into the same outputs as the sound track. -These 8 machines will be triggered at certains points of the sound track, therefor make a sound which will be added to my sound track and be transmitted to the speakers.

That's why my first idea was to have an Arduino master connected to my computer to trigger the sound track in Reaper and launch the programs of all these 8 Arduino slaves at the same time.

I hope it's a bit more understandable...

The less wires, the better(but I'm setting aside RF or bluetooth transmissions for now as I don't want to make this more of a headache than it already is) . The more straight forward code and installation, the better.

I begin to get lost with all the possibilities to achieve that, and I don't have so much time to complete this project and I really don't know how to separate the wheat from the chaff to be the most efficient possible...

Also, I don’t understand what you mean by “drifting out of sync due to temperature variations”. Arduinos have an internal clock right? So why would the timings in my code be messed up?

The Arduino’s clock is either a crystal oscillator or a resonator. Both have a temperature coefficient, but the resonator is greater. This means when you zoom into the exact frequency of the Arduino’s clock you will find it will change slightly with temperature. This means it can never be relied upon to produce the same time delays from one run to the next. This difference gets bigger the longer the system has run from a synchronisation event. In effect it is exactly the same as when you tried to synchronise a tape recorder and a movie film projector. Just like that the two systems will drift. It is a fundamental law of physics that free running oscillators will drift unless locked together.

I begin to get lost with all the possibilities to achieve that, and I don’t have so much time to complete this project and I really don’t know how to separate the wheat from the chaff to be the most efficient possible

Keep it simple and don’t add too many features at one go. Start simple and do as much as you can in the time you have.

At the moment I’m guessing that each of the Arduino machines will have it’s own fixed sequence of actions which just needs to be started and perhaps stopped at specific points in the playback. If so then you can just use a different “note” for each machine and your trigger track will then contain long “notes” to cover the times when each machine is to be active. The code needed to receive MIDI commands is not trivial but there are many examples and decent libraries available (and the project is interesting enough that you’ll probably have plenty of help ;))

You could make it more complex with a whole series of commands that each “machine” needs to obey but that’s probably overkill (maybe for a later project).

But either way if you’re already running sound from DI boxes back to the computer then you could always use cables with more cores and run both sound and MIDI on them so you only have a single cable to each machine station.

I’d probably start by making a single Arduino “machine” that just receives MIDI note on/note off commands (a specific note on a specific channel) and switches an LED on and off. Once you have that working you’re almost there.

Steve

@Grumpy_Mike I didn't know that. Thanks for this clear explanation.

Grumpy_Mike: Keep it simple and don't add too many features at one go. Start simple and do as much as you can in the time you have.

That's what I'm trying to do.

slipstick: At the moment I'm guessing that each of the Arduino machines will have it's own fixed sequence of actions which just needs to be started and perhaps stopped at specific points in the playback. If so then you can just use a different "note" for each machine and your trigger track will then contain long "notes" to cover the times when each machine is to be active. The code needed to receive MIDI commands is not trivial but there are many examples and decent libraries available

You're right, that's exactly what I want to do. But do I absolutely need to go through Processing like in this video: https://www.youtube.com/watch?v=cZmtrPImZaI ? That's the only example I found of Reaper MIDI track sending informations to Arduino...

slipstick: I'd probably start by making a single Arduino "machine" that just receives MIDI note on/note off commands (a specific note on a specific channel) and switches an LED on and off. Once you have that working you're almost there.

I'will try that once I found how to make them communicate together.

slipstick: (and the project is interesting enough that you'll probably have plenty of help ;))

Well, that's what I was seeking with this thread (and some others threads elsewhere) but unfortunately I'm still a bit stuck for now. But thanks for your suggestions and starting points guys. :)

It shouldn't be nearly as complicated at the Reaper end as that video suggests. But since I've never actually done it I'd better test my theories myself before I tell you how easy it is;). Give me a few days, I don't have a lot of spare time just now.

Steve

slipstick: It shouldn't be nearly as complicated at the Reaper end as that video suggests. But since I've never actually done it I'd better test my theories myself before I tell you how easy it is;). Give me a few days, I don't have a lot of spare time just now.

Steve

That's really nice of you!! Thanks a lot, I genuinely appreciate your help!

Let me know. :)

Saynomore: That's the only example I found of Reaper MIDI track sending informations to Arduino...

I don't think you need examples of Reaper sending MIDI info to Arduino. Just

  • figure out how you connect Reaper to external MIDI devices through USB. Probably just set your dedicated track in Reaper to some midi channel no other instrument or device uses.
  • figure out how to read incoming data from the USB to Arduino as MIDI data.

An alternative to Arduino reading MIDI data through its USB is to build a separate midi connection for your Arduino, say with DIN contacts (old school MIDI standard). Then you need a USB to MIDI converter.

Since there are many audio interfaces with MIDI already incorporated and even if you don't have one of those the USB to MIDI converters are so cheap I was going with "proper" MIDI to make wiring simpler. There's no need to use bulky DIN plugs at the Arduino end as it's a custom build.

For me using MIDI over USB would be more of a pain. As the OP wants to send the signal in parallel to a number of different Arduinos you'd probably need a powered hub and you'd have USB cables trailing around the place when there's otherwise no need for a USB connection. But my way does mean building a little opto-isolator MIDI IN circuit for each Arduino.

As always there are many different ways to achieve something similar.

Steve

slipstick:
It shouldn’t be nearly as complicated at the Reaper end as that video suggests. But since I’ve never actually done it I’d better test my theories myself before I tell you how easy it is;). Give me a few days, I don’t have a lot of spare time just now.

Sorry, that took longer than I expected. I couldn’t find the optocoupler I thought I had so had to order more and then my laptop died so I had to fix that. Fortunately, when I did get to it, it was fairly simple, as I thought.

In Reaper you just need a single MIDI track then choose a different note for each function you need to control. You then add long notes to that track with the start of the note switching on the function and the end switching it off. That gives you up to 128 different functions you can control on each of 16 channels.

Each Arduino needs the standard MIDI IN circuit (a 6N138 optocoupler a diode and two resistors). I set mine up so the MIDI used software serial on pins 2/3 so I still had the hardware serial for debugging.

If you use the MIDI.h library the Arduino code is simple and fairly neat. The following example looks on channel 16 for middle C (MIDI 60) and E (64) and switches different LEDs on and off and still has serial.prints in to check what notes are arriving. Obviously you could also run motors or do whatever else you need in those NoteHandler routines. Just don’t use any blocking code like delay()…leave all the timing to the MIDI NoteOn/NoteOff.

#include <SoftwareSerial.h>
#include <MIDI.h>

byte greenLED = 10;
byte redLED = 11;

SoftwareSerial softSerial (2, 3);
MIDI_CREATE_INSTANCE(SoftwareSerial, softSerial, MIDI);

void handleNoteOn(byte channel, byte pitch, byte velocity)
{
  Serial.print("Channel: ");
  Serial.print(channel);

  if (channel == 16) // check channel first
  {
    // Do functions based on note received
    // Simple case - switch appropriate LED on depending on note 60=green, 64=red
    if (pitch == 60) {
      digitalWrite(greenLED, HIGH);
    }
    if (pitch == 64) {
      digitalWrite(redLED, HIGH);
    }
    Serial.print("NoteOn: ");
    Serial.println(pitch);
  }
}
void handleNoteOff(byte channel, byte pitch, byte velocity)
{
  Serial.print("Channel: ");
  Serial.print(channel);

  if (channel == 16) // check channel first if listening on all channels
  {
    // Do functions based on note received
    // Switch appropriate note's LED off
    if (pitch == 60) {
      digitalWrite(greenLED, LOW);
    }
    if (pitch == 64) {
      digitalWrite(redLED, LOW);
    }

    Serial.print(" NoteOff: ");
    Serial.println(pitch);
  }
}
void setup() {
  Serial.begin (57600);
  // Connect the handleNoteOn function to the library,
  // so it is called upon reception of a NoteOn.
  MIDI.setHandleNoteOn(handleNoteOn);  // Put only the name of the function

  // Do the same for NoteOffs
  MIDI.setHandleNoteOff(handleNoteOff);

  // Initiate MIDI communications, listen to all channels
  // change to MIDI.begin(16); to listen to just ch16 then you won't need tests in the notehandlers.
  MIDI.begin(MIDI_CHANNEL_OMNI);
}

void loop() {
  // Call MIDI.read the fastest you can for real-time performance.
  MIDI.read();
  // Note: you could add callback handlers for other messages but
  // currently only NoteOn and NoteOff are set up so
  // any othe MIDI messages will be ignored
}

I’m certain it could be neater but it’s so simple and effective that I’m now thinking of interesting projects I can use the technique for.

Steve

Steve,

thanks a lot for taking the time to do this test despite your computer problems.

I feel ashamed because I’ve made some tests on my side as well and I completely forgot to let you know…

I get some results but not exactly with your technique. I don’t understand why you had to used an optocoupler though.

What I’ve done is use Hairless MIDI to “connect” Reaper with my Arduino. It was a bit arduous but I finally make it works with the built in LED and a servo. But when I’ve tried with my solenoids it was an another story.
I used a lot of libraries because I’m lame and because I tried to have a non-blocking code. But I think I got timer conflicts between librairies.

So, for my solenoids only I tried this alone (without MIDI triggering), for having them periodically hitting(while the note is ON when it’s in the next code, lower in this comment):

#include "Timer.h"

Timer t;

int soleEvent1 = 10;
int soleEvent2 = 11;


void setup()
{
  Serial.begin(9600);
 
  pinMode(10, OUTPUT);
  pinMode(11, OUTPUT);

  int tickEvent1 = t.every(1, doSomething1);
  int tickEvent2 = t.every(1, doSomething2);

}

void loop()
{
  t.update();
  doSomething1();
  doSomething2();
}


void doSomething1() {
    soleEvent1 = t.oscillate(soleEvent1, 50, LOW, 5);
}

void doSomething2() {
    soleEvent2 = t.oscillate(soleEvent2, 50, LOW, 40);
}

And my test code for MIDI triggering with LED and servo working but not the solenoids because I don’t know how to include that in my switch/case part(I know it’s a super ugly code, sorry…):

#include <MIDI.h>  // Add Midi Library

#include "Timer.h"

Timer t;

int soleEvent1 = 10;
int soleEvent2 = 11;


#define LED 13    // Arduino Board LED is on Pin 13

#include <VarSpeedServo.h> 
 
VarSpeedServo myservo;    // create servo object to control a servo 


//Create an instance of the library with default name, serial port and settings
MIDI_CREATE_DEFAULT_INSTANCE();

void setup() {
  pinMode (LED, OUTPUT); // Set Arduino board pin 13 to output
  pinMode(10, OUTPUT);
  pinMode(11, OUTPUT);

  int tickEvent1 = t.every(1, doSomething1);
  int tickEvent2 = t.every(1, doSomething2);

  myservo.attach(9);  // attaches the servo on pin 9 to the servo object 
  MIDI.begin(MIDI_CHANNEL_OMNI); // Initialize the Midi Library.
  // OMNI sets it to listen to all channels.. MIDI.begin(2) would set it 
  // to respond to notes on channel 2 only.
  MIDI.setHandleNoteOn(MyHandleNoteOn); // This is important!! This command
  // tells the Midi Library which function you want to call when a NOTE ON command
  // is received. In this case it's "MyHandleNoteOn".
  MIDI.setHandleNoteOff(MyHandleNoteOff); // This command tells the Midi Library 
  // to call "MyHandleNoteOff" when a NOTE OFF command is received.
  Serial.begin(115200);
}

void loop() { // Main loop
  MIDI.read(); // Continuously check if Midi data has been received.
}

// MyHandleNoteON is the function that will be called by the Midi Library
// when a MIDI NOTE ON message is received.
// It will be passed bytes for Channel, Pitch, and Velocity
void MyHandleNoteOn(byte channel, byte pitch, byte velocity) { 
  switch (pitch) {
    case 42:
    myservo.write(150, 200, false);        // move to 180 degrees, use a speed of 30, wait until move is complete
    digitalWrite(LED,HIGH);  //Turn LED on
      return;
    case 44:
    myservo.write(30, 100, false);         // move to 0 degrees, use a speed of 30, wait until move is complete
      return;
      case 46:
    myservo.write(60, 30, false);         // move to 0 degrees, use a speed of 30, wait until move is complete
      return;
      case 48: {
      t.update();
      doSomething1();
      }
      return;
      case 50: {
      t.update();
      doSomething2();
      }
      return;
    default: 
    myservo.stop();
    digitalWrite(LED,LOW);
    t.stop(soleEvent1);
    t.stop(soleEvent2);
      // if nothing else matches, do the default
      // default is optional
    return;
  }
}

// MyHandleNoteOFF is the function that will be called by the Midi Library
// when a MIDI NOTE OFF message is received.
// * A NOTE ON message with Velocity = 0 will be treated as a NOTE OFF message *
// It will be passed bytes for Channel, Pitch, and Velocity
void MyHandleNoteOff(byte channel, byte pitch, byte velocity) { 
 //switch (pitch) {
    //case 42:
      //do something when var equals 1
      //break;
    //case 44:
      //do something when var equals 2
      //break;
    //default: 
      // if nothing else matches, do the default
      // default is optional
    //break;
    myservo.stop();
    digitalWrite(LED,LOW);
    t.stop(soleEvent1);
    t.stop(soleEvent2);

 }

void doSomething1() {
    soleEvent1 = t.oscillate(soleEvent1, 10, LOW);
}

void doSomething2() {
    soleEvent2 = t.oscillate(soleEvent2, 10, LOW);
}

Do you know how I could improve that and make it works as intended. I try to have a code simple to edit to have various parameters easily adjustable for each note.
Also, I didn’t try with stepper motor yet… And with several Arduinos either.
But I feel like I slowly move forward (with baby steps but still).

Again, thanks a lot for your help, and again, sorry to have forgotten to let you know about my progress…

Anyway I’m very glad you find this inspiring for your own projects! :slight_smile:

Have a good day.

Cyril_

No apology needed I'm enjoying myself. I'm glad you're getting it worked out.

I wanted to just use Reaper's MIDI routing without needing extra software like Hairless and LoopMIDI. I already had MIDI outs on my Audio interface (though I tested it with a cheap USB to MIDI converter too) so I'm using plain MIDI and at the Arduino end the standard MIDI in circuit (which uses an optocoupler) https://www.midi.org/specifications/item/midi-din-electrical-specification

Your way should also work and has the advantage of not needing you to build the input circuits.

I'll have a look at your code...but what exactly do you want the solenoids doing? For as long as their specific notes (48, 50?) are on should the pin really be switching on and off every 10ms ? Will your solenoids switch 50 times a second, that's very fast?

I think some problems are likely to be because both MIDI and Timer are using independent callbacks and getting those integrated is tricky. I haven't needed to use that Timer library before so I'll have a play with it.

But presumably one possibility is to drop the timer and instead send a series of short notes to drive the solenoids directly.Though I guess that's not really practical if it really does need to run so fast.

I don't know anything about stepper motors so I'd be even less use there ;).

Steve

Thanks for your reply Steve.

Hairless MIDI doesn't seem to use much processor and memory resources so I find this way more simple, at least for now. But I don't know how I will manage that with several Arduinos...

About the solenoids part, you're exactly right. I want them to switch on and off as long as the note is on. 50ms was a value I put for my test. I figured out it was the fastest I needed (and this speed seems to be supported by my tiny solenoids). But if I could adjust their "hitting speed" with the note velocity it would be perfect. I don't know if it's feasible with switch/case though...

You must be right about callbacks issues. And that's where I was struggling. The problem with the "short notes" is that you can't have notes this short in MIDI afaik.

No problem for the stepper motors. I'm about to make them work I think (hope?).

Cyril_