Arduino – Basic Theremin meets Processing!

My last theremin involved a small speaker. Now I’ve replaced the speaker with my PC, using processing to pick up the values from the SRF05 ultrasound sonar distance sensor and...

My last theremin involved a small speaker. Now I’ve replaced the speaker with my PC, using processing to pick up the values from the SRF05 ultrasound sonar distance sensor and play different notes accordingly – which gives multiple possibilities and far better sounds.

So to start with check out my previous theremin, the circuit is the same except for removing the speaker and the Arduino code now prints values to the serial port instead of outputing directly to a speaker. The only thing that I’m doing here that is really new is using the minim libary for Processing, built by this chap (thankyou). What this allows us is to assign a sound file to a variable in Processing and then gives us functions to start/stop the sound.

In my processing code you’ll see that I’ve got 12 sounds, one for each chromatic note and at the moment they’re from a piano. To get sounds and samples to use you can sign up to freesound.org. Mine I got here from ‘pinkyfinger’ and once you’ve decided which sounds you want to use then the rest is fairly easy – the more samples and octaves the better. I’ve used the piano set here just so I can hear the different notes and I’ve only 12 notes (chromatic scale) but eventually Iwould like to expand this to say 48 notes.

When you get your sounds I’ve found it’s easiest to use .wavs but minim will allow you to use WAV, AIFF, AU, SND, and MP3 files. Also I store my sounds in the root of the folder where I’m saving my processing sketch.

Ok, lets start with the Arduino parts, circuit and sketch.

Arduino Theremin Parts

SRF05 Ultrasonic range finder
Arduino Deumilanove w/ ATMEGA328
Breadboard / Prototyping board (you can actually do this without a breadboard)
Jumper/ Connector wires

The Theremin Arduino Circuit

Basically the same as before just without the speaker on it. For more info on the SRF05 checkout my past stuff here. In this instance Processing is going to do all the work, so the circuit just needs to pass values from the SRF05 to Arduino, which in turn passes values to my PC via the USB cable.

piano-theremin

The Arduino Theremin Sketch

Very cut down version, it takes the value as before and converts it to a distance and then just prints it to a new line in on the serial port.

// written at: luckylarry.co.uk
// very easy Theremin combined with processing
// sketch prints out distance to the serial port
// processing picks up value and plays notes accordingly
// no annoying speaker drone! :) 

// setup pins and variables for SRF05 sonar device
int echoPin = 2;                                // SRF05 echo pin (digital 2)
int initPin = 3;                                // SRF05 trigger pin (digital 3)
unsigned long pulseTime = 0;                    // stores the pulse in Micro Seconds
unsigned long distance = 0;                     // variable for storing the distance (cm) we'll use distance as a switch for the speaker

//setup
void setup() {

  pinMode(initPin, OUTPUT);                     // set init pin 3 as output
  pinMode(echoPin, INPUT);                      // set echo pin 2 as input
  Serial.begin(9600);                           // start the serial port

} 

// execute
void loop() {
  digitalWrite(initPin, HIGH);                  // send 10 microsecond pulse
  delayMicroseconds(10);                        // wait 10 microseconds before turning off
  digitalWrite(initPin, LOW);                   // stop sending the pulse
  pulseTime = pulseIn(echoPin, HIGH);           // Look for a return pulse, it should be high as the pulse goes low-high-low
  distance = pulseTime/58;                      // convert the pulse into distance (cm)

  // make the sound.
  // check the distance, if over 50cm make no sound - send no signal
  if (distance > 50) {
    Serial.println(distance);                   // print the distance value to the serial port
    delay(50);                                  // delay for 50 milliseconds before starting again...
  }
}


Next up we have processing, which will look for values on the serial port, so first upload the Arduino code to your board and test it works. Next start up Processing to finish off the code. If like me you’re fairly new to processing there’s lots of info to be had at: http://www.arduino.cc/playground/Interfacing/Processing

The Processing Theremin Sketch

With your code now running on the Arduino board we now need processing to pick up these values. Previously I had something of an issue getting these values and reading them. But in hindsight I was being a bit dim when I realised I could just look in the serial port for when a new line (n) was printed which would tell me that a new value was about to be sent. Of course thats providing your Arduino sketch is using Serial.println() (print line) instead of Serial.print() which just chucks every value into one long string – and if you look at my previous attempts with processing you can laugh at how I started splitting this huge string up etc… Oh hindsight is a wonderful thing, anyway, I digress, below is the processing sketch:

// written at: luckylarry.co.uk
// very easy Theremin combined with processing
// sketch prints out distance to the serial port
// processing picks up value and plays notes accordingly
// no annoying speaker drone! :)  replace the sounds and delays with
// your own...

