Introduction: Intel IoT Edison Sonar Theremin

Intel® Edison is Intel's new tiny wonder, featuring i.a. a dual-core Intel® Atom™ processor System on a Chip, 1GB RAM, WiFi, Bluetooth LE which enables you to run a real operating system (linux!) on it and do whatever you can imagine.

Things get even better with the Intel® Edison Arduino Board: If you have already some experience with the Arduino platform, you can upload your Arduino sketches through the Arduino Edison IDE and run them exactly like you would do on the Arduino. The added benefit is that, since your Arduino sketches run as a process in a linux system on your Edison, you can also benefit from all the extra goodies of your Edison (Wireless? Check! Bluetooth? Check! Http server? Check!).

In this instructable, you can build an Intel Edison based sonar theremin! Before you get too excited, let's admit that neither the circuit, nor the sound produced has anything to do with the original theremin :-) http://en.wikipedia.org/wiki/Theremin

Our theremin uses an ultrasonic ranging module to determine the note played by a buzzer. The volume is fixed (and deafening) Moreover, the original theremin plays a continuous spectrum of frequencies, our theremin plays a fixed set of notes (which you can set to dodecaphony, Do major, pentatonic, or a note-set of your choice!)

I am thankful to Instructables and Intel for providing me the Intel® Edison Arduino Board used in this project (I was one of the 250 lucky ones!)

Step 1: Setup

To build your own Intel IoT Edison sonar theremin, you'll need the following:

  1. Intel® Edison Arduino Board
  2. Grove Starter Kit Plus V2.0
  3. Grove Ultrasonic Ranger (or Ultrasonic ranging module HC-SR04 - read below)
    Connect the ultrasonic ranger module to port D7 of your grove shield.
    If you don't have a Grove - Ultrasonic Ranger, you can still use a stock
    Ultrasonic ranging module HC-SR04. The two are largely interchangeable, provided that you do a small cable hack: Change the pinouts (by connecting a second 4-pin cable) from
    GND-VCC-D8-D9 of the Grove Board to GND-ECHO-TRIGGER-VCC of the sonar, so that you access TRIGGER from Arduino Edison's Pin 7 and ECHO from Pin 8

  4. Grove Buzzer
    Connect it to port D6 of the grove shield.
  5. Having successfully installed the Arduino IDE on your computer, updated to the latest Yocto Image and a working terminal connection to the board. For a detailed how-to, you can check my other instructable https://www.instructables.com/id/Touch-me-Edison-b...

Step 2: The Arduino Sketch

Create a new sketch in the Arduino Edison IDE and save it with the following code:

/*<br>    theremin_edison.ino 
    Part of "Intel IoT Edison sonar theremin"
    Copyright 2014 Pavlos Iliopoulos, techprolet.com
    This program is free software: you can redistribute it and/or modify
    it under the terms of the GNU General Public License as published by
    the Free Software Foundation, either version 3 of the License, or
    (at your option) any later version.
 
    This program is distributed in the hope that it will be useful,
    but WITHOUT ANY WARRANTY; without even the implied warranty of
    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
    GNU General Public License for more details.
 
    You should have received a copy of the GNU General Public License
    along with this program.  If not, see <a href="http://www.gnu.org/licenses/" rel="nofollow">http://www.gnu.org/licenses/</a>.

HC-SR04 Ping distance sensor code from jsvester<a href="https://www.instructables.com/id/Simple-Arduino-and-HC-SR04-Example/step3/Upload-the-sketch/" rel="nofollow">

https://www.instructables.com/id/Simple-Arduino-an...>

*/

//89, dodecaphony
//const unsigned int usablePitches[] = {31,33,35,37,39,41,44,46,49,52,55,58,62,65,69,73,78,82,87,93,98,104,110,117,123,131,139,147,156,165,175,185,196,208,220,233,247,262,277,294,311,330,349,370,392,415,440,466,494,523,554,587,622,659,698,740,784,831,880,932,988,1047,1109,1175,1245,1319,1397,1480,1568,1661,1760,1865,1976,2093,2217,2349,2489,2637,2794,2960,3136,3322,3520,3729,3951,4186,4435,4699,4978};
//#define NUM_SAMPLES 89

//52, Do major
//const unsigned int usablePitches[] = {  31,  33,  37,  41,  44,  49,  55,  62,  65,  73,  82,  87,  98,  110,  123,  131,  147,  165,  175,  196,  220,  247,  262,  294,  330,  349,  392,  440,  494,  523,  587,  659,  698,  784,  880,  988,  1047,  1175,  1319,  1397,  1568,  1760,  1976,  2093,  2349,  2637,  2794,  3136,  3520,  3951,  4186,  4699};
//#define NUM_SAMPLES 52

//37, pentatonic
const unsigned int usablePitches[] = { 33, 37, 41, 49, 55, 65, 73, 82, 98, 110, 131, 147, 165, 196, 220, 262, 294, 330, 392, 440, 523, 587, 659, 784, 880, 1047, 1175, 1319, 1568, 1760, 2093, 2349, 2637, 3136, 3520, 4186, 4699};
#define NUM_SAMPLES 37

#define TRIGGER_PIN  7  // Arduino pin tied to trigger pin on the ultrasonic sensor.
#define ECHO_PIN     8  // Arduino pin tied to echo pin on the ultrasonic sensor.
#define BUZZER_PIN   6

#define MAX_DISTANCE_SOUND 110.0

float distanceDivider = 1.0;

void setup() {
  Serial.begin(9600); // Open serial monitor at 115200 baud to see ping results.
  distanceDivider =  MAX_DISTANCE_SOUND / NUM_SAMPLES;
  pinMode(TRIGGER_PIN, OUTPUT);
  pinMode(ECHO_PIN, INPUT);
 
 for (int i = 0; i< NUM_SAMPLES;i++){
   Serial.print ("no ");
   Serial.print (i);
   Serial.print (": ");
   Serial.println (usablePitches[i]);
 }
}

void loop() {
  delay(200);                      // Wait 200ms between pings (about 5 pings/sec). 29ms should be the shortest delay between pings.
  float duration, distance;
  digitalWrite(TRIGGER_PIN, LOW);
  delayMicroseconds(2); 
  digitalWrite(TRIGGER_PIN, HIGH);
  delayMicroseconds(10); 
  digitalWrite(TRIGGER_PIN, LOW);
  duration = pulseIn(ECHO_PIN, HIGH);
  distance = (duration/2) / 29.1;
  if ((distance>0)&&(distance<MAX_DISTANCE_SOUND)){
  	tone(BUZZER_PIN, usablePitches[round(distance/distanceDivider)]);
  	Serial.print("Freq: ");
  	Serial.print( usablePitches[round(distance/distanceDivider)] ); 
  	Serial.print(" Ping: ");
  	Serial.print(distance); // Convert ping time to distance in cm and print result (0 = outside set distance range)
  	Serial.println("cm");
  } else {
    noTone(BUZZER_PIN); 
  }
}<br><br>

As it has now, the code above will produce pentatonic melodies. If you prefer a Do major or dodecaphonic, uncomment the respective lines at the top of the code and comment out the pentatonic part.

Check that the code compiles and upload it to your Intel® Edison.

You are now ready to produce some (beep beep) music! Be careful though, because the Grove Buzzer turned to be far louder than expected:)