a new laser harp project

ey there!

I am testing a new layout for a laser harp

my prototype has 2 photoresistors, each of them recibing light from 2 lasers.

when I interrupt the laser beam addressed to "sensor 01", I trigger a midi note
when I interrupt the laser beam addressed to "sensor 02", I trigger a 2nd midi note
and when I interrupt both laser beams , I trigger a 3rd midi note

everything works ok so far, but.

In the code you will see that the 3rd midi note stops when both sensors are again recibing light, but I would like this 3rd midi note to stop when both sensors are again recibing light, OR when one of these sensor are again recibing light.

I tried this in several ways, without proper results. It would be very extensive to detail my attemps, so I rather simply present the problem and see if a brilliant mind helps me sorting this out.

Attached, the code.

thanks!

sketch_arpa_gross_test.ino (2.24 KB)

Hi camilozk

I have not had time to work through your logic in detail. I think there are ways to improve the structure and simplify the conditions in the if statements.

But just as a quick fix, try changing the code that handles both sensors being active to the following. Does it do what you need?

//SENSOR 0102---------------------------------------------------                            
  if (sensorValue01 > threshold && sensorValue02 > threshold && Key1LastState0102 == false) {
  MIDI_TX(128,sensornote0102,127);
  Key1LastState0102 = true;
  }
  else if (sensorValue01 < threshold && sensorValue02 < threshold && Key1LastState0102 == true) {
  MIDI_TX(144,sensornote0102,127);
  Key1LastState0102 = false;
  }  
// ADDED THESE TO START THE SINGLE SENSOR NOTES IF APPROPRIATE
  else if (sensorValue01 > threshold && Key1LastState0102 == true) {
        MIDI_TX(144,sensornote0102,127);
	Key1LastState0102 = false;
	MIDI_TX(128,sensornote01,127);
	Key1LastState01 = true;
  }
  else if (sensorValue02 > threshold && Key1LastState0102 == true) {
	MIDI_TX(144,sensornote0102,127);
	Key1LastState0102 = false;
	MIDI_TX(128,sensornote02,127);
	Key1LastState02 = true;
  }
}

I'm assuming MIDI 128 is note on and 144 is note off?

Regards

Ray

thanks Ray!

Noup. It is not working as expected.

first, in your added code else if (sensorValue01 > threshold && Key1LastState0102 == true) we are looking for the value to be smaller that the threshold. (<)

Anyway, I changed it but what happens now is that even when I interrupt a single laser, the 3rd midi note is triggered.

We are going to get it! :slight_smile:

Hi

Can I suggest something else. Try my added code with the ">" the way I had them. But also do the following.

For each of your state variables (e.g. Key1LastState01), in every place where they are set to true, add statements to set the other two state variables to false.

Logically, only one of them should be true at any given time.

Which suggests that a better solution would be to use a single variable to hold the current state (or previous state) and give it one of four values that equate to "both sensors off", "sensor 1 on", "sensor 2 on" or "both sensors on".

You could do this using a byte variable and #define constants, or "const byte" constants, or an enum type.

Maybe worth researching "finite state machine" - there is information on this website about it.

Regards

Ray

Ray!

you understood everything correctly (I think), but anyway the code doesnt work as expected. instead is triggering a kaos of the 3rd note continuosly...

And about what you said

If sensor01 is still on and previously both were on, stop the third note and start the note for sensor01.

I want the third note to stop, but not to start the note for sensor01. the note for sensor01 would be already playing, so I dont need to start it, but I need it to continue as it is.

:slight_smile:

Ah, ok. Sorry, I misunderstood.

When both sensors are true, you start the 3rd note but keep the first two going?

Then, for example, if sensor01 goes off, you want to stop the 3rd note and stop sensor01 note but keep sensor 02 note going?

Let me look at your program again with that in mind.

Regards

Ray

exactly!

Does it cause a problem if a note is already on and you send the MIDI on command again for the same note?

And what about a note that is already off and you send the off command again?

Does it cause a problem if a note is already on and you send the MIDI on command again for the same note?

yes

And what about a note that is already off and you send the off command again?

lets try it!

I would actually try both...

I am trying to use the boolean or in the meantime, without sucess...

