Go Down

Topic: Sharp IR sensor to MIDI. Tutorial? Help. (Read 7087 times) previous topic - next topic

Grumpy_Mike

#15
Mar 07, 2015, 06:31 pm Last Edit: Mar 07, 2015, 06:31 pm by Grumpy_Mike
Try this:-
Code: [Select]


//
// by Mike Cook
// v.1.1 07 March 2015
////////////////////////////////

#include <MIDI.h>
boolean playing = false;
const byte channel = 0;
const byte baseNote = 72;



void setup() {

  Serial.begin(31250); // MIDI Begin
  noteOn();
}
 

void loop(){
  int av1 = // put the ultrasonic measurement here
  trackNote(av1);
}

void noteOff(){
  playing= false;
  // note off + sustain off
  noteSend(0x80,baseNote,127);
  controlSend(64, 0);
}
void noteOn(){
 // note on + sustain on
  noteSend(0x90,baseNote,127);
  controlSend(64, 127);
  playing = true;
}

 void noteSend(byte cmd, byte data1, byte data2) {
  cmd = cmd | channel;
  Serial.write(cmd);
  Serial.write(data1);
  Serial.write(data2);
}

int trackNote(int freq){
  int pb = 0x2000 - (435 - freq);
  sendPB(pb);
  int vel = volume>> 3;
   controlSend(7, vel);
}

void controlSend(byte CCnumber, byte CCdata) {
  byte CCchannel = channel | 0xB0; // convert to Controller message
  Serial.write(CCchannel);
  Serial.write(CCnumber);
  Serial.write(CCdata);
}

void sendPB(int pb){ // send pitch bend message
  Serial.write( (byte)0xE0 | channel);
  Serial.write( pb & (byte)0x7f);
  Serial.write( (pb>>7) & (byte)0x7f);
}



Note that some voices decay after the first note on. Choose a voice that sustains as long as the note on remains in force.

kreationsministern

Note that some voices decay after the first note on. Choose a voice that sustains as long as the note on remains in force.

Thank you so much.
But I get this error:
__

sketch_mar07f.ino: In function 'int trackNote(int)':
sketch_mar07f.ino:50:13: error: 'volume' was not declared in this scope
__

How can I declare the volume?

Grumpy_Mike

Quote
How can I declare the volume?
Don't you are not controlling the volume are you? Just delete volume related code.

kreationsministern

Try this:-
Code: [Select]


//
// by Mike Cook
// v.1.1 07 March 2015
////////////////////////////////

#include <MIDI.h>
boolean playing = false;
const byte channel = 0;
const byte baseNote = 72;



void setup() {

  Serial.begin(31250); // MIDI Begin
  noteOn();
}
 

void loop(){
  int av1 = // put the ultrasonic measurement here
  trackNote(av1);
}

void noteOff(){
  playing= false;
  // note off + sustain off
  noteSend(0x80,baseNote,127);
  controlSend(64, 0);
}
void noteOn(){
 // note on + sustain on
  noteSend(0x90,baseNote,127);
  controlSend(64, 127);
  playing = true;
}

 void noteSend(byte cmd, byte data1, byte data2) {
  cmd = cmd | channel;
  Serial.write(cmd);
  Serial.write(data1);
  Serial.write(data2);
}

int trackNote(int freq){
  int pb = 0x2000 - (435 - freq);
  sendPB(pb);
  int vel = volume>> 3;
   controlSend(7, vel);
}

void controlSend(byte CCnumber, byte CCdata) {
  byte CCchannel = channel | 0xB0; // convert to Controller message
  Serial.write(CCchannel);
  Serial.write(CCnumber);
  Serial.write(CCdata);
}

void sendPB(int pb){ // send pitch bend message
  Serial.write( (byte)0xE0 | channel);
  Serial.write( pb & (byte)0x7f);
  Serial.write( (pb>>7) & (byte)0x7f);
}



In your code you say " put the ultrasonic measurement here".
I am not sure what part of the code I have been using that is the "ultrasonic measurement". Wich part should I copy/paste from this code?:

