Beginner project: MIDI, analog pot turned into MIDI CC, MIDI merge with incoming MIDI

Status
Not open for further replies.

Carlos11

Active member
Hello everybody,
I'm new here and an absoute beginner to the programming of the teensy, but quite an expert at soldering etc. I should say that English is not my first language and I do apologize if I do not adopt the right tone sometimes.

I've got a commercial MIDI foot controller that sends program changes. I would like to add an expression pedal that means the teensy should convert 0-5 volts into MIDI CC 0-127 without jitter. Secondly, the teensy should be able merge the generated CC message with the incoming program change messages from the existing MIDI foot controller.

What kind of teensy hardware do I need? It does not seem to be such a big job for the teensy.
I guess the code required may already exist, too.
Could someone point me in the right direction, please?

Kind regards and stay at home programming and soldering ...
Carlos11
 
In theory you would not only need a 5V-tolerant Teensy (3.2, 3.5 are OK), but a Teensy with an ADC working with 0-5V input.
No Teensy can do that straight away.
But no problem, you can arrange a voltage divider to "remap" your 0-5V to 0-3.3V, which any Teensy can read (so you don't even need 5V-tolerance).

For example, using 10K and 18K for R1 and R2 here
http://www.ohmslawcalculator.com/voltage-divider-calculator
gives a nice 3.2v

As for MIDI, it's not clear which kind of MIDI Out interface (from the Teensy) you need. Serial (DIN cable) or USB?

Anyway, Teensy can do both.

A couple links:
https://www.pjrc.com/teensy/td_libs_MIDI.html
https://www.pjrc.com/teensy/td_midi.html
 
Thanks Xfer!
I need a serial (DIN Cable) MIDI out interface. I guess I can do with 0-3.3V at the pot of the expression pedal as long as MIDI CC 0-127 are created.
Does the teensy provide enough output voltage to trigger standard MIDI equipment? Will 3.3V output of the teensy trigger the next MIDI device safely?
What kind of teensy would you recommend for this job?
 
What else does the Teensy connect to and what kind of connection? (DIN/USB?)

Is the foot-switcher DIN only?

Any Teensy will do unless you need to be a USB host. But if you want to connect a DIN MIDI source and output either DIN or USB any current Teensy will do the job as the processing requirements are limited.

Getting a good MIDI signal off an expression pedal means smoothing the raw data from the voltage divider. The library ResponsiveAnalogRead() can extract a usable signal from even a noisy pot on a long, poor-quality cable.

What are you using for an expression pedal (and be advised they are not all wired the same)?
 
BTW - Both the voltage divider that is the expression pedal and the MIDI DIN can be driven with 3.3 v or 5 v and if you are really keen on 5 volt inputs or you did need it for some reason the Teensy 2.0 makes a very good MIDI controller. The LC is cheaper and faster but either is sufficient for a project like this with modest processing needs.
 
Thanks, oddson!
I guess I'll go for the teensy 2.0 then.
The foot switcher is DIN MIDI only. I'm using a Roland EV-5 expression pedal.
Thank your for the advice on the library. ResponsiveAnalogRead().
Do you know a MIDI merge routine or does the teensy merge incoming MIDI data (program changes) with the generated MIDI CC message automatically?
I would like to insert the teensy at the output of the footswitcher.
 
Last edited:
Merge used to be very difficult if you wanted to merge DIN with USB but with the 'new' USB MIDI library I believe it's very simple (but I've not bothered to try it).

I'd be happy to help with that when you get to that stage.

There might be an "easier still" method but for MIDI other than sysex you can just .read() each message for type, channel and D1 and D2 values and send them using the generic '.send()' in either the USB or regular MIDI libraries. (You still have not said whether you are connecting the Teensy to a USB host or via DIN.)

It's essentially read incoming Rx line and send along with whatever MIDI (if any) you have waiting to go.

The MIDI circuits for DIN (along with the library referenece) are here: https://www.pjrc.com/teensy/td_libs_MIDI.html

The USB MIDI page is here: https://www.pjrc.com/teensy/td_midi.html

FYI - The LC should work well. I've never tested whether the higher voltage of the T2.0 is any advantage with the long pedal cable of an expression pedal but I've used both 2.0 and 3.0 (which is very similar to the LC) successfully.