ray! thank you very much for your effort, really.

I didnt went through the code to try to understand it, it will take me probably a couple of hours since I do not know much about the language yet. But I did try it and it doesnt work. It doesnt work in a very complicated way.

Also, because I saw the lenght and complexity of the code, I think it is a good moment to share with you that what we are trying to apply now to 2 sensors (which give us 3 sound), I want to apply it to 16 sensors (which give us 80 sounds). I am not sure, but have the feeling that the direction you are taking might be a little bit complex for this...

what about the idea of sending a repeated "note off"?

Hi

I deleted my post before you replied because I thought again about your original problem :slight_smile:

And your point about 16 sensors is a valid one.

Going back to your original code, you have this conditional test:

else if (sensorValue01 < threshold && sensorValue02 < threshold && Key1LastState0102 == true)

What happens if you change this to be:

else if ((sensorValue01 < threshold || sensorValue02 < threshold) && Key1LastState0102 == true)

Regards

Ray

I want to apply it to 16 sensors (which give us 80 sounds).

Can you explain how the 80 sounds are triggered by the 16 sensors? Using if statements on 16 separate "value > threshold" type comparisons will be OK for starting the individual notes. But it could be complex for the combination notes.

else if ((sensorValue01 < threshold || sensorValue02 < threshold) && Key1LastState0102 == true)

I tried this one before, and it realeses the 3rd note correctly, but it also triggers the 3rd note when a single laser beam is interrupted. I think this is the way to go, but we have to get rid of the 3rd note being triggered by a single laser beam interrupted.

regarding how it would work with 16 lasers, check the image attached.

I tried this one before, and it realeses the 3rd note correctly, but it also triggers the 3rd note when a single laser beam is interrupted.

Maybe there is the equivalent of key bounce happening here. The only place in your code that has the MIDI statement to start the 0102 note is here:

  if (sensorValue01 > threshold && sensorValue02 > threshold && Key1LastState0102 == false) {
  MIDI_TX(128,sensornote0102,127);

What may be happening is that when you remove one hand, the sensor value drops. But it does not drop smoothly. As it passes the threshold level, it bounces up and down a bit. But this is enough for the above statement to be true again. So you get another note 0102.

How about this. Have two threshold values. Make them some distance apart in value. Use the higher one in all the tests where you have ">" and the lower one in the tests where you have "<".

Alternatively, you could use a timer and the techniques used for debouncing mechanical buttons. Basically, if you think the level has changed, wait a few ms and then test again. But to do this neatly, I think you will need to move the "is sensor on or off" test out of the if statements into a separate function. Then use the result of the function in your if statements.

Regards

Ray

Thanks for the diagram.

8 x 8 matrix so 64 places you could break the beams with one hand. That would give you 1 of 64 individual notes?

Then if you put a second hand in, you want to detect which of the 64 it is at and generate that individual note?

How do you get the extra 16 to make it 80?

Regards

Ray

I think the code should be written like this:

//SENSOR 0102---------------------------------------------------                            
  if (sensorValue01 > threshold && sensorValue02 > threshold && Key1LastState0102 == false) {
  MIDI_TX(128,sensornote0102,127);
  Key1LastState0102 = true;
  }
  else if (sensorValue01 < threshold && Key1LastState0102 == true || sensorValue02 < threshold && Key1LastState0102 == true) {
  MIDI_TX(144,sensornote0102,127);
  Key1LastState0102 = false;
  }  
}

I have being checking the sensor´s values with the serial monitor before, and the values go down pretty straight forward. I dont think there is any bouncing. I think is a code issue.

How do you get the extra 16 to make it 80?

you have 16 midi notes per single laser beam interrupted + 64 midi notes per interrupted node

here the values that the photoresistor sends when the laser beam is interrupted

In that test program, the frequency with which you do the analogRead is limited by the time to print the result at 9600bps.

I still think it might be worth testing with, for example, "sensorValueXX > 750" and "sensorValueXX < 600".

EDIT: As an alternative, just for testing not as a long term solution, try adding a delay after you send the third note:

MIDI_TX(144,sensornote0102,127);
delay(100); // wait 100ms - brute force debounce for debugging purposes

Do you still get the extra third note?