Breath sensor made from an MPXV7002 and a silicon tube. The tube has incisions added near the breathing end to allow air to flow through while still building pressure at the sensor end. Enough pressure is still built up within the tube to allow circular breathing if desired. The sensor sends note on / off and continuous control data.
To improve this I might consider a wider tube that is coupled with the sensor or try more or different-sized puncture holes or a 3D printed mouthpiece. However, it still works really well as-is.
Wiring is simple as the sensor outputs an analog voltage and works fine on 3v3 or 5v power supply. The output voltage is rail to rail across the power supply voltage range, and can represent both positive and negative pressure, meaning that the neutral pressure will output at halfway of the voltage supply.
For a Teensy 3.x or 4.x: 3v3 to the 5V pin on the sensor, ground to ground and output of the sensor to Teensy A0 analog input pin.
The TMP117 is a high precision temperature sensor with I2C output and can measure between -55˚C to 150˚C.
Hardware
The following connections should be made between the Teensy 4.1 and the TMP117:
Teensy 4.1 3V to TMP117 VCC - orange in the above photo
Teensy 4.1 ground to TMP117 GND - black in the above photo
Teensy 4.1 pin 19 / A5 / SCL / PWM to TMP117 SCL - yellow in the above photo
Teensy 4.1 pin 18 / A4 / SDA / PWM to TMP117 SDA - yellow in the above photo
In order to set the correct I2C address for the TMP117 device for this code example, make sure the first bit of the four address bits is set and the rest are cleared.
Software
The Arduino code uses the Wire library to communicate with the TMP117 via the I2C bus. The TMP117-Arduino library by Nils Minor is required and can be installed via the Arduino IDE. If the temperature changes, the new value is sent as a scaled, simple USB MIDI control change message.
#include"TMP117.h"
double temp;
int data;
int data_prev;
constint chan = 1;
constint cc = 1;
TMP117 tmp(0x48);
voidsetup(){
Wire.begin();
Serial.begin(115200);
tmp.init(NULL);
}
voidloop(){
temp = tmp.getTemperature();
data = constrain(map(temp, 0.0, 48.0, 0.0, 127.0), 0.0, 127.0);
Serial.println(temp);
if(data != data_prev){
usbMIDI.sendControlChange(cc, data, chan);
delay(10);
}
}
The temperature can be viewed in Max via this example patch:
The GY-521 board uses an MPU-6050 IC with an accelerometer, gyroscope and thermometer. An I2C bus is used to communicate with the board using the Teensy 4.1.
Hardware
The following connections should be made between the Teensy 4.1 and the GY-521:
Teensy 4.1 3V to GY-521 VCC - orange in the above photo
Teensy 4.1 ground to GY-521 GND - black in the above photo
Teensy 4.1 pin 19 / A5 / SCL / PWM to GY-521 SCL - yellow in the above photo
Teensy 4.1 pin 18 / A4 / SDA / PWM to GY-521 SDA - yellow in the above photo
Software
The Arduino code uses the Wire library to communicate with the GY-521 via the I2C bus. The data from seven registers (accel x, y, z; temperature; gyro x, y, z). If these values change, they are sent as a simple USB MIDI control change message
#include"Wire.h"// This library allows you to communicate with I2C devices.
constint MPU_ADDR = 0x68; // I2C address of the MPU-6050
int16_tvalue[7];
constint chan = 1;
constint cc_offset = 0;
voidsetup(){
Serial.begin(9600);
Wire.begin();
Wire.beginTransmission(MPU_ADDR); // Begins a transmission to the I2C slave (GY-521 board)
Wire.write(0x6B); // PWR_MGMT_1 register
Wire.write(0); // set to zero (wakes up the MPU-6050)
Wire.endTransmission(true);
}
voidloop(){
Wire.beginTransmission(MPU_ADDR);
Wire.write(0x3B); // starting with register 0x3B
Wire.endTransmission(false); // active connection
Wire.requestFrom(MPU_ADDR, 7 * 2, true); // request a total of 7*2=14 registers
for(int i = 0; i < 7; i++){
int16_t data = Wire.read() << 8 | Wire.read();
data = constrain(map(data, -17000, 17000, 0, 127), 0, 127);
MIDI clock messages (see System Real-Time Messages) are used to synchronise software or hardware playback transport using MIDI messages. One device sends the clock messages, and another device receives. The device receiving the messages is synchronised to the device that sends the messages.
MIDI clock messages do not carry song position, location or absolute time. Instead, this is transport information for synchronising.
There are four relevant message types - 'start', 'stop', 'continue' and 'clock'. Start and stop are self explanatory - they represent the transport beginning to play and ending to play. Continue represents a transport that is not at the start of the sequence to carry on from the current position. The clock message is sent 24 times per quarter note (a resolution of 24 ppqn). The clock message interval is, of course, depending on the beats-per-minute and can be calculated as (60 / beats-per-minute) / 24 seconds.
Teensy and the Teensyduino add-on can send and receive MIDI clock messages over USB as a USB-compliant MIDI device.
To receive MIDI clock messages on the Teensy, four functions must be written, that correspond with the following:
void myClock()
void myStart()
void myContinue()
void myStop()
These functions are created by the user, and each function will only be called when that type of message is received by the Teensy.
In setup(), each function must be connected by name to the message type it should respond to.
usbMIDI.setHandleClock(myClock);
usbMIDI.setHandleStart(myStart);
usbMIDI.setHandleContinue(myContinue);
usbMIDI.setHandleStop(myStop);
MIDI clock can be used with Ableton Live to sync the Teensy to the Transport. In Ableton Live, set up the Teensy as a sync output source in the Link MIDI tab in preferences.
When the transport is played in Live, this will then send MIDI clock messages from Live to Teensy.
Here are three examples of sending MIDI clock messages from Live to Teensy.
Turn on LED when transport is playing, turn off when transport is stopped
MIDI clock messages (see System Real-Time Messages) are used to synchronise software or hardware playback transport using MIDI messages. One device sends the clock messages, and another device receives. The device receiving the messages is synchronised to the device that sends the messages.
MIDI clock messages do not carry song position, location or absolute time. Instead, this is transport information for synchronising.
There are four relevant message types - 'start', 'stop', 'continue' and 'clock'. Start and stop are self explanatory - they represent the transport beginning to play and ending to play. Continue represents a transport that is not at the start of the sequence to carry on from the current position. The clock message is sent 24 times per quarter note (a resolution of 24 ppqn). The clock message interval is, of course, depending on the beats-per-minute and can be calculated as (60 / beats-per-minute) / 24 seconds.
Teensy and the Teensyduino add-on can send and receive MIDI clock messages over USB as a USB-compliant MIDI device.
To send MIDI clock messages, four functions are used:
usbMIDI.sendRealTime(usbMIDI.Clock);
usbMIDI.sendRealTime(usbMIDI.Start);
usbMIDI.sendRealTime(usbMIDI.Continue);
usbMIDI.sendRealTime(usbMIDI.Stop);
To use a particular function, simple send it at the required point in time.
MIDI clock can be used with Ableton Live to sync the transport to the Teensy. In Ableton Live, set up the Teensy as a sync input source in the Link MIDI tab in preferences. This will enable an EXT button near the BPM. Click on this to enable external sync to the Teensy.
Here are three examples of sending MIDI clock messages from Teensy to Live.
The button is pressed. The change in state (either high or low) is read by the ESP8266. A note on message is formatted, with MIDI channel 1, note 60 and a velocity that is either 127 or 0 depending on the state of the button. These three bytes are then wrapped up in an OSC message with the name "MIDI", and sent via UDP. One MIDI message is sent per OSC message, and one OSC message is sent per UPD packet.
Overview
The Teensy 3.6 can read the values from up to 25 potentiometers without any additional hardware.
By combining multiple potentiometers, and then reading each one after the other, a basic MIDI sequencer can be constructed. Each pot represents a note (for example, pitch) - but additional pots could also represent velocity and interval.
Many considerations can be made in regards to how one or more pots are read, in which order, what scaling, what each pot represents and so on.
Here are some simple examples exploring different combinations.
Teensy 4.1 Note: You can adapt many of these examples to work with 4 or 5 pots. Also, Teensy 4.1 only appears to be able to have a analogReadResolution of 8, 10 or 12 bits so adjust this code accordingly by multiplying or dividing.
Hardware Setup
Eight pots are connected to analog inputs 0 - 7. The outside legs of the pots are connected to 3.3V and ground.
Example 1 - Basic Sequencing
The eight pots represent eight notes. Each pot sets the pitch value of a note. Each note is played one after the other. The velocity and time interval are static, and set as part of the code.
Example 2 - Sequencing with Step Enable and Time Interval Control
Another pot is added. The first eight pots set the pitch values of notes. Each note is played one after the other. The velocity is static, and set as part of the code. The time interval is set by the ninth pot. If a given pot is all the way at minimum, then that particular step is disabled.
Nine pots control a total of four notes. The first four pots control pitch. The next four pots control velocity. The last controls the time interval for all notes.
Example 4 - Pitch, Velocity and Time Interval Control
Nine pots control a total of three notes. The first three pots control the pitches. The next three pots control the velocities. The last three pots control the time intervals.
Nine pots in total. The first four pots control pitch. The last five pots control time interval. These two parameters combine to form notes. The pitch and time interval are out of phase with one another, thereby forming a pattern of twenty notes that repeat by combining the possibilities of pitch / time interval pairs.
The Teensy 3.6 can be used to create a simple MIDI sequencer. Many pots can be read in different ways and orders, and mapped to note parameters in different ways - making lots of different possibilities.
Overview
A rotary encoder, although looking similar to a potentiometer, is actually a pair of mechanical connections that are closed and then opened in a particular order and timing depending on the direction and speed that the connecting shaft is rotated.
Furthermore, an encoder (unlike a potentiometer) does not have a maximum and minimum excursion, making it ideal for contextual values, delta data points, and parameters that need accurate adjustment beyond a finite number of turns.
As a result, the output of an encoder can be read and interpreted to give direction (left or right) as well as some sense of speed of turning, in combination with limitless rotations.
The Teensy has a great library for using the encoder, which is part of the Teensyduino installation. More information about the library and its use can be found here: https://www.pjrc.com/teensy/td_libs_Encoder.html.
An encoder can make for a useful MIDI control.
Hardware Setup
To begin with a single encoder is connected to digital pins 25 and 26. The middle leg of the encoder is connected to ground.
Example 1 - Reading the Value of One Encoder
In this example, an encoder object is created, using digital pins 25 and 26. The value of the encoder is read and compared to the previous reading. If the value of the reading has changed compared to the previous reading, then the value is sent to the Serial Monitor.
No constraints are set on reading the value of the encoder, and so there is no limit on the reading when turning the encoder left or right.
Example 2 - Reading the Value of One Encoder, and Send as MIDI Continuous Control Message
In this example, an encoder object is created, using digital pins 25 and 26. The value of the encoder is read and compared to the previous reading. If the value of the reading has changed compared to the previous reading, then the value is sent as a MIDI continuous control message
The value is constrained to the range 0 - 127, so turning the encoder beyond 127 or below 0 will have no effect.
Example 3 - Reading the Value of Two Encoders, and Send as MIDI Continuous Control Messages
In this example, two encoder object are created, using digital pins 25 - 28. The value of the encoders are read and compared to previous readings. If the value of a reading has changed compared to the previous reading, then the value is sent as a MIDI continuous control message. Each encoder has a separate controller number.
The values are constrained to the range 0 - 127, so turning the encoders beyond 127 or below 0 will have no effect.
Example 4 - Four Encoders Plus One Button as Bank of Switchable MIDI Controllers
In this example, four encoders are used alongside a button. The button switches between four different banks. Each bank is represented by the four physical encoders. Each bank has unique, four MIDI controller numbers, thereby having a total of sixteen MIDI controllers.
Summary
Encoders can be used in addition to buttons and switches for controlling parameters. The limitless rotation can be used in different contexts than a standard potentiometer.
Overview
The Teensy can send many types of MIDI data of USB, including pitchbends. MIDI pitchbend data has a resolution of 14 bits, which covers the range of 0 - 16383. This is far higher than continuous controller data, which has a range of 0 - 127 with 7 bits.
As such, the pitchbend messages are useful when requiring a higher degree of control.
Teensy 4.1 Note: You may need to set analogReadResolution() to 12 bits and then multiply the analogRead() value by 4 in order for this code to work correctly.
Hardware Setup
In this example, a potentiometer is connected to analog input 0. A push button is connected to digital pin 32.
Example 1 - Sending Pitchbend Data
In this example, the pitchbend value is sent based on the potentiometer and the push button sends note on / note off messages.
Note the use of analogReadResolution to set the range to 14 bits (0 - 16383), and analogReadAveraging to smooth out the data values by averaging 32 samples.
The pitchbend function, usbMIDI.sendPitchBend() takes the argument of value and channel, where value is an int in the range of 0 - 16383.
The Teensy can send MIDI data over USB. This include sending MIDI note on and note off events. Built-in functions make sending MIDI data simple. A summary of Teensy MIDI message types that can be sent over USB can be found here.
Teensy 4.1 Note: You may need to set analogReadResolution() to 8 bits and then divide the analogRead() value by 2 in order for this code to work correctly.
Hardware Setup
A potentiometer is connected to 3.3V, ground and analog input 0.
Software Setup
The analogRead() function is used to measure a voltage at an analog input. The analogReadResolution() function is used to set the range of the reading value to 0 - 127. The usbMIDI.sendControlChange() function is used to send a MIDI continuous control message via USB.
The order of arguments for the usbMIDI.sendControlChange() are control number, control value, MIDI channel.
The DAW that receives the controller data must be set up to see the Teensy as a control input.
Example 1 - Sending the Value of One Potentiometer as a Continuous Control Message
In this example, the aim is to read the value of a potentiometer and, if the value has changed compared to the previous reading, send the new value as a MIDI control message.
Example 2 - Sending the Value of Two Potentiometers as Continuous Control Messages
In this example, the aim is to read the value of two potentiometers and, if a value has changed compared to the previous reading, send the new value as a MIDI control message. The two potentiometers are completely separate.