import processing.serial.*;                // import serial library so we can read the serial port
import ddf.minim.*;                        // import minim library

// define the serial port
Serial myPort;          

// define minim variables:
// here we say that variable A is an audiosample etc...
Minim minim;
AudioSample GSharp;
AudioSample A;
AudioSample Bb;
AudioSample B;
AudioSample C;
AudioSample CSharp;
AudioSample D;
AudioSample Eb;
AudioSample E;
AudioSample F;
AudioSample FSharp;
AudioSample G;

// setup
void setup () {

  // set up the variables, loading in the sound files from your project folder
  // which should be the same place as where you save this sketch
  // details on using minim and audioSample are here: http://code.compartmental.net/tools/minim/manual-audiosample/
  minim = new Minim(this);
  GSharp = minim.loadSample("GSharp.wav", 2048);
  A = minim.loadSample("A.wav", 2048);
  Bb = minim.loadSample("Bb.wav", 2048);
  B = minim.loadSample("B.wav", 2048);
  C = minim.loadSample("C.wav", 2048);
  CSharp = minim.loadSample("CSharp.wav", 2048);
  D = minim.loadSample("D.wav", 2048);
  Eb = minim.loadSample("Eb.wav", 2048);
  E = minim.loadSample("E.wav", 2048);
  F = minim.loadSample("F.wav", 2048);
  FSharp = minim.loadSample("FSharp.wav", 2048);
  G = minim.loadSample("G.wav", 2048);

  // List serial ports, saves us trying to figure out which COM we're using.
  println(Serial.list());
  // Open the active port - providing you've only got one sending serial data (which you should)
  myPort = new Serial(this, Serial.list()[1], 9600);
  // don’t read the serial buffer until we see a new line - this is genius and simple compared with my last efforts
  myPort.bufferUntil('n');
}

void draw() {
  // we need to declare the draw function even though we're not using it!!
}

void serialEvent (Serial myPort) {
  // get the string from the serial buffer - gets all chars until the next line break...
  String bufferString = myPort.readStringUntil('n');

  if (bufferString != null) {
    // get rid of any whitespace - sometimes the serial buffer can have blanks etc.. in the string
    bufferString = trim(bufferString);
    // convert the value to an int - we're only sending numbers over the serial port so parsing it to an int shouldn't ever be an issue.
    float inByte = float(bufferString);
    int pulse = int(bufferString);         // declare a variable to hold our value.
    println(pulse);                        // for debug print the value so we can check it.

    // remember that our pulse is in CM so if its less than 5cm then do this etc... else do this... else do this.. for as many sound samples
    if ( pulse < 5 ) {
      GSharp.trigger();
      delay(25);
    }
    else if ( pulse < 8 ) {
      A.trigger();
      delay(25);
    }
    else if ( pulse < 11 ) {
      Bb.trigger();
      delay(25);
    }
    else if ( pulse < 14 ) {
      B.trigger();
      delay(25);
    }
    else if ( pulse < 17 ) {
      C.trigger();
      delay(25);
    }
    else if ( pulse < 20 ) {
      CSharp.trigger();
      delay(25);
    }
    else if ( pulse < 23 )  {
      D.trigger();
      delay(25);
    }
    else if ( pulse < 26 ) {
      Eb.trigger();
      delay(25);
    }
    else if ( pulse < 29 ) {
      E.trigger();
      delay(25);
    }
    else if ( pulse < 32 ) {
      F.trigger();
      delay(25);
    }
    else if ( pulse < 35 ) {
      FSharp.trigger();
      delay(25);
    }
    else if ( pulse < 38 ) {
      G.trigger();
      delay(25);
    }
    else if ( pulse > 50 ) {
      // if the distance is greater than 50cm then play nothing
    }

  } // end if there's a value in the serial bufferstring

}   // end void serialevent()

This content is published under the Attribution-Noncommercial-Share Alike 3.0 Unported license.

Technorati Tags: , , , , , , , , ,

  1. Arduino + Processing: Make a Radar Screen to Visualise Sensor Data from SRF-05 – Part 2: Visualising the Data
  2. Arduino & Processing – Getting values from SRF05 ultrasound sensor & serial port
  3. Arduino – A Basic Theremin
  4. Arduino + Processing – Make a Radar Screen to Visualise Sensor Data from SRF-05 – Part 1: Setting up the Circuit and Outputting Values
  5. Arduino: Controlling the Robot Arm
  6. Arduino + Processing – 3D Sensor Data Visualisation
  7. Arduino + Processing – Make a Radar Screen – Part 3: Visualising the Data from Sharp Infrared Range Finder
  8. Arduino – making a basic drum machine
  9. Obstacle avoidance Arduino robot – build your own larryBot
  10. Arduino – Redefining the TV Remote