Wind Controller Touch (Mk IV)

This is my fourth wind controller design, and it has the same 3D printed body, mouthpiece, and mounting parts as my previous Wind Controller BLE.  You can get the stl files from Thingiverse. Like the previous wind controller, it features capacitive touch sensors for the main keys but this one uses a hard-wired MIDI interface so you can connect to any synthesizer that has a standard 5-pin hardware MIDI port. In fact, inspiration for this design came from several people who built the BLE version and/or wanted something to connect to an old fashioned hardware MIDI port to control a hardware synthesizer or DAW.  This version also uses a more conventional (but also very inexpensive) breath pressure sensor than the original BLE version. I also simplified things a bit by eliminating the gyro module used for pitch bend as well as the battery included in the previous version.  The Arduino Mini Mega 2560 used in this version is also somewhat easier to find than the previous processor used.

Note that this wind controller doesn’t make any sound in itself – it sends out MIDI messages via standard MIDI cable to any synthesizer that has a 5-pin MIDI-in port.

Here is a parts list for the project (Amazon links may earn me a small commission):

(*) If you don’t like the idea of using a 3D printed mouthpiece (a mouthpiece STL file is included in the files), note that the wind controller neck is designed to fit a standard alto saxophone mouthpiece and reed instead of the printed one if you wish. The mouthpiece makes no sound itself so any alto mouthpiece should work.  That said, I use the 3D printed mouthpiece all the time and I’m just sure to remove it and wash it and let everything dry after every use.  So far so good!

Files for the 3D printed parts are available on Thingiverse.

Operating Features Overview

Fingering on this wind controller is very similar to the saxophone, with a few minor tweaks. The main front touch pad keys are B to D, and the left pinky has a G# and a low C# hard key (LP1 and LP2). There right pinky has an Eb and low C hard key (RP1 and RP2). The right side hard keys (RS1 and RS2) are a bit different than normal saxophone fingerings – these two keys allow any fingered note to be shifted up by either a 1/2 step or a whole step.

On the bottom side there are three octave touch keys – the top ones shift everything up by either 2 octaves or 1 octave, and the bottom one shifts everything down by 1 octave. When your left thumb is on the raised bump and not touching any of the octave keys, no octave shift occurs.

On the bottom there are also three buttons used to navigate through the display menus and select options. There is an increment (INC) key, a decrement (DEC) key, and a combined mode/select/enter key (MODE).

Below the right hand thumb hook is a force sensitive resistor (FSR) that detects how hard you are pressing and causes the software to send out a MIDI continuous controller (CC) message that’s assigned to the thumb control function.

There are two connections/ports at the bottom of the wind controller – one is a standard 5-pin DIN MIDI out connector, and the other is a micro-USB to power the wind controller. The micro-USB hole actually accessed the connector on the Arduino Mini Mega 2560, and this is the same connector used to program the software. After programming the Arduino, the wind controller can just be plugged into a USB power bank or AC adapter to supply 5 volts to power it through this port.

The small 128×64 pixel OLED LCD is used to display the various screens with menu, status, and selection options for the wind controller.

Displays and Menu Structure

Startup screen
The startup screen briefly displays on initial power up while the wind controller’s software is starting up. As noted in the picture above, the installed software version is displayed on this screen.  During the time this screen is displayed, variables and functions are initialized, the touch sensors are initialized, and the breath pressure sensor is read several times to establish a ‘not-blowing’ baseline for the breath control sensor. It’s important to not blow into the wind controller for the first couple seconds after the power switch is turned on, and also try not to touch any of the copper touch pads during this time while the touch sensor calibrates.

Program Select
When this screen is displayed, the MIDI program change command is sent every time the INC or DEC buttons are pressed. If the INC or DEC buttons are held, program changes are rapidly changed in the desired direction.

Pressing the MODE switch cycles forward to the next setting screen. If one of the control switches – MODE, INC, or DEC – are not pressed again within 10 seconds, the display will revert back to first page (PROGRAM SELECT).

Octave Select
In this screen the wind controller’s default octave can be adjusted.

Tuning Select
In this screen the wind controller’s default tuning can be adjusted. For example, to play in an alto saxophone tuning, select “+3 (Eb)” or to play in a trumpet, clarinet, or tenor saxophone tuning, select “-2 (Bb)”.