Code: [Select]


// MIDI THEREMIN
// Moritz Simon Geist
// www.sonicrobots.com
// v.1.0 14 March 2014
////////////////////////////////
// This sketch uses an HC-SR04 Ultrasonic Sensor and produces an MIDI out signal, according to the measured distance form a object
// Be sure to include the latest MIDI Library  (here 4.0)
// http://playground.arduino.cc/Main/MIDILibrary#.UyNutYUn2Hs
//
// Wiring: Ping pin from the HC-SR04 Ultrasonic Sensor --> arduino Pin 13,
// Echo pin from HC-SR04 Ultrasonic Sensor --> Arduino PIN 12
// MIDI-Out --> TX according to this sketch http://arduino.cc/en/uploads/Tutorial/MIDI_schem.png

#include <MIDI.h>
int pingPin = 13;
int inPin = 12;
long duration;
int cm_new = 20;
int cm_old = 20;
int sens = 5; // sensivity range when to launch a new  note

void setup() {

  Serial.begin(31250); // MIDI Begin
  pinMode(pingPin, OUTPUT); // setup the Pins
  pinMode(inPin, INPUT); // setup the Pins

}
 
void loop()
{


// The PING is triggered by a HIGH pulse of 2 or more microseconds.
// Give a short LOW pulse beforehand to ensure a clean HIGH pulse:

digitalWrite(pingPin, LOW);
delayMicroseconds(2);
digitalWrite(pingPin, HIGH);
delayMicroseconds(10);
digitalWrite(pingPin, LOW);
duration = pulseIn(inPin, HIGH); // the singal from the Sensor is measured. The length of the pulse describes the distance form an object to the sensor.
 
cm_new = map(constrain(duration, 20, 3000), 50, 2000, 96, 48); // contrain --> set a threshold to cut values of the sensor that are to far away of to short (20 .. 3000) MAP --> Map the sensor range to a note values vom 96 (A high C) to 48 (a low C)

if (cm_new != cm_old) // only if a new sensor value is detected, a new nite will be send. IF the object stays stable infront of the sensor, no note will be send.
{
 MIDI.sendNoteOff(cm_old,0,1);   // Stop the old note
 MIDI.sendNoteOn(cm_new,127,1);  // Send a new Note (pitch , velocity 127, on channel 1)
cm_old = cm_new;
}
delay(30); // for staiblity
}


Grumpy_Mike

Quote
I am not sure what part of the code I have been using that is the "ultrasonic measurement".
Are you actually reading the code? You read it like words. Each line does one job. You must try and understand what these lines say.

Come on, I think you can guess which lines pulse the ping sensor and measure the returned pulse. If you are lost look at the comments in your code, that tells you.

For the theory look at this:-
How an Ultrasonic distance sensor works

kreationsministern

Come on, I think you can guess which lines pulse the ping sensor and measure the returned pulse. If you are lost look at the comments in your code, that tells you.

Haha, allright. Maybe I have some kind of idea that it is more complicated than what it actually is. I´ll dig in to it again. Thanks for the link.

kreationsministern

Hello again.

Now I have decided to use one IR sensor instead of the ultrasonic sensor.
I have connected it to A0. But i only get one long tone when I hold my hand over the sensor. I really don't understand how I can modify the code I´m using now to get rid of the information concerning the other IR-sensor that would be controlling the volume. I only want one IR sensor to pitch bend through a range of tones when I move m hand up and down. Please help me out here.

this is what the code looks like now:
Code: [Select]


// MIDI THEREMIN
// by Mike Cook
// v.1.0 03 March 2015
////////////////////////////////

#include <MIDI.h>
boolean playing = false;
const byte channel = 0;
const byte baseNote = 72;

void setup() {

  Serial.begin(31250); // MIDI Begin

}
 

void loop(){
  int av1 = 1027 - analogRead(0);
  int av2 = 1027 - analogRead(1);
  if(av1 <870 && av2 < 870){
     if(!playing)noteOn();
     else {
          trackNote(av2,av1);
     }
  }
  else {
    if(playing) noteOff();
  }
}

void noteOff(){
  playing= false;
  // note off + sustain off
  noteSend(0x80,baseNote,127);
  controlSend(64, 0);
}
void noteOn(){
 // note on + sustain on
  noteSend(0x90,baseNote,127);
  controlSend(64, 127);
  playing = true;
}

 void noteSend(byte cmd, byte data1, byte data2) {
  cmd = cmd | channel;
  Serial.write(cmd);
  Serial.write(data1);
  Serial.write(data2);
}

int trackNote(int freq, int volume){
  int pb = 0x2000 - (435 - freq);
  sendPB(pb);
 
}

void controlSend(byte CCnumber, byte CCdata) {
  byte CCchannel = channel | 0xB0; // convert to Controller message
  Serial.write(CCchannel);
  Serial.write(CCnumber);
  Serial.write(CCdata);
}

void sendPB(int pb){ // send pitch bend message
  Serial.write( (byte)0xE0 | channel);
  Serial.write( pb & (byte)0x7f);
  Serial.write( (pb>>7) & (byte)0x7f);
}



Grumpy_Mike

Modify these three functions:-

Code: [Select]

void setup() {

  Serial.begin(31250); // MIDI Begin
  noteSend(0x90,baseNote,127);
}
 

void loop(){
  int av1 = 1027 - analogRead(0);
   trackNote(av1);
}

int trackNote(int freq){
  int pb = 0x2000 - (435 - freq);
  sendPB(pb);
 
}


Note that the 'note on' call is in the setup and is run only once on start up or reset, because you still haven said what you want to trigger the note. There is no note off call for the same reason. If your MIDI sound module can cope with an infinite length note then it is fine.

Quote
I really don't understand how I can modify the code I´m using now to get rid of the information concerning the other IR-sensor that would be controlling the volume.
Now as you can see this is trivial. You should now look at the modifications and the original and see what has been done. You can not go on getting other people to do your projects for you.

kreationsministern

You should now look at the modifications and the original and see what has been done. You can not go on getting other people to do your projects for you.

Okey! Well, I'm not letting other people do my projects. But since I'm working at same time with the other parts of this project like designing, constructing and writing I´m having trouble to focus all of my time on this arduino-part. So I was just reaching out. But I understand what you mean.

But I have now decided to let the pitch-bend idea wait. I have come up with something that is working good enough with my IR sensor without the PB. The only problem I have now is that the sensor seems to be sending signals random sometimes, even when theres no object infront of it. Like some kind of glitch problem.

Some of the cables are now like laying on top of each other and it's a little bit messy.
can that be a problem? Maybe the cables are effecting each other in some way?

This is the code I,m using now:

Code: [Select]




#include <MIDI.h>
const int analogInPin = A0;  // Analog input pin that the ir-sensor is attached to

int sensorValue = 0;        // value read from the sensor
int outputValue = 0;        // value output to the midi
int outputValue_old = 0;   

const byte channel = 0;



void setup() {
Serial.begin(31250);
}
void loop()
{

  // read the analog in value:
  sensorValue = analogRead(analogInPin);
  // map it to the range of the analog out:
  outputValue = map(sensorValue, 0, 1023, 48, 96);
  // change the analog out value:

/
if (outputValue != outputValue_old)
{
MIDI.sendNoteOff(outputValue_old,0,1); // Stop the old note
MIDI.sendNoteOn(outputValue,127,1); // Send a new Note (pitch , velocity 127, on channel 1)
outputValue_old = outputValue;
}
delay(80); // for staiblity
}


Grumpy_Mike

Quote
Some of the cables are now like laying on top of each other and it's a little bit messy.
can that be a problem?
Yes as can motors, long wires, florescent lights and thermostats.

Quote
This is the code
The code is not the cause of glitching. But if you can not eliminate it you could do some filtering in the software, like averaging or rejecting readings that are radically different from the last reading.

kreationsministern

Yes as can motors, long wires, florescent lights and thermostats.
The code is not the cause of glitching.
Hello again. I´m back with trying to get the pitchbend and the IR-sensor to behave like I want it to.
It works good but theres some parts I would like to modify. Can you maybe give me some advises how to not only pitch bend the base note?  What and where should I modify the code to get a broad range of tones that the pitch bend should slide between?

Code: [Select]



#include <MIDI.h>
boolean playing = false;
const byte channel = 0;
const byte baseNote = 60;

void setup() {

  Serial.begin(31250); // MIDI Begin
  noteSend(0x90,baseNote,127);

}


void loop() {
  int av1 = 1027 - analogRead(0);
//  int av2 = 1027 - analogRead(1);
  if (av1 < 870) {
    if (!playing)noteOn();
    else {
      trackNote(map(av1, 0, 1023, -8000, 8000));
    }
  }
  else {
    if (playing) noteOff();
  }
}

void noteOff() {
  playing = false;
  // note off + sustain off
  noteSend(0x80, baseNote, 127);
  controlSend(64, 0);
}
void noteOn() {
  // note on + sustain on
  noteSend(0x90, baseNote, 127);
  controlSend(64, 127);
  playing = true;
}

void noteSend(byte cmd, byte data1, byte data2) {
  cmd = cmd | channel;
  Serial.write(cmd);
  Serial.write(data1);
  Serial.write(data2);
}

int trackNote(int freq) {
  int pb = freq;
  sendPB(pb);

}

void controlSend(byte CCnumber, byte CCdata) {
  byte CCchannel = channel | 0xB0; // convert to Controller message
  Serial.write(CCchannel);
  Serial.write(CCnumber);
  Serial.write(CCdata);
}

void sendPB(int pb) { // send pitch bend message
  Serial.write( (byte)0xE0 | channel);
  Serial.write( pb & (byte)0x7f);
  Serial.write( (pb >> 7) & (byte)0x7f);
}


Grumpy_Mike

Quote
What and where should I modify the code to get a broad range of tones that the pitch bend should slide between?
Not sure what you mean. The pitch bend will apply to all notes you are producing. I think you haven't thought of exactly what you want to do.
What will trigger these extra notes?

kreationsministern

Not sure what you mean. The pitch bend will apply to all notes you are producing. I think you haven't thought of exactly what you want to do.
What will trigger these extra notes?
Oh I see. My idea is that the IR sensor should send information to my midi-device wich will play a range of different tones. The sensor is activated by objects that are spinning around in front of it. Depending on how the objects are shaped the "music-loops" will sound different.

BUT. I would like the tones to glide (bend) between each other. Smooth like  when two tones bitchbend from one to another. Maybe I have missunderstood the function of the PB-code. Maybe it is not possible to pitchbend through a range of like 20 different tones?

Grumpy_Mike

#28
Apr 08, 2015, 10:05 pm Last Edit: Apr 08, 2015, 10:06 pm by Grumpy_Mike
Quote
BUT. I would like the tones to glide (bend) between each other.
You do not want pitch bend, it sounds to me like you want to control the portamento. That is a function of your tone controller, if available you turn it on with a CC 5 (MSB) and CC 37 (LSB) control.

I repeat what triggers these tones?

kreationsministern

You do not want pitch bend, it sounds to me like you want to control the portamento. That is a function of your tone controller, if available you turn it on with a CC 5 (MSB) and CC 37 (LSB) control.

I repeat what triggers these tones?
Aha, allright. Maybe That´s why I couldn't get my head around this.
I´m not sure what you mean with what trigger the notes. But the midi-signals are sent from the Arduino to my "Korg Volca Keys" through the MIDI-in. I have tried to use the portamento-knob on the Volca Keys with some of the earlier codes from this thread but it seems to ignore it. You mean that I have to send information from the arduino-code concerning the portamento-function? (cc 5 and cc 37)?

Go Up