Page 1 of 1

Sending out an SOS! Arduino, Hairless, LoopMidi, Resolume

Posted: Wed Oct 04, 2017 17:04
by genghisaloe
Hey guys!
I've spent the last two months working on a project that's for an educational exhibition in a college.


What we're trying to achieve is to have a multimedia 'book', that can tell when the page has turned, then play the next series of videos based on which page is revealed. The way I'm going about this is to have a series of light dependant analogue resistors, hidden under tabs on the pages, so when a page is turned, the sensor is revealed then causes a midi note to be generated, (which Resolume has been mapped to) and the change occurs.

It's all gone from strength to strength as I've worked on it and I've gotten to the point where I've had everything work exactly as I've wanted it to, then it's apparently all randomly failing, and quite spectacularly at that!
I'll bring you along through the stages of things now:

At first I had used and Arduino Uno, alongside LoopMidi and the Hairless-Midi tools for the proof of concept and it all was fine:
uno proof of concept.jpg
That was all perfect, as I was able to map Resolume correctly and it would 'hear' the command properly.

The next phase was to move things up to the Arduino Due, as we wanted to be able to have more permutations of pages of the book {jumping from 3 sensors in the first test up to 6}. At this point in the work, everything functioned perfectly again, so I had 4 slices {top left, bottom left, top right, bottom right} each with a layer mapped to it, then one midi note to cover changing the 4 slices as each page turned.
overall idea.jpg
At this point, as everything was cool with the hardware and code, the focus went to the presentation of the plinth, and how the sensors could be concealed:
early stage plinth.jpg
plinth in progress.jpg
Here you can see a still of the mapping having worked successfully:
this is when it worked briefly and took the mapping correctly.jpg
(using baud rates of 115200 in both the arduino code and in Hairless)

This is right around when tragedy struck, the due gets dropped from a table and everything went haywire from there. I replaced the Due with a Mega {changing resistor values and port numbering because of the difference in the Due being 3.3v and the Mega being 5v}

So the way the arduino code works is like this, loopmidi has made the virtual midi port, hairless midi is attached to that same port, then finally resolume is set to see that virtual port too. When the arduino code starts, it checks to see if the sensors give an answer that's above a certain threshold, if the answer is yes, then +1 gets added to 'newnote'. Later in the code (when I'm constructing the midi packet), I tell it to send out a note based on that 'newnote' variable.
The logic of this is such that when a person reveals a sensor by turning a page, I want it only to send the note once so as not to spam the change, so at the end of my loop I declare 'newnote' to equal 'oldnote'
If 'oldnote' is the same as 'newnote' it does nothing, if 'newnote' varies from 'oldnote' then it plays the next note.
Figuring that bit out was the game changer that meant everything would work as we'd hoped.

So I have 9 sensors, then I also have an array of the notes that can be played {55 - 64}
So when 'newnote' is set to call one of the notes from the array it looks like this:

MIDImessage(noteON, notePlayed[newNote], velocity);
delay(300);
MIDImessage(noteOFF, notePlayed[newNote], velocity);

All of this what I've described works perfectly when it's just the arduino, loopmidi and hairless, the first time you reveal any sensors, the arduino counts them and then if the note wasn't just played a second ago then it plays it, if it's not changed it does nothing.
Now for some unknown reason Resolume will ignore the part of the code that tells the note not to repeat, so then it'll spam the same note until Resolume crashes.
I'm using windows 7 and have tried to set everything up in Arena 4.1.8 & 5.1.4. Everything's been edited with Media Encoder to the dxv standard through the adobe suite, I've tried 38400 baud and 115200. I've tried opening hairless before and after resolume is open. Even holding the arduino's reset button so that I'm certain resolume 'hears' the status byte at the start of the transmission.
What's really making me crazy is that the very same code has all been able to work perfectly and achieve what we need, then as if arbitrarily, it's suddenly ignoring the aspect of the code that stops it repeating itself so then Hairless's output is that note 55 is being spammed on at 127 velocity. If Resolume is open it flickers between each of the mapped layers for that note and then about 30kilobytes per second of data gets sent until everything crashes.

This is a really so close but yet so far situation. I'd intend buying Arena 5 at the educational rate for the project but I need to side step these issues, otherwise I need to start from scratch with another platform, I really have my heart set on using Resolume though because it just such a masterfully well made program! Any help would be much appreciated, thanks for your time in reading this! :)

This Arduino ino file that I've used:
_____________________________________________________________________________________
// include MIDI library
#include <MIDI.h>

MIDI_CREATE_DEFAULT_INSTANCE();

//controller notes
int noteON = 144;//144 = 10010000 in binary, note on command
int noteOFF = 128;//128 = 10000000 in binary, note off command

//led's to correspond with which ldr's are giving a read to aid debugging/mapping midi
int ledPin1 = 22;
int ledPin2 = 23;
int ledPin3 = 24;
int ledPin4 = 25;
int ledPin5 = 26;
int ledPin6 = 27;
int ledPin7 = 28;
int ledPin8 = 29;
int ledPin9 = 30;

int sensorValue1 = 0; // variables to hold LDR sensor values
int sensorValue2 = 0;
int sensorValue3 = 0;
int sensorValue4 = 0;
int sensorValue5 = 0;
int sensorValue6 = 0;
int sensorValue7 = 0;
int sensorValue8 = 0;
int sensorValue9 = 0;

const int threshold = 200;

int x = 0;
//this is the array of notes that can be called, later the variable newNote is added to notePlayed[here] to decide which gets played

int notePlayed[] = {55, 56, 57, 58, 59, 60, 61, 62, 63, 64};
int oldNote;

// put your setup code here, to run once:
void setup() {
pinMode(ledPin1, OUTPUT);
pinMode(ledPin2, OUTPUT);
pinMode(ledPin3, OUTPUT);
pinMode(ledPin4, OUTPUT);
pinMode(ledPin5, OUTPUT);
pinMode(ledPin6, OUTPUT);
pinMode(ledPin7, OUTPUT);
pinMode(ledPin8, OUTPUT);
pinMode(ledPin9, OUTPUT);

// begin MIDI
MIDI.begin();
// 115200 Hairless MIDI Serial Bridge baud rate
//Serial.begin(115200);
Serial.begin(38400);
}
void loop() {
int velocity = 127;
int newNote = 0;
sensorValue1 = (analogRead(A7));
sensorValue2 = (analogRead(A8));
sensorValue3 = (analogRead(A9));
sensorValue4 = (analogRead(A10));
sensorValue5 = (analogRead(A11));
sensorValue6 = (analogRead(A12));
sensorValue7 = (analogRead(A13));
sensorValue8 = (analogRead(A14));
sensorValue9 = (analogRead(A15));

if (sensorValue1 > threshold) {
(newNote++);
digitalWrite(ledPin1, HIGH);
} else if (sensorValue1 < threshold) {
digitalWrite(ledPin1, LOW);
}
if (sensorValue1 && sensorValue2 > threshold) {
(newNote++);
digitalWrite(ledPin2, HIGH);
} else if (sensorValue1 && sensorValue2 < threshold) {
digitalWrite(ledPin2, LOW);
}
if (sensorValue1 && sensorValue2 && sensorValue3 > threshold) {
(newNote++);
digitalWrite(ledPin3, HIGH);
} else if (sensorValue1 && sensorValue2 && sensorValue3 < threshold) {
digitalWrite(ledPin3, LOW);
}
if (sensorValue1 && sensorValue2 && sensorValue3 && sensorValue4 > threshold) {
(newNote++);
digitalWrite(ledPin4, HIGH);
} else if (sensorValue1 && sensorValue2 && sensorValue3 && sensorValue4 < threshold) {
digitalWrite(ledPin4, LOW);
}
if (sensorValue1 && sensorValue2 && sensorValue3 && sensorValue4 && sensorValue5 > threshold) {
(newNote++);
digitalWrite(ledPin5, HIGH);
} else if (sensorValue1 && sensorValue2 && sensorValue3 && sensorValue4 && sensorValue5 < threshold) {
digitalWrite(ledPin5, LOW);
}
if (sensorValue1 && sensorValue2 && sensorValue3 && sensorValue4 && sensorValue5 && sensorValue6 > threshold) {
(newNote++);
digitalWrite(ledPin6, HIGH);
} else if (sensorValue1 && sensorValue2 && sensorValue3 && sensorValue4 && sensorValue5 && sensorValue6 < threshold) {
digitalWrite(ledPin6, LOW);
}
if (sensorValue1 && sensorValue2 && sensorValue3 && sensorValue4 && sensorValue5 && sensorValue6 && sensorValue7 > threshold) {
(newNote++);
digitalWrite(ledPin7, HIGH);
} else if (sensorValue1 && sensorValue2 && sensorValue3 && sensorValue4 && sensorValue5 && sensorValue6 && sensorValue7 < threshold) {
digitalWrite(ledPin7, LOW);
}
if (sensorValue1 && sensorValue2 && sensorValue3 && sensorValue4 && sensorValue5 && sensorValue6 && sensorValue7 && sensorValue8 > threshold) {
(newNote++);
digitalWrite(ledPin8, HIGH);
} else if (sensorValue1 && sensorValue2 && sensorValue3 && sensorValue4 && sensorValue5 && sensorValue6 && sensorValue7 && sensorValue8 < threshold) {
digitalWrite(ledPin8, LOW);
}
if (sensorValue1 && sensorValue2 && sensorValue3 && sensorValue4 && sensorValue5 && sensorValue6 && sensorValue7 && sensorValue8 && sensorValue9 > threshold) {
(newNote++);
digitalWrite(ledPin9, HIGH);
} else if (sensorValue1 && sensorValue2 && sensorValue3 && sensorValue4 && sensorValue5 && sensorValue6 && sensorValue7 && sensorValue8 && sensorValue9 < threshold) {
digitalWrite(ledPin9, LOW);
}
if (oldNote == newNote) {
delay(1000);
} else if (newNote != oldNote) {
MIDImessage(noteON, notePlayed[newNote], velocity);//turn note on
delay(500);//hold note for 300ms
MIDImessage(noteOFF, notePlayed[newNote], velocity);//turn note off
delay(200);//wait 200ms until triggering next note
oldNote = newNote;
}
}
void MIDImessage(int command, int MIDInote, int MIDIvelocity) {
Serial.write(command);//send note on or note off command
Serial.write(MIDInote);//send pitch data
Serial.write(MIDIvelocity);//send velocity data
}

Re: Sending out an SOS! Arduino, Hairless, LoopMidi, Resolume

Posted: Wed Oct 04, 2017 18:52
by Zoltán
had a quick look at your code,
I don't think the IF statements are doing what you want them to.
if (sensorValue1 && sensorValue2 > threshold)
will return true if
sensorValue1 != 0 'and' sensorValue2 > treshold
I think you may want (sensorValue1 > threshold && sensorValue2 > threshold)
genghisaloe wrote:If Resolume is open it flickers between each of the mapped layers for that note and then about 30kilobytes per second of data gets sent until everything crashes.
data gets sent from where to where?
Resolume doesn't need to send midi back to midi loop, so make sure you disable midi output from resolume.

Re: Sending out an SOS! Arduino, Hairless, LoopMidi, Resolume

Posted: Wed Oct 04, 2017 19:43
by genghisaloe
First of all I'd like to thank you profusely for your really fast reply! :)
{I'll likely be here working on this all night again!}

I've amended each of the 'if' statements, so as to have each respond in the way you've described.

What I've done is made several screenshots to help illustrate what's happening.

So this is the arduino code, loopmidi & hairless, without resolume 5.1.4 turned on:
post Zoltans edit.PNG
It's behaving exactly as it's meant to, notice that the amount of data sent is tiny.

This is where you can see that Resolume has been introduced to the equation and now the part of the code which tells Resolume not to repeat a note is being ignored, then you can see the amount of data being sent is skyrocketing. {at 9,000 ish bytes about 30 seconds in}
post Zoltans change with resolume 5.1.4.PNG
This is about 90 seconds on, what you can't see is how layer1, then 2, then 3, then 4 are cycled through rapidly
Before it crashes.PNG
Now it's at 2 minutes or so and Resolume has died:
post crash about 2 minutes later.PNG
And then with Resolume out of the equation again it levels out and behaves as it should again:
post crash code behaving itself again.PNG
The thing that's really throwing me off is that this same very code (prior to your suggested edit) has been able to function and correctly 'hear' and composition map and also deliver the right layers as per the notes called correctly, on both arena 4 or 5. So in other words, the ambition of the job has been achieved already, yet some unknown influence has meant that Resolume now decides not to 'hear' things as it had. I'm just running out of possible avenues of things to change.

I've gone to the rounds of starting with a fresh version of windows 7, made a backup of it before any software, then another backup after installing all the relevant drivers etc and the version I'm using now is totally fresh.
Perhaps there's a lead in these screenshots?

Re: Sending out an SOS! Arduino, Hairless, LoopMidi, Resolume

Posted: Wed Oct 04, 2017 19:50
by Zoltán
You can see in the midi debug window, that you get the midi back to hairless,
I don't think you process that in the arduino so you probably don't need that input.
I think resolume is crashing because in Preferences, you have midi output enabled back to the loopmidi device, which will make resolume crash as it has to process the midi, then send it out, then process what it sent out and so on.

Re: Sending out an SOS! Arduino, Hairless, LoopMidi, Resolume

Posted: Wed Oct 04, 2017 19:56
by genghisaloe
You Sir, are a gentleman and a scholar :D !!!

Sorry, I'd missed that last line in your initial reply!
The output from MIDI options going back into the Midi port was what was causing it.
I can't thank you enough! You literally have no idea how much more heartache you've saved me!

Re: Sending out an SOS! Arduino, Hairless, LoopMidi, Resolume

Posted: Wed Oct 04, 2017 20:00
by Zoltán
You're welcome!

Re: Sending out an SOS! Arduino, Hairless, LoopMidi, Resolume

Posted: Thu Oct 05, 2017 04:58
by francoe
Love your project, when you get fully working please post a little video of it.

Re: Sending out an SOS! Arduino, Hairless, LoopMidi, Resolume

Posted: Thu Oct 05, 2017 10:13
by genghisaloe
https://youtu.be/wilnh7ZotQI

This was an earlier version of things when it was still the Arduino Due board.
I'll follow up with more in about a fortnight once it's installed :)
Thanks again Zoltan :D Have a good day!