MIDI Channel
In this screen the wind controller’s default MIDI channel can be changed.

Breath Assign and Thumb Assign
The breath and thumb controllers can output a MIDI continuous controller (CC) message for one of many device types selectable here.

The filter resonance (CC71) can be ‘full range’ or constrained to one-third of the MIDI CC range over the full breath or thumb pressure ranges. The latter is useful if the MIDI synth being controlled has a very sensitive resonance response.

The filter cutoff (CC74) can be ‘normal’ where increasing breath or thumb pressure result in higher values, or ‘reverse’ where increasing breath or thumb pressure result in smaller values.

For most standard MIDI synths, breath control is routed to CC11 (Expression), and thumb control is routed to CC1 (Modulation).  The code written so these settings come up at startup – if your setup uses a different controller, this default can be easily changed in the setup() routine in the code.

Reset Sensors
This page is accessed by a long press (greater than 1 second) of the MODE switch. Here the breath and touch sensors can be reset by pressing INC or DEC.

Hardware

Most of the 3D printed parts for this wind controller are the same or very similar to the ones for my previous Wind Controller BLE. The main changes to this version are the elimination of the power switch, revised mountings for the internal electronics, revised mounting for the breath sensor, and changed bottom plug for the MIDI socket and USB access to the Arduino.  The mechanical parts are all 3D printed in PLA using my CR-10S printer. This printer has a 300mm x 300mm print bed, and the three large parts (Body Top, Body Bottom, and Body Bottom Skin) were individually printed at a 45 degree angle on the print bed. Note that these parts will not fit on a printer with a print bed smaller than about 250mm x 250mm.

Files for the 3D printed parts are available on Thingiverse.

Gold PLA was used for all parts of this version.  All of the parts are printed at 0.2mm layer height with 20 or 30% infill. Most of the parts can also be printed without support material – the only parts that I printed with support turned on were the Breath Chamber Lower, Breath Chamber Upper, and Neck. For strength, the Neck is printed sideways (as oriented in the STL file).  Note that the bottom skin part has three small alignment indents along its center line. Short pieces of filament are glued into the holes in the skin, and then these ‘pins’ are used to align the skin to the body bottom when it is glued on. After the glue is dry, the excess pins are trimmed off on the inside.

The breath chamber and the main assembly screw in the bottom plug piece of the wind controller use M3 screws into M3 brass inserts. A good way to assemble these is to put the inserts on a long M3 screw and heat the insert using a small butane torch for about 5 seconds. Then carefully press the hot insert into the plastic parts so they melt themselves in place. An insert ‘practice piece’ is included in the 3D printer files to use several times to be sure to get the hang of heating and inserting these just right before committing doing it to the real parts. The larger holes in the insert practice piece is for the PC4-M10 connector which screws into the bottom of the breath chamber – it helps it to screw this in easier if it’s heated first as well.

This controller uses an HX710 pressure sensor module.  This module has recently come onto the marketplace on Amazon and elsewhere, and is very inexpensive compared to the sensors used in my Mk I and Mk II wind controllers. The HX710 name actually refers to the 24 bit Analog-to-Digital converter IC used in the module – the pressure sensor itself is a Wheatstone bridge type of differential pressure sensor with a range of approximately 0 to 5.8 PSI.  Despite the “OUT” and “SCK” labeling, this module is not I2C or SPI controlled – it actually uses an unusual serial data protocol.  Data is read from the module by sending clock pulses to the SCK input and reading the resultant bits from the OUT pin.  A full sample read requires 24 clock pulses and gets 24 bits from the output.  The HX710 is capable of sampling the pressure sensor at either 10Hz or 40Hz and provide corresponding data outputs depending on how many clock pulses are sent following the data read described above.    This website does a great job explaining the operation of this module, and my code in the 05_sensor.ino file contained in the software zip download (link below) is based on the code examples from that site.  Here’s another good reference website that gives additional information.

