Saturday, October 29, 2011

Ultrasonic Theremin

UPDATE: i have redone the code in the last hour with the help of some Arduino forum members (mainly "Nick Gammon", thanks!), and now it is way more responsive...New vid up

Friday night i made a thermin using a ultrasonic module. the arduino reads module which says how far away my hand is from it(the module) in centimeters. then according to how far my hand is away from the module, the Arduino plays a coordinating tone. the closer my hand is, the lower the tone the speaker plays and each tone has 5 centimeters. so the first 5cm in front of the sensor is dead space, then 5 to 10cm is the lowest tone, and 10 to 15cm is the a little higher tone and so on up to 70cm



The distortions are actually caused by the code being too efficient, i figured out that i needed to add a delay before the code loops again.

Code:

#define trig 7 //trigger pin on sonar module
#define echo 6 //echo pin
#define spkr 4
#define led 12
int dist; //how far the object is away from the module(cm)
float valueSensor=0;

//tones array which holds the frequency to play.
float pitchTable[] = {
  329.63, //E4
  349.23, //F4
  369.99, //F#4/Gb4
  392.00, // G4
  415.30, // G#4/Ab4
  440.000000, // A
  466.163757, // A#/Bb
  493.83301, // B
  523.251160, // C
  554.365234, // C#/Db
  587.329529, // D
  622.253967, // D#/Eb
  659.255127, // E
  698.456482, // F
  739.988831, // F#/Gb
  783.990845, // G
  830.609375, // G#/Ab
  880.00, //A5
  932.33 //A#5/Bb5
};

#define NUMITEMS(arg) (sizeof (arg) / sizeof (arg [0]))

void setup()
{
  pinMode(echo, INPUT);
  pinMode(trig, OUTPUT);
}

void loop()
{
  //send a trigger signal
  digitalWrite(trig, HIGH);
  delayMicroseconds(10);
  digitalWrite(trig, LOW);
  //receive the trigger signal echo, and calculate cm to the object
  valueSensor= pulseIn(echo, HIGH);
  dist= valueSensor/58;

  // each 5 positions represents a different note
  byte i = dist / 5;

  // play note if in range
  if (i < NUMITEMS (pitchTable))
  {
    tone(spkr,pitchTable[i]);
  }
  else
  {
    tone(spkr,523.251160);
  }
  delay(125);
}


Code for Just Reading Sonar Value:

#define trig 7 //trigger pin on sonar module
#define echo 6 //echo pin
int dist; //how far the object is away from the module(cm)
int valueSensor = 0; //see here, just added this line

void setup()
{
  Serial.begin(9600);
  pinMode(echo, INPUT);
  pinMode(trig, OUTPUT);
}

void loop()
{
  //send a trigger signal
  digitalWrite(trig, HIGH);
  delayMicroseconds(10);
  digitalWrite(trig, LOW);
  //receive the trigger signal echo, and calculate cm to the object
  valueSensor= pulseIn(echo, HIGH);
  dist= valueSensor/58; //converts raw to cm, valueSensor/74/2 = inches
 
  Serial.println(dist);
}


Pics:


LM386 scheme:

14 comments:

  1. Now what you need to do is make some music with it.

    ReplyDelete
  2. your code is giving me problems sir!!!
    i don't know much of programming,,,the compiler is telling me that "lt was not declared in this scope"
    and then it highlights the if bracket???
    please help me sir!!!

    ReplyDelete
  3. sorry bout that, the code got converted to html as it went into the post and so it replaced all the "<" and ">"s with the html equivalent.
    fixed now :)

    ReplyDelete
  4. thank you sir!!! you've made my day
    it worked...
    1 more question,,,,i'm only using my arduino and a simple piezoelectric buzzer....and not your amplifier circuit....right now it does not sound good on the buzzer but i'm planning to connect a guitar jack to it and via that i'm expecting the sound to come out through my digital guitar processor (the digitech rp200A)
    would u recommend me to go ahead with this plan??

    ReplyDelete
  5. ive never used a guitar amp before, but theres no reason i can think of why it wouldn't work. don't worry you bothering me; my projects have actually been put to use by someone else now. :)

    go for it:)

    also, later after the video, i used some nicer speakers that i pulled out of a imac(see other post), and they were way better.

    If you are going to use this in any sort of semi public environment, i would recommend putting a switch in so you can shut it mute this dang obnoxious thing between playing with it

    ReplyDelete
  6. cool....thank you so much sir...
    i really appreciate this....thank you for all your help and guidance!!! :)
    will keep you updated with my work thanks again!!! peace ;)

    ReplyDelete
  7. is there a way by which i can add buttons to this project to play different scales by pressing different buttons,,, for example 8 buttons in total,,,,,out of which 7 choose the scales in the keys of C,D,E,F,G,A,B,,,,and the 8th button can be used for choosing whether the scale is major or minor??

    ReplyDelete
  8. that would be fairly simple, just create a new pitch table that uses the minor or major(im not sure which i used in the code) version then use an if statement.

    if button is pressed, then use pitchtable, else use pitchtable2

    if you need help with code; no problem

    ReplyDelete
  9. i'm pretty new to programming so could u plz help me out with this!!! here's the code that i tried,,,,

    \\ #define trig 7 //trigger pin on sonar module
    #define echo 6 //echo pin
    #define spkr 4
    #define led 13
    const int buttonPin = 2;
    int buttonState = 0;
    int dist; //how far the object is away from the module(cm)
    float valueSensor=0;

    //tones array which holds the frequency to play.
    float pitchTable[] = {
    82.41, // E2
    92.50, // F#2
    98.00, // G2
    110.00, // A2
    123.47, // B2
    130.81, // C3
    146.83, // D3
    164.81, // E3
    185.00, // F#3
    196.00, // G3
    220.00, // A3
    246.94, // B3
    261.63, // C4
    293.66, // D4
    329.63, // E4
    369.99, // F#4/Gb4
    392.00, // G4
    440.000000, // A4
    493.83301, // B4
    523.251160, // C5
    587.329529, // D5
    659.255127, // E5
    739.988831, // F#/Gb5
    783.990845, // G5
    880.00, //A5
    987.77, // B5
    1046.50, // C6
    1174.66, // D6
    1318.51, // E6
    };

    float pitchTable2[] = {
    82.41, // E2
    92.50, // F#2
    // 98.00, // G2
    103.83, // G#2
    110.00, // A2
    123.47, // B2
    // 130.81, // C3
    138.59, // C#3
    // 146.83, // D3
    155.56, // D#3
    164.81, // E3
    185.00, // F#3
    // 196.00, // G3
    207.65, // G#3
    220.00, // A3
    246.94, // B3
    // 261.63, // C4
    277.18, // C#4
    // 293.66, // D4
    311.13, // D#4
    329.63, // E4
    369.99, // F#4/Gb4
    // 392.00, // G4
    415.30, // G#4
    440.000000, // A4
    493.83301, // B4
    // 523.251160, // C5
    554.37, // C#4
    // 587.329529, // D5
    622.25, // D#5
    659.255127, // E5
    739.988831, // F#/Gb5
    // 783.990845, // G5
    830.61, // G#5
    880.00, //A5
    987.77, // B5
    // 1046.50, // C6
    1108.73, // C#6
    // 1174.66, // D6
    1244.51, // D#6
    1318.51, // E6
    };

    #define NUMITEMS(arg) (sizeof (arg) / sizeof (arg [0]))

    void setup()
    {
    pinMode(echo, INPUT);
    pinMode(trig, OUTPUT);
    pinMode(buttonPin, INPUT);
    }

    void loop()
    {
    //send a trigger signal
    digitalWrite(trig, HIGH);
    delay(1);
    digitalWrite(trig, LOW);
    //receive the trigger signal echo, and calculate cm to the object
    valueSensor= pulseIn(echo, HIGH);
    dist= valueSensor/58;

    // each 5 positions represents a different note
    byte i = dist / 5;

    buttonState = digitalRead(buttonPin);

    // play note if in range
    if (i < NUMITEMS (pitchTable) && buttonState == LOW)
    {
    tone(spkr,pitchTable[i]);
    }
    else if (i < NUMITEMS (pitchTable) && buttonState == HIGH)
    {
    tone(spkr,pitchTable2[i]);
    }
    else
    {
    tone(spkr,329.63);
    }
    delay(60);
    }

    ReplyDelete
  10. in:
    if (i < NUMITEMS (pitchTable) && buttonState == LOW)
    {
    tone(spkr,pitchTable[i]);
    }
    else if (i < NUMITEMS (pitchTable2) && buttonState == HIGH)
    {
    tone(spkr,pitchTable[i]);
    }
    else
    {
    tone(spkr,329.63);
    }

    in the else if it needs to be tone(spkr,pitchTable2[i]);
    not
    tone(spkr,pitchTable[i]);

    why \\ #define trig 7?
    needs to be #define trig 7

    the notes seem fairly close between pitch table 1 and 2, try putting really different tones in the 2nd pitch table so you can tell

    ReplyDelete
  11. ok thank you,,,i'll try this out

    ReplyDelete
  12. pls..can any 1 send me the AVR code for this...

    ReplyDelete
  13. ooohh MAN your my hero ok. really i mean i thought i had looked.... i am so glad you posted your code! thanks so so so much man! i of course would not mind if you could suggest how to integrate several ultrasonic sensors to work in an array to produce a range of tones

    ReplyDelete
  14. quite simple, really. just do this again:

    //send a trigger signal
    digitalWrite(trig, HIGH);
    delayMicroseconds(10);
    digitalWrite(trig, LOW);
    //receive the trigger signal echo, and calculate cm to the object
    valueSensor= pulseIn(echo, HIGH);
    dist= valueSensor/58;

    but with the pins adjusted for another sonar on different pins.

    ReplyDelete