Either 3.3 or 5 volts can be used with the DIN MIDI but the resistors are much smaller valued with the lower voltage.
 
Thanks, oddson!
I've ordered a teensy 2.0 locally and not in China, so it's going to arrive here pretty son.
I am going to connect the teensy to a DIN output jack.
The original foot controller only generates program changes, no sysex. In real life you don't change MIDI patches and use an expression pedal to change MIDI CC simultaneously (at least I can't while standing on my other leg), so it's going to be very basic MIDI merge. Thanks for the links!
 
Simple. Thru is enabled by default when the Midi library is instantiated. All incoming Din Midi messages are passed to Din Midi out so you just have to add code to send what you need.
 
Thanks for that info. I think i knew that once but I don't really use UART MIDI much and never two ports.
 
Thanks, MatrixRat.
I'll try setting up the teensy for MIDI thru first, as soon as the teensy has been delivered.
Then I'll come back here when I 'm about to include the library ResponsiveAnalogRead().
Thanks to oddson as well.
 
I got the teensy today. the onboard LED blinks, turns off when I press the button. Teensy Loader 1.48 recognizes the device.
Downloaded latest version of WINAVR. I'm running it on Windows 10 64bit laptop. Tried to compile blinky, but failed:
screenshot.jpg
 
Thanks MatriXRat!
How stupid of me using C!
By now I have installed the Arduino software and the teensy loader and everything works as it should. I can edit the blinking time of the LED, compile and upload the code. The LED blinking rate changes accordingly. Obviously, I am able to edit, compile and upload code to the teensy 2.0 and make it work correctly!

I guess I will have to include the MIDI library into my new sketch now like this:


#include <MIDI.h>

/*
Blink
Turns on an LED on for one second, then off for one second, repeatedly.

This example code is in the public domain.
*/

// Pin 13 has an LED connected on most Arduino boards.
// Pin 11 has the LED on Teensy 2.0
// Pin 6 has the LED on Teensy++ 2.0
// Pin 13 has the LED on Teensy 3.0
// give it a name:
int led = 11;

// the setup routine runs once when you press reset:
void setup() {
// initialize the digital pin as an output.
pinMode(led, OUTPUT);
}

// the loop routine runs over and over again forever:
void loop() {
digitalWrite(led, HIGH); // turn the LED on (HIGH is the voltage level)
delay(100); // wait for a second
digitalWrite(led, LOW); // turn the LED off by making the voltage LOW
delay(100); // wait for a second
}​
 
If I delete the blink code now, I can copy & paste exisiting code that reads 0-5V at the analog input F0/21 A0 next to the VCC pin and turns it into CC16 (0-127) MIDI commands without jitter. The expression pedal is a Roland EV-5 with a 50k linear pot.
Which code should I use? I only need to setup the number of CC (16) and the MIDI channel (1) once.
 
In File>Examples>Teensy>USB_MIDI you will find AnalogControlChange and Many_Buttons_Knobs.

Ok, It's for USB Midi and both examples have more than one pot but are good to play with.

Many_Buttons_Knobs. does a better job of cleaning up jittery readings and is easy to turn off what you don't need.
It's a good place to start and when you have your pot hooked up and the sketch uploaded and working you will be able to monitor it's Midi output with MidiOx.

From there it's pretty easy to change the code to use Din Midi. Ya gotta play with it and explore and if you don't have Midiox I suggest you download and install it.

Have fun with it.
 
Alternatively, you could use the Control Surface library, it'll filter the analog input for you, and it supports MIDI routing as well.

For example:
Code:
#include <Control_Surface.h> // Include the Control Surface library

// Instantiate the MIDI interface to use.
HardwareSerialMIDI_Interface midi = Serial1;
// A pipe for connecting MIDI interfaces.
MIDI_Pipe pipe;
 
// Instantiate a CCPotentiometer object
CCPotentiometer potentiometer = {
  A0,              // Analog pin connected to potentiometer
  {16, CHANNEL_1}, // CC controller number and MIDI channel
};
 