The pressure sensor mounts into a small round adapter and this assembly fits into the breath chamber assembly which is held together with four 18mm long M3 screws. The neck piece fits into the breath chamber, and there is a ‘key’ in the design to ensure it’s aligned. A little sanding may be needed on the inside of the neck hole in the breath chamber to make it fit nicely. The neck is glued to the bottom of the breath chamber only (where the key is) – this way the top and middle pieces can still be removed if necessary for access. The breath chamber sandwich (lower, middle, and upper) has gaps which the tabs on the body top fit into. The gaps and/or the tabs might need to be sanded slightly so the body top slides in easily. Then the lower breath chamber is glued to the body bottom and the bottom plug is glued to the body top. This way, the single M3x8mm screw at the bottom of the wind controller can be removed and the body top slid down to disengage the tabs so the unit can be opened.

The air and any moisture that collects from your breath exits the breath chamber through a PTFE tube that runs down to the bottom of the wind controller. The PTFE tube is a leftover piece of standard 3D printer bowden tube, and it’s connected to the bottom of the breath chamber using a PC4-M10 connector, also a spare from my 3D printer.

The key touch sensors are copper foil tape applied to the 3D printed bottom and top switch mount parts before they are mounted to the body. This tape comes with a paper backing, so it’s fairly easy to pre-cut the necessary sizes. A gap is left where the ridge is on the switch mounts to provide isolation between the B and bis keys on the top and between the +2 and +1 octave keys on the bottom. Soldering the wires to the back of the copper foil touch pads to connect them to the MPR121 capacitive touch sensor board was very easy and did not melt the plastic parts due to the way the soldering heat was dissipated in the foil.  Note: the pictures shown above show the mounts in black PLA for clarity, the actual ones used in this unit are gold in color.

The right and left switch mounts and the bottom switch mount have recesses for standard 12mm tact switches with posts for caps (the caps are attached from the outside after everything is assembled). The legs of these switches fit neatly into the holes in the mounts, and there’s a taper on the bottom to provide a little clearance for soldering the wires after the parts are assembled. The right switch mount parts 2A and 2B are glued together before attaching them. The switch mounts are all attached to the body with 1/4″ long #2 round head screws.  Note: the pictures shown above show the mounts in black PLA for clarity, the actual ones used in this unit are gold in color.

A piece of 2mm thick cork sheeting (sold for saxophone neck cork replacement) is used on the neck. There are many resources that show how to cork a saxophone neck on the web, but basically the first thing to do is sand one edge of the piece of cork down to a bevel as shown. Then put contact cement on the bevel, the bottom of the cork, and the neck itself and allow the glue to dry. After the contact cement is dry to the touch, the cork is wrapped tightly around the neck and trimmed with a razor blade. Finally, the cork is sanded and greased until it fits into the mouthpiece. The cork sheeting typically comes in packs of 10 pieces so you can try again if it doesn’t work out well the first time. I have done this several times and I get better at it with each one I do.  If you prefer, wrapping the neck part with electrical tape to build up a nice fit into the mouthpiece instead of using cork would probably work too.  Note: the pictures shown above show the neck in black PLA for clarity, the actual one used in this unit is gold in color.

The new bottom plug end cap has a rectangular hole that allows access to the micro USB connector on the Arduino Mini Mega board.  It also has a hole to fit a standard MIDI jack.  In order to avoid a short-circuit between the pins on the back of the MIDI connector and the Arduino board, the connector pins were ground down before mounting into the hole using M3 screws.  The screws fit into M3 brass inserts which are heat-set into the bottom plug.  In the last picture above you can see the clearance between the MIDI jack and the Arduino when everything is in place.

The 128X64 OLED LCD display used in the wind controller has a glass size of 25 x 17mm and this fits perfectly in the hole in the body. If you build this and use a different display, you may need to slightly sand or carve the opening in the lower body to fit the display. The glass is very fragile on these tiny displays, so it needs to fit into the opening without force. The bottom switch mount and the bottom skin hold the display in place, sandwiched between these parts with the lower body in between. No screws are put through the holes of the display board itself.

The MPR121 Touch Sensor is mounted in its own dedicated area and is held in place with two screws at the bottom.

The Level Converter Module just floats freely inside the body. It’s small and lightweight enough that I didn’t think a hard mounting was required.

The Arduino Mini Mega is screwed in place with its micro USB connector accessible through the bottom plug hole when everything is assembled.  Note that the three resistors used in this project are just soldered in place on the Arduino with heat shrink tubing to insulate the wire connections to the other components.

