MiniMin - a Theremin Style Instrument From 6 Components

7,184

82

32

Introduction: MiniMin - a Theremin Style Instrument From 6 Components

About: Retired software engineer, womblin' in the free world.

The aim of this project is to build a playable Theremin style instrument using the minimum number of components. The Theremin is an electronic instrument played by moving both hands in close proximity to the device. It requires no physical contact between the player and the instrument. A conventional Theremin uses electromagnetic fields to sense the distance of the players hands from two antennae. The MiniMin uses two low cost ultrasonic distance detectors controlled by an Arduino micro-controller.

Learning to play a traditional Theremin is notoriously difficult. For this reason, the MiniMin has a 'cheat' mode where the pitch will 'snap' to the closest musical note in a scale. Four musical scale options are provided :-

  • Chromatic
  • C Major
  • C Minor
  • C Minor pentatonic

Additional scales can be added simply by defining an array of frequency values. Traditional behaviour or 'snap to scale' mode can be selected when the Arduino sketch is compiled.

Supplies:

The MiniMin comprises only six components: -

1 X Arduino microcontroller - I used an Uno but any compatible should work

2 X Ultrasonic range sensors - I used the ELEGOO HC-SR04

1 X 270 Ohm resister

1 X 100 nF capacitor

1 X Audio output socket (6.3mm or 3.5mm)

The circuit is simple enough for point-to-point hand wiring or you could use a breadboard or perfboard.

The MiniMin runs happily off USB power so no special power supply is required.

You will also need a PC with the Arduino IDE installed to load the software.

Teacher Notes

Teachers! Did you use this instructable in your classroom?
Add a Teacher Note to share how you incorporated it into your lesson.

Step 1: How It Works

The circuit for the MiniMin is shown above.

The two Ultrasonic range detectors replace the antenna of the traditional Theremin. One controls the frequency (pitch) of the output and the other controls the amplitude (volume). Operation of the sensors is straightforward. The Arduino sends a digital pulse to the TRIG pin of the sensor causing it to emit a burst of high frequency audio. If an echo is detected the sensor toggles the ECHO pin which is monitored by the Arduino. By measuring the time delay between the outgoing pulse and returning echo we can calculate the distance. As sound takes 29 microseconds to travel one cm, and must travel out and back, we can divide the time to the echo by 5.8 to get the distance in mm (the project uses time/6 as an approximation).

The audio output is generated using Pulse Width Modulation (PWM) to reduce the component count. It requires only one capacitor and resistor connected between the PWM output (digital pin 9 on the Uno) and the output socket. The PWM output is a string of digital pulses. If the pulses are high enough frequency they will charge the capacitor and give a rising voltage on the output. If the pulses are of low frequency the capacitor will discharge and the output voltage falls. By varying the pulse frequency (or pulsewidth) a waveform can be generated. Although this kind of PWM audio is fairly low quality it is good enough for this application. The project uses the Mozzi audio library to generate a triangle wave which is sent to the output.

The MiniMin has a usable range of around three octaves which is comparable to a mid-range analogue Theremin. The sketch uses a tuning range of C4 to C6 (one octave below Middle C to two octaves above) which can be changed by editing the values of 'lowestFreq' and 'highestFreq'. Similarly, the operating distance of the sensors can be tweaked by changing the 'low' and 'high' threshold values.

The two sensors of the Minimin are placed at 90 degrees to each other, similar to the antennae on a regular Theremin. The distances measured are mapped to frequency and volume variables which are applied to the Mozzi oscillator.

Line 22 of the sketch determines the operating mode of the MinMin. If set to 'false' it will operate as a traditional theremin with a constantly variable frequency response. If set to 'true' the MiniMin will choose the closest note in the selected scale.

const boolean stepMode = false;

The desired scale is selected by 'uncommenting' the corresponding array of frequency values (lines 24 - 42 of the sketch).

The complete sketch can be found on my GitHub page.

Step 2: Demo and Future Plans

The video above gives a brief demo of the MinMin (external delay and reverb effects have been added). The current version is very much a breadboard prototype. The next step is to choose a suitable enclosure and hard wire the components. I like the idea of using a short length of drainpipe with a 90 degree elbow to keep the sensors at a right angle. Swapping the Arduino Uno for the smaller Nano would allow a more compact case to be used.

The aim of this project was to use as few components as possible. However, the addition of a some extra hardware could greatly increase the functionality. Some simple switches would allow different waveforms, mode, scales and octaves to be selected. Next job - the MiniMinMax!

Instrument Contest

Participated in the
Instrument Contest

Be the First to Share

    Recommendations

    • Trash to Treasure Contest

      Trash to Treasure Contest
    • Raspberry Pi Contest 2020

      Raspberry Pi Contest 2020
    • Wearables Contest

      Wearables Contest

    32 Discussions

    0
    robertorossi313
    robertorossi313

    Question 14 days ago on Introduction

    Hi, I just constructed the MiniMin and I can see with a scope the echo of both channels but the output of pin 9 is only a steady triangular wave with no changes.
    Is there something missing in the audio part that is not responding to the changes that I see in both echos?

    0
    djaawn
    djaawn

    23 days ago

    Hi. I've been able to make it work. And I love it! I've been able to mess with the frequencies and such. The thing I want to do is use a button or switch to change the key by changing a variable (an array of frequencies for each major key) which is fed into the function in place of the notes[] array.

    This is my first arduino project, so forgive me if I ask stupid questions or break etiquette.

    I have been able to execute a simple hardware to software manipulation — the toggling of an LED via button push. And I think I know how to write the function to declare different variables which contain the different keys (frequency sets). So here's my issue. I understand the logic behind what needs to happen. But I can't figure out where to put the function which determines the frequency set. As I understand, the functions needed to determine the button state need to be in the loop. But manipulating your sketch, this has already all been executed before even reaching the loop. I've tried changing the variable from the loop. No go. Tried wrapping up the non-setup portions of the code as a function, and running that code in the loop, after my button code. Still no go.

    So, without asking you for specific code...can you point me maybe to how I might be able to manipulate notes[] variable and have it actually affect the function? Am I incorrect in thinking that the button detection must go in the loop?

    Here's my build (unenclosed of course). I've also run it through guitar pedals and such and it's wacky!

    https://www.instagram.com/p/B7-GY34gtRM/

    0
    techno-womble
    techno-womble

    Reply 20 days ago

    Thanks for building it - great to see another one!
    If you want to make real-time changes to the sound you will need to put the code in the updateControl function (starting line 95). This is the main loop when using the Mozzi library. It is called 128 times per second as defined by CONTROL_RATE (line 20).
    Hope this helps.

    0
    djaawn
    djaawn

    Reply 19 days ago

    Oooh, thank you so much! That is so helpful, and I can finally try it out today. If I can get that working, then that opens up so much for me.
    Again, thanks for being so generous and specific to my question.
    — D

    0
    djaawn
    djaawn

    Reply 17 days ago

    Definitely helpful. Thank you.
    So I got a bush to toggle between step mode and free form mode by changing the const for that to a global variable instead. There is just one (I think one?) issue that I can't seem to figure out.

    My other button is intended to cycle through a set of frequency arrays such as:
    <code>
    notes1[] = {.....}
    notes2[] = {.....}
    </code>

    I figured I'd be able to check the button count and change the notes[] set I'm using based on that by doing something like (which is how I'm changing the global stepmode variable from within the main Mozzi function):

    <code>
    if (buttonCount == 2) { notes[] = notes2[]; }
    //or
    if (buttonCount == 2) { notes = notes2; } // so I don't message with bracket contents
    </code>
    ...and so one for each frequency array.

    But I just get a variety of erros. The lines that I can't figure to manipulate are:
    <code>
    int nearest(int x)
    {
    int idx = 0; // by default near first element
    int distance = abs(notes[idx] - x); // this line
    }
    for (int i=1; i<37; i++)
    {
    int d = abs(notes[i] - x); // this line
    }
    if (d < distance)
    {
    idx = i;
    distance = d;
    }
    }
    return idx;
    }
    </code>

    ...and one more instance of notes[] below with contents in the brackets.

    I've tried other things but this is already long-winded enough. I'd appreciate any guidance that might be offered. It's very generous. My js and PHP tactics aren't working for me in this case. ;)

    0
    Redwoodturner
    Redwoodturner

    Question 27 days ago on Step 1

    Hi John,
    I get the error message - 'Serial' was not declared in this scope - as you haven't declared anything, is it in the "library"?
    Derek

    0
    techno-womble
    techno-womble

    Answer 27 days ago

    That's odd. It compiles without errors for me. My only thought is that it might be device specific. I used an UNO - maybe other Arduinos are different?
    The serial port was used for testing but isn't used in the final version. You can safely delete line 75 of the sketch (Serial.begin(9600);)

    0
    Redwoodturner
    Redwoodturner

    Reply 24 days ago

    Thanks for a quick response. For some reason a lot of .h items were downloaded to the beginning of the script - no idea why and also I had a faulty sensor. As a previous user said - I now get the LED to activate with movement, but no signal reaches the speaker. I've checked the polarity and used a scope, but other than an earth hum nothing happens. Any ideas? I'm using 100microF and have tried several resistors below 300R with the Cmin pentatonic.

    0
    lorilabskaus
    lorilabskaus

    Question 24 days ago on Step 2

    Hello techno-womble. I'm not getting any audio out of it. I do get a "pop" whenever I power it on or unplug the cable to the amp. Also, there is an orange led on the uno that flickers when I move my hand in front of the pitch sensor but not the volume. I do get a warning that the mozzi library is not valid. " Invalid Version 'version 2013-07-07-17:51' for library in: C:\Users\txxx\Documents\Arduino\libraries\Mozzi ". I haven´t got a clue what that means. What signal should ocur on pin 9 of the Arduino? I do have an oscilloscope to measure. Thanks in Advance.

    0
    mossrid
    mossrid

    25 days ago

    I have tried everything I know (which isn't a great deal when it comes to Arduino C++) but output signals from pin 9 just do not exist! My oscilloscope shows both sensors are working and I can get some printouts to the monitor screen by inserting a 'Serial.println (x)' command in various parts of the code. Obviously, this upsets the speed of the sketch and gives some 'burps' from the speaker, but I can get numeric printouts from 'int freq' and 'int vol'.
    During the compile phase, I always get the error "Invalid version 'version 2013-07-07-17:51' " which refers to the Mozzi library. I have downloaded and replaced it three times but I still get the error message. Is it possible that you have a different version and, if so, where would I find it?
    This looks like a great project but without some help please, I'm getting nowhere.
    I have tried some of the example code in the Mozzi folder (eg Sinewave, Bamboo, etc) which work well, so I know my setup is OK. I'd love to get this working, so any help would be much appreciated, thanks.

    0
    algures
    algures

    27 days ago

    Hola, gracias por compartir tu proyecto. Tengo un error en el cçodigo que no comprendo. Por favor, puedes ayudarme? Gracias
    Arduino:1.8.9 (Windows Store 1.8.21.0) (Windows 10), Tarjeta:"Arduino/Genuino Uno"
    ATENCIÓN: Categoría '' de la biblioteca Mozzi no es válida. Configurando a 'Uncategorized'
    In file included from C:\Users\vicen\Desktop\ARDU\sketch_jan30b\sketch_jan30b.ino:3:0:
    C:\Users\vicen\Documents\Arduino\libraries\Mozzi/AudioConfigStandard9bitPwm.h:14:0: warning: "PWM_RATE" redefined
    #define PWM_RATE 16384

    #define PWM_RATE 125000
    #define AUDIO_BIAS ((uint8_t) 244)
    #define AUDIO_BIAS ((unsigned int) 0x2000)
    warning: "PWM_RATE" redefined
    #define PWM_RATE 32768
    #define PWM_RATE 16384
    .
    .
    .
    .

    0
    nathanduncanphoto
    nathanduncanphoto

    4 weeks ago

    Hey this looks amazing and I'm looking at the parts now to build it. Thank you for posting! One question about the capacitor, should the 100 uF capacitor be 10v, 35v, 50v? I'm seeing several voltage levels available. Thanks!

    0
    techno-womble
    techno-womble

    Reply 4 weeks ago

    The maximum voltage present is 5V so any will work. The capacitor is not a critical component so feel free to experiment.
    If you connect the MiniMin to a small speaker you can omit the RC network entirely.

    0
    nathanduncanphoto
    nathanduncanphoto

    Reply 4 weeks ago

    Excellent to know; thanks again! 👌

    0
    welchk76
    welchk76

    4 weeks ago

    I've built it! However, I'm not getting any audio out of it. I do get a "pop" whenever I power it on or unplug the cable to the amp. Also, there is an orange led on the uno that flickers when I move my hand in front of the pitch sensor but not the volume.

    I've gone over the wiring diagram multiple times and can't seem to figure this out. I'm running the code as stock without any changes. I used the same color wires as in the diagram just to keep things easy. I'm including an image of my build hoping that you might see something that stands out. Thanks for a neat project!

    IMG_0422.jpegIMG_0423.jpegIMG_0424.jpeg
    0
    techno-womble
    techno-womble

    Reply 4 weeks ago

    Sorry about this but there is an error in the circuit diagram. It shows a polarized capacitor that is connected the wrong way round. My mistake. Connecting the side with stripe to GND should fix it. Alternatively, a non-polarized capacitor would work.The flashing LED is a good sign as the pitch sensor is connected to the same pin as the internal LED. I'll update the diagram.

    1
    Trollfar
    Trollfar

    5 weeks ago on Step 1

    I agree with MicheleA41, the capacitor looks like 100uF (or 100μF). I also wonder what its purpose is. If it is there to block DC from reaching the jack-socket then it should be in series with the resistor.

    The jack-socket as shown is wired out of phase. The pin on the top is the one that will connect to the sleeve of the jack, and this should be ground. It matters if this circuit is connected to the same power source as the equipment that comes after it, an audio interface or small speaker for example.

    Otherwise it’s a very neat and cool project!

    0
    techno-womble
    techno-womble

    Reply 5 weeks ago

    Thanks for spotting the error in the socket wiring! The resistor/capacitor network acts as an integrator to smooth the rapid pulses from pin 9 into an analogue audio waveform. The values of 270 ohm and 100nF (0.1uF) are standard for this kind of application.

    0
    AengusR
    AengusR

    Reply 4 weeks ago

    So should the capacitor NOT be connected to the black wire? i.e. just put it on the same line as the resistor.

    1
    techno-womble
    techno-womble

    Reply 4 weeks ago

    Hi, the diagram is correct and the capacitor is connected between the PWM output and GND. The PWM output is a string of digital pulses. If the pulses are high enough frequency they will charge the capacitor and give a rising voltage on the output. If the pulses are of low frequency the capacitor will discharge and the output voltage falls. By varying the pulse frequency (or pulsewidth) a waveform can be generated.

    This Instructable goes into much more details https://www.instructables.com/id/Arduino-RC-Circui...