I'm fairly new to writing code and I've run into a problem to which I can't find the answer.
For a interactive sound installation I want to play a single midi note when a person comes close to the installation and play a different note when the person is gone for more than 3 seconds. I use a sharp ir sensor on analog pin 0 to measure the distance of the listener and hairless to convert serial to midi. Ableton plays the samples.
The code I have found/edited works, but sends continuous midi notes, restarting the samples all the time. I am looking for a way to tell the arduino to play one note if the sensor data is higher than 400 and wait until the data is lower than 400 for more than 3 seconds and then play the other note etc. The code I have now is the following:
int velocity = 100;//velocity of MIDI notes, must be between 0 and 127
//higher velocity usually makes MIDI instruments louder
int noteON = 144;//144 = 10010000 in binary, note on command
int noteOFF = 128;//128 = 10000000 in binary, note off command
int sensorPinL = 0; // IR SensL - A0
int irValL = 0;
int zValL = 0;
int irStateL = 0; //current state
int lastIrStateL = 0; //previous state
int lowThresh = 115;
int highThresh = 635;
void setup() {
// Set MIDI baud rate:
Serial.begin(115200);
}
void loop() {
zValL = irValL;
irValL = analogRead(sensorPinL);
if(irValL > 400) {
irStateL = 1;
}
else {
irStateL = 0;
}
if (irStateL == 1) {
MIDImessage(noteON, 50, velocity);//turn note on
}
if (irStateL == 0) {
MIDImessage(noteON, 51, velocity);//turn note on
}
if (irStateL - lastIrStateL > 0) {
delay (3000);
}
irStateL = lastIrStateL;
}
//send MIDI message
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
}
int toMIDIRange(int x)
{
if (x < lowThresh)
return 0;
if (x > highThresh)
return 127;
else
return x/5;
}
I hope someone here can give me a tip where I can find an example or tutorial that can teach me how to solve this.
I may have missed a state here, but hopefully you will get the idea
Use a global variable e.g.
int state=1;
to hold you state,
Then in loop() use a switch statement to execute the statements for each state
e.g. something like this
switch(state)
{
case 1:
if (dist<400)
{
state=2;
// Play a note
}
break;
case 2:
if (dist>400)
{
state=3;
// keep playing a note??
}
break;
case 3:
delay(3000);
state=4
break;
case 4:
// play another notes??
break;
}
OP: You need to send the MIDI message only when there has been a change. Instead, you are sending a message every time.
Copying a previous value, on every pass through loop (as you are doing) is essential to that process. But, then you have to decide if the new value is the same as the old value, and send a message only if the old and new values are different.
I found a way to make it work. Thanks for the tips. I have to change the 3 second delay for a solution which doesn't stop the arduino from listening, but for the rest it's ok now.
int velocity = 100;//velocity of MIDI notes, must be between 0 and 127
//higher velocity usually makes MIDI instruments louder
int noteON = 144;//144 = 10010000 in binary, note on command
int noteOFF = 128;//128 = 10000000 in binary, note off command
int sensorPinL = 0; // IR SensL - A0
int irValL = 0;
int zValL = 0;
int irStateL = 0; //current state
int lastIrStateL = 1; //previous state
int lowThresh = 115;
int highThresh = 635;
void setup() {
// Set MIDI baud rate:
Serial.begin(115200);
}
void loop() {
zValL = irValL;
irValL = analogRead(sensorPinL);
if(irValL > 400) {
irStateL = 0;
}
if(irValL <= 400) {
irStateL = 1;
}
if(irValL <= 400 && irStateL != lastIrStateL) {
delay(3000);
irValL = analogRead(sensorPinL);
if(irValL > 400) {
irStateL = 0;
}
if(irValL <= 400) {
irStateL = 1;
}
}
if(irValL > 400 && irStateL != lastIrStateL) {
irStateL = 0;
MIDImessage(noteON, 50, velocity);//turn note on
}
if(irValL <= 400 && irStateL != lastIrStateL) {
irStateL = 1;
MIDImessage(noteON, 51, velocity);//turn note on
}
lastIrStateL = irStateL;
}
//send MIDI message
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
}
int toMIDIRange(int x)
{
if (x < lowThresh)
return 0;
if (x > highThresh)
return 127;
else
return x/5;
}