The thumb FSR-402 fits in the opening in the bottom skin below the thumb hook, and the tail is curved over on the inside so that its pins face the mouthpiece and it is held in place with the FSR support piece.

Once all the parts are mounted, separated ribbon cable was used to make the wiring connections shown on the electrical schematic. Click on the picture above for a larger view – it’s a surprisingly simple schematic and can be wired up point-to-point pretty easily if you take your time.  Use several zip ties to keep things neat and tidy.

Software

Wind Controller Touch Software (link downloads a zip file)

The wind controller operating software is broken up into several “.h” and “.ino” files, contained in the zip file linked above. After the files are unzipped to a folder on your PC, double-click on the Wind_Controller_Touch_V1_0.ino file and all the others will open up in tabs in the Arduino IDE. This main file has the usual loop() main program which has sections that execute at 10 Hz for the display routine, 40 Hz for reading the breath pressure sensor, and at 100 Hz for everything else.

The 40 Hz section has only one function:
1 – Read the breath pressure sensor

The 100 Hz section has these main parts:
2 – Switch read and pitch computation
3 – Note on/off message computation
4 – Breath controller message computation
5 – Thumb controller message computation
6 – Handle mode changes

The 10 Hz section has only one part:
7 – Display control

1 – Breath pressure input analog read
The breath pressure sensor is read and adjusted to provide a minimum value dead band and scaled to a value to be used with the rest of the software.  The HX710 pressure sensor module uses a unique serial read interface to get 24 bits of data from the sensor.  The read_pressure() routine in the code takes care of reading the 24 bits of data and then toggling the clock line to the sensor three more times to initiate another sensor read that will be ready in 25 milliseconds, for a sensor read rate of 40 Hz overall.  If this routine is called too quickly, the data line will indicate not ready until the 25 milliseconds are elapsed and the rest of the processing will be blocked while the routine waits.  The main loop() routine therefore has a millis() comparison check  to ensure the read_pressure() routine is called no more frequently than needed.

2 – Switch read and pitch computation
The switch read and pitch computation section first reads the state of the touch sensors from the MPR121 Touch Sensor board and uses this data to lookup a base pitch value from the FINGERING_ARRAY_1 table. The pinky hard switches (left pinky 1&2 and right pinky 1&2) states are used to index into the FINGERING_ARRAY_2 table to determine an adjustment to the base pitch value. Finally, the octave touch switch states are used to index into the FINGERING_ARRAY_3 table to determine an octave adjustment.

3 – Note on/off message computation
Once the pitch computation and breath input are computed, it’s time to play a note. There are three parts to the note on/off computation section. First, if no note is playing and a new note is started, a MIDI note-on message is sent using the pitch and velocity computed earlier. The breath average array is reinitialized when a new ‘tongued’ note is detected (i.e. if a note wasn’t already playing). Second, if a note is already playing but the pitch changes, that means the old note should simply be stopped (MIDI note-off) and the new note started (MIDI note-on) while keeping the breath control message unchanged. Third, if the breath input is stopped, a MIDI note-off message is sent.

4 – Breath controller message computation
The breath controller message is computed by keeping a 20 element rolling average of the breath pressure analog. This averaging gives a filtered response for the control message sent for this controller. This controller uses a 20 element rolling average instead of the 50 element rolling average used in the Wind Controller BLE unit because of the sensor read rate of 40 Hz vs the 100Hz.  The control messages can be one of several MIDI controllers (more on this later).

5 – Thumb controller message computation
The thumb controller message computation is similar to the breath controller logic – first the analog is read and adjusted to the MIDI range. Then the value is averaged using a 50 element rolling average. Finally, the control message is sent on the selected MIDI control message (more later).

6 – Handle mode changes
Mode changes allow the user to adjust several aspects of the behavior of the wind controller:

  • program changes
  • octave changes
  • tuning changes
  • MIDI channel changes
  • breath pressure MIDI controller assignment
  • thumb pressure MIDI controller assignment
  • reset the breath and touch sensors

7 – Display control
The display control routine handles all the aspects of the display of information on the SSD1306 OLED display (see above).   The display is only updated when something on it has changed (display_changed == true) in order to keep the MIDI processing as fast as possible.

Conclusion

This was a fun project and hopefully there’s enough information here if you want to build one for yourself.  If you do build one, let me know how it works out!

Comments are closed.