void setup() {
  Control_Surface.begin(); // Initialize Control Surface
  midi >> pipe >> midi;    // Loop all MIDI input back to the same interface.
}
 
void loop() {
  Control_Surface.loop(); // Update the Control Surface
}

Be sure to download the latest master version.

You can check out these examples for more information:
» Control-Change-Potentiometer.ino
» MIDI_Pipes-Routing.ino

Pieter
 
Thanks, Pieter!
@MatrixRat: I connected VCC, GND and A0 to the expression pedal, opened the "Many_button_knobs" example and changed the code here:

// define the pins you want to use and the CC ID numbers on which to send them..
const int ANALOG_PINS[A_PINS] = {A0};
const int CCID[A_PINS] = {16};

compiled and uploaded the code and I can see the values 00 to 7F (0-127) on MIDI CC16 (hex 10) in the input monitor of MIDI-Ox! If I don't touch the pedal, no new input in MIDI-Ox. No jitter! :)

Now:
How do I deactivate the other analog and digital inputs that I don't need.
How I do change the code from USB_MIDI to DIN_MIDI?

Thanks for your generous help, MatrixRat and Pieter!
 
Last edited:
Code:
#include <ResponsiveAnalogRead.h>

const int channel = 1; // MIDI channel
const int ANALOG_PIN = A0;
const int CCID = 15;


byte data;
byte dataLag; // when lag and new are not the same then update MIDI CC value


// initialize the ReponsiveAnalogRead object
ResponsiveAnalogRead analog(ANALOG_PIN, true);

void setup(){};

void loop() {
  analog.update(); 
  if(analog.hasChanged()) {
    data = analog.getValue()>>3;
    if (data != dataLag){
      dataLag = data;
      usbMIDI.sendControlChange(CCID, data, channel);
    }
  }
  while (usbMIDI.read()) {
     // controllers must call .read() to keep the queue clear even if they are not responding to MIDI
  }
}
This should be the analog only, one pot only version of many-knobs... It should convert to DIN MIDI fairly easily but you need to create an instance of a MIDI object

#include <MIDI.h>
MIDI_CREATE_INSTANCE(HardwareSerial, Serial1, MIDI);


Then MIDI replaces usbMIDI.
 
Last edited:
You also need to add in void setup()

MIDI.begin(MIDI_CHANNEL_OMNI);

Which wakes up the library so that Din IN is passed thru to Din OUT.
 
Thanks to everbody!
Where exactly do I have to insert

MIDI.begin(MIDI_CHANNEL_OMNI);​

in oddson's code (post#21)?
 
Sorry, I've got some computer - IDE problem and simply cannot get Oddson's sketch to work.

I'm definitely not blaming Oddson as I've had the same computer issue several times recently on my desktop (Win 7 and 10) and now my darn W7 laptop is doing it.

First, I gotta make sure all my work is backed up.
 
...I didn't test so there may be a problem with my code but it did compile and it pretty simple so if there's an error one of us should be able to spot it.

edit- tested on a T2 and it the usb version should work.

For DIN MIDI it should be this but I don't have a test rig available right now:
Code:
#include <ResponsiveAnalogRead.h>
[COLOR="#FF0000"]#include <MIDI.h>

MIDI_CREATE_INSTANCE(HardwareSerial, Serial1, MIDI);[/COLOR]

const int channel = 1; // MIDI channel
const int ANALOG_PIN = A0;
const int CCID = 15;


byte data;
byte dataLag; // when lag and new are not the same then update MIDI CC value


// initialize the ReponsiveAnalogRead object
ResponsiveAnalogRead analog(ANALOG_PIN, true);

void setup(){
[COLOR="#FF0000"]  MIDI.begin(MIDI_CHANNEL_OMNI);[/COLOR]
}

void loop() {
  analog.update(); 
  if(analog.hasChanged()) {
    data = analog.getValue()>>3;
    if (data != dataLag){
      dataLag = data;
      // usbMIDI.sendControlChange(CCID, data, channel);
      MIDI.sendControlChange(CCID, data, channel);
    }
  }
  while (usbMIDI.read()) {
     // controllers must call .read() to keep the queue clear even if they are not responding to MIDI
  }
}
 
Last edited:
Status
Not open for further replies.
Back
Top