Xeramin - an Instrument That Is Shaken and Stirred-
Introduction: Xeramin - an Instrument That Is Shaken and Stirred-
Back in the year of 2014, while I was trying to fix my Theramin, I could not help but complain: “Gee! These discrete components are so expansive. Under the same budget, I can build a dozen Theramins with microcontroller and sensors.”
My idea was straight-forward: replacing the 2 antennas of a Theramin (one for tone and the other for volume) with equivalent sensors. That is, to…
* Use a range detector, to detect the distance, and then translate to a tone.
* Use another sensor to detect the gesture, to decide the volume.
So, I set off to build a Theramin with microcontroller and sensors. But soon, I realized that I can build something different – an inversed Theramin. Such instrument would be portable and able to be played single-handed. I named it Xeramin; because I use an accelerometer for the volume part.
An ultrasound ping sensor detects the distance from floor; while an accelerometer captures the g force when the device is shaken. These readings are processed by a microcontroller. And finally, a PWN tone was generated, filtered, and fed to a class-D amplifier. The final product is emitted by a speaker that is glued to a plastic bottle cap.
These parts can be found in all sorts of “Arduino Starter Kit”. It was painless for me to create the prototype. However, after several attempts to make it sound better, I came to a conclusion: I should convert it to a MIDI instrument and hook it to a synthesizer. Then I left the project there for years.
Recently, I came across Arduino Nano 33 BLE, an Arduino with built-in BLE and IMU funcionality. 1003
I thought: “This is it! I can definitely upgrade my Xeramin with it.”
I am going to show you how to build a Xeramin with the latest Arduino parts. It is very easy and requires no pro tools at all. Here we go!
Step 1: Prepare the Parts
You will need...
* A half-size breadboard
* Arduino Nano 33 BLE with headers
* VL53L0x breakout board
* Grove-Mech keycap
* A portable power source (9v battery x1 or 18650 battery x 2)
* A computer to host MIDI synthesizer (we will use Raspberry Pi in this Instructable)
The VL53L0x is a ToF laser range detector. We will hook it to Arduino via I2C. Any brand of breakout board will do.
The Grove-Mech keycap is a mechanical button with LED. It will function both as a visual cue and as a “shut-up” button. If you can't get one, you can replace it with an ordinary push button and an Adafruit NeoPixel RGB LED.
And for the power source… I did not hesitate to use a 9V battery. Given the low current and good efficiency of the regulator, it should not be too eco-unfriendly. An USB powerbank might refuse to power the device, unless it has "micro-current mode" (mode to charge earbuds at low current).
Step 2: Wire Up Everything
Because the needed wiring are so few, it can be built on a bread board without side effect except for durability issue. The keycap and battery case can be glued to the back of the breadboard, at whatever locations that you find comfortable.
Regarding the position of the chips, I recommend to keep the VL53L0x near the wrist, while the IMU on Arduino board away from the wrist. This makes the reading of distance more stable during waving or shaking.
Step 3: Program the Microcontroller
I know, the code is a bit messy, especially the header part.
Despite the readability issue, there are however, several constant variables that you definitely want to modify:
* BLE device name: char const DEVICE_NAME[] = "Xeramin_R"; This will be the device name you see while connecting it to bluetooth central.Change it to avoid any confusion.
* The MIDI channels that the device will use: byte const ch[] = {1, 2, 3, 10}; You might need to modify this to avoid collision; for example, if you plan to connect more than one device to the synthesizer. The code that I provided only use 3 channels, you can change int const SIZEOF_CH_ARR = 3; to use more or less.
* If you wish to change the scale of notes, you can modify the byte const notes[] array, and int const NOTE_STEP_DIST = 88; , which determines how distance is translated to note. 939