Go Down

Topic: Sonar and MIDI Mapping (Read 5504 times) previous topic - next topic

dingledow

Hi

I have a LV-MaxSonar EZ1 and I using this code to get readouts of distance measurements.  This is the code that I am using for that:

Code: [Select]

//Feel free to use this code.
//Please be respectful by acknowledging the author in the code if you use or modify it.
//Author: Bruce Allen
//Date: 23/07/09

//Digital pin 7 for reading in the pulse width from the MaxSonar device.
//This variable is a constant because the pin will not change throughout execution of this code.
const int pwPin = 7;

//variables needed to store values
long pulse, inches, cm;


void setup() {
  //This opens up a serial connection to shoot the results back to the PC console
  Serial.begin(9600);
}


void loop() {
  pinMode(pwPin, INPUT);
    //Used to read in the pulse that is being sent by the MaxSonar device.
  //Pulse Width representation with a scale factor of 147 uS per Inch.

  pulse = pulseIn(pwPin, HIGH);
  //147uS per inch
  inches = pulse/147;
  //change inches to centimetres
  cm = inches * 2.54;
  Serial.print(inches);
  Serial.print("in, ");
  Serial.print(cm);
  Serial.print("cm");
  Serial.println();
  delay(500);
}



I have a potentiometer that sends MIDI data over a DIN-5 MIDI connector attached to my breadboard using this code:

Code: [Select]

/*
* 7.1 Midi OUT controller
* roguescience.org
*
* digital pin 11 (OUTPUT/PWM) --> LED
* digital pin 2 (INPUT) <-- button
* analog pin 0 <-- pot
* tx1 <-- pin 5 (5 PIN DIN aka MIDI jack)
*
* Send a MIDI note when the button is pressed and sends MIDI
* CC data when a potentiometer is turned.
*/

int ledPin = 11;                //choose the pin for the LED - needs to be (3,5,6,9,10, or 11)
int buttonPin = 2;               //choose the input pin for a pushbutton
int potPin = 0;                  //choose the input pin for a potentometer
int buttonVal = 0;                    //variable for reading the button status
int buttonState = 0;            //variable to hold the buttons current state
int bounceCheck = 0;            //variable for debouncing
int potVal = 0;                //variable for reading potentiometer value
int mappedPotVal = 0;          //variable for holding remapped pot value
int prevPotVal = 0;               //variable for storing our prev pot value
int THRESHOLD = 2;            //threshold amount

void setup() {
  pinMode(ledPin, OUTPUT);      //declare LED as output
  pinMode(buttonPin, INPUT);     //declare pushbutton as input
  Serial.begin(31250);            //MIDI communicates at 31250 baud
}

void loop(){

  buttonVal = digitalRead(buttonPin);     //read input value from button
  delay(10);                              //wait 10ms
  bounceCheck = digitalRead(buttonPin);   //check again
  if(buttonVal == bounceCheck){           //if val is the same then not a bounce
    if (buttonVal == HIGH && buttonState == 1) {   //check if the input is HIGH
      digitalWrite(ledPin, LOW);         //turn LED OFF
      midiOUT(0x90, 60, 0); //Note ON (CH 1), middle C, zero velocity turns note off
      buttonState = 0;
    }
    if(buttonVal == LOW && buttonState == 0){
      digitalWrite(ledPin, HIGH);       //turn LED ON
      midiOUT(0x90, 60, 127); //Note ON (CH 1), middle C, velocity 127
      buttonState = 1;
    }

  }

   potVal = analogRead(potPin);         //read input from potentiometer
   mappedPotVal = map(potVal, 0, 1023, 0, 127);  //map value to 0-127
   if(abs(mappedPotVal - prevPotVal) >= THRESHOLD){
     midiOUT(0xB0, 7, mappedPotVal); //Control Change (Ch 1), Controller 7 - default control for volume.
     digitalWrite(ledPin, HIGH);
     prevPotVal = mappedPotVal;
   }
   else{
      digitalWrite(ledPin, LOW);
   }

}

void midiOUT(char command, char value1, char value2) {
  Serial.print(command, BYTE);
  Serial.print(value1, BYTE);
  Serial.print(value2, BYTE);

}


The Sonar is inputting values over Pulse Width, whereas the Pot in the MIDI example is inputting values through an Analog pin.


What code will I need to replace the Analog Potentiometer with a Sonar input over Pulse Width?

Thanks

dxw00d

Code: [Select]
   potVal = analogRead(potPin);         //read input from potentiometer
Here, potVal is a number that relates to the position of the pot wiper.

Code: [Select]
  pulse = pulseIn(pwPin, HIGH);
Here, pulse is a number that relates to the distance to whatever the ping sensor is seeing.

Code: [Select]
   mappedPotVal = map(potVal, 0, 1023, 0, 127);  //map value to 0-127
Here, the potVal is mapped to a range of 0-127.

You need something like
Code: [Select]
   mappedPulse = map(pulse, start, end, 0, 127);  //map value to 0-127

You will need to work out the start and end of the range of numbers that the ping sensor returns. I don't have one, so I don't know.

PS. Please don't cross post. If you didn't understand what I posted on http://arduino.cc/forum/index.php/topic,99709.msg748238.html, you could have said so, and I, or someone else, would have expanded on it.

dingledow

Sorry for reposting something similar.  How would I find out the range?

Thanks

AWOL

Quote
. How would I find out the range?

Write a simple sketch to print raw readings.
Point the sensor at the sky.
Point the sensor at something really close.
Point the sensor at the limits of detection.
Note the values.

dingledow

I'm really sorry for being new to this, but how would I write a sketch to print raw readings?

Thanks

dxw00d

You already have one that converts the raw value to inches and centimetres. One of those options will probably be suitable.

dingledow

Code: [Select]

  pulse = pulseIn(pwPin, HIGH);
  //147uS per inch
  inches = pulse/147;
  //change inches to centimetres
  cm = inches * 2.54;
  Serial.print(inches);
  Serial.print("in, ");
  Serial.print(cm);
  Serial.print("cm");
  Serial.println();
  delay(500);
}


If I change that code above to this:

Code: [Select]

  pulse = pulseIn(pwPin, HIGH);
  Serial.print(pulse);
  Serial.println();
  delay(500);
}


Will that give me raw readouts?

dxw00d


AWOL

Yes, and you could make the first print a println, and skip the second completely.

dingledow

What does 'println' do?  Can you explain it in layman's terms please?

Thanks

dxw00d

http://arduino.cc/en/Serial/Println

dingledow

I have started again with this project starting from this: http://arduino.cc/en/Tutorial/Midi

I can get raw values from the MaxBotix sonar using this code:

Code: [Select]


//Feel free to use this code.
//Please be respectful by acknowledging the author in the code if you use or modify it.
//Author: Bruce Allen
//Date: 23/07/09

//Digital pin 7 for reading in the pulse width from the MaxSonar device.
//This variable is a constant because the pin will not change throughout execution of this code.

const int pwPin = 7;

//variables needed to store values

long pulse, inches, cm;


void setup() {
  //This opens up a serial connection to shoot the results back to the PC console
  Serial.begin(9600);
}


void loop() {
  pinMode(pwPin, INPUT);
    //Used to read in the pulse that is being sent by the MaxSonar device.
  //Pulse Width representation with a scale factor of 147 uS (microseconds) per Inch.

  pulse = pulseIn(pwPin, HIGH);
  Serial.println(pulse);
  delay(500);
}


I am trying to change get the raw values to map to the range 0-127 so the distance measurement can act as a note.

I have put this code together, but it does not work:

Code: [Select]

//Feel free to use this code.
//Please be respectful by acknowledging the author in the code if you use or modify it.
//Author: Bruce Allen
//Date: 23/07/09

//Digital pin 7 for reading in the pulse width from the MaxSonar device.
//This variable is a constant because the pin will not change throughout execution of this code.

const int pwPin = 7;

//variables needed to store values

byte note = 0;            // The MIDI note value to be played

long pulse;


void setup() {
  //This opens up a serial connection to shoot the results back to the PC console
  Serial.begin(31250);
}


void loop() {
  pinMode(pwPin, INPUT);
    //Used to read in the pulse that is being sent by the MaxSonar device.
  //Pulse Width representation with a scale factor of 147 uS (microseconds) per Inch.

  pulse = pulseIn(pwPin, HIGH);
  Serial.println(pulse);
  delay(500);
 
  mappedPulse = map(pulse, 827, 15000, 0, 127);  //map value to 0-127
 
}

//  plays a MIDI note.  Doesn't check to see that
//  cmd is greater than 127, or that data values are  less than 127:
void noteOn(byte cmd, byte data1, byte data2) {
   Serial.write( byte(cmd) );
   Serial.write( byte(data1) );
   Serial.write( byte(data2) );
}




Can someone PLEASE help me write it!! :)

PaulS

Once you have a mapped value, don't you think you should call noteOn()?
The art of getting good answers lies in asking good questions.

dingledow

I keep getting the error:

Code: [Select]
Final_MIDI2.cpp: In function 'void loop()':
Final_MIDI2:32: error: 'mappedPulse' was not declared in this scope

PaulS

Where do you actually define a type for mappedPulse?
The art of getting good answers lies in asking good questions.

Go Up