Go Down

Topic: Sending out an SOS! Arduino, Hairless, LoopMidi, Resolume (Read 2146 times) previous topic - next topic

genghisaloe

Hey guys!
I've spent the last two months working on a project that's for an educational exhibition in a college.

{see attached image 'overall idea'}
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:
{see attached image '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:

{see images:
early stage plinth.jpg
plinth in progress.jpg}


Here you can see a still of the mapping having worked successfully:

{see image: 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! :)


genghisaloe

Code: [Select]
// 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
}

genghisaloe

Hey guys,
I was helped to find the answer with this yesterday by Zoltan from the Resolume forums. The first suggestion that was made was that the sections of 'if' statements should have each analogue read be greater than threshold, as the way I have it in the code above, when the reads were being done, only the last sensor had to be greater than threshold based on what was there.
Eg
if (sensorValue1 && sensorValue2 > threshold)
*should be*
if (sensorValue1 > threshold && sensorValue2 > threshold) etc

The main thing that we worked out together was that the reason Resolume was being caused to crash was because I'd been allowing it to output midi back to the loopmidi virtual midi port, so this backchatter was what was messing it all up. As soon as the midi out was removed, things behaved exactly as they should again, Resolume could take the midi mapping correctly from Hairless Midi and the triggers worked right.

Thanks to everyone for their contributions on these forums, in particular Grumpy Mike, cheers for all your time & help :) b




Go Up