Expression pedal

Status
Not open for further replies.

Explodey

Member
Hi folks! A few years ago this forum was very helpful with the guitar-mounted midi controller that I built (here's a video if you'd like to check it out), and it recently occurred to me that I could significantly simplify my setup if I just added a extra TRS jack to my project box and connected my expression pedal to that. Then I would only need to connect my little Teensy-LC box to my laptop and use it for both my guitar mounted midi controller and my expression pedal, and then I wouldn't need to worry about replacing the batteries in my iRig Blueboard all the time.

So it's been a while, but if memory serves, I just need to wire a TRS jack to the pins on the other side of the Teensy board -- the side with the paired pins. I'm a little less clear on the what to add to my existing code. So this is all my long-winded way of asking what's the code for an expression pedal? Sorry for such a newbie question; I did look around for an answer on the website, and I gathered that I'll need the analogRead() function, but other than that I'm really not sure. Here's my code so far. As you can see, it's just a simple twelve button (six rocker) setup, and all I want to do is add one knob. Thanks!

Code:
#include <Bounce.h>  // Bounce library makes button change detection easy

const int channel = 0; 
const int CC5 = 16 ;
const int CC6 = 17 ;
const int CC7 = 18 ;
const int CC8 = 19 ;
const int CC9 = 20 ;
const int CC10 = 21 ;
const int CC11 = 22 ;
const int CC12 = 23 ;

Bounce button1 = Bounce(1, 5);  // 5 = 5 ms debounce time
Bounce button2 = Bounce(2, 5);  // which is appropriate for good quality mechanical pushbuttons
Bounce button3 = Bounce(3, 5);  
Bounce button4 = Bounce(4, 5);
Bounce button5 = Bounce(5, 5);  
Bounce button6 = Bounce(6, 5);
Bounce button7 = Bounce(7, 5);  
Bounce button8 = Bounce(8, 5);
Bounce button9 = Bounce(9, 5);  
Bounce button10 = Bounce(10, 5);
Bounce button11 = Bounce(11, 5);  
Bounce button12 = Bounce(12, 5);

void setup() {
  pinMode(1, INPUT_PULLUP);
  pinMode(2, INPUT_PULLUP);
  pinMode(3, INPUT_PULLUP);
  pinMode(4, INPUT_PULLUP);
  pinMode(5, INPUT_PULLUP);
  pinMode(6, INPUT_PULLUP);
  pinMode(7, INPUT_PULLUP);
  pinMode(8, INPUT_PULLUP);
  pinMode(9, INPUT_PULLUP);
  pinMode(10, INPUT_PULLUP);
  pinMode(11, INPUT_PULLUP);
  pinMode(12, INPUT_PULLUP);
}

void loop() {
  button1.update();
  button2.update();
  button3.update();
  button4.update();
  button5.update();
  button6.update();
  button7.update();
  button8.update();
  button9.update();
  button10.update();
  button11.update();
  button12.update();
  
// CC messages when each button is pressed
  if (button1.fallingEdge()) {
    usbMIDI.sendNoteOn(60, 99, channel);  // 60 = C4
  }
  if (button2.fallingEdge()) {
    usbMIDI.sendNoteOn(61, 99, channel);  // 61 = C#4
  }
  if (button3.fallingEdge()) {
    usbMIDI.sendNoteOn(62, 99, channel);  // 62 = D4
  }
  if (button4.fallingEdge()) {
    usbMIDI.sendNoteOn(63, 99, channel);  // 63 = Eb4
  }
  
  if (button5.fallingEdge()) {
  usbMIDI.sendControlChange(CC5, 127, channel);
  }
  if (button6.fallingEdge()) {
  usbMIDI.sendControlChange(CC6, 127, channel);
  }
  if (button7.fallingEdge()) {
  usbMIDI.sendControlChange(CC7, 127, channel);
  }
  if (button8.fallingEdge()) {
  usbMIDI.sendControlChange(CC8, 127, channel);
  }
  if (button9.fallingEdge()) {
  usbMIDI.sendControlChange(CC9, 127, channel);
  }
  if (button10.fallingEdge()) {
  usbMIDI.sendControlChange(CC10, 127, channel);
  }
  if (button11.fallingEdge()) {
  usbMIDI.sendControlChange(CC11, 127, channel);
  }
  if (button12.fallingEdge()) {
  usbMIDI.sendControlChange(CC12, 127, channel);
  }
  
// CC messages when each button is released
  if (button1.risingEdge()) {
    usbMIDI.sendNoteOff(60, 0, channel);
  }
  if (button2.risingEdge()) {
    usbMIDI.sendNoteOff(61, 0, channel);
  }
  if (button3.risingEdge()) {
    usbMIDI.sendNoteOff(62, 0, channel);
  }
  if (button4.risingEdge()) {
    usbMIDI.sendNoteOff(63, 0, channel);
  }

  if (button5.risingEdge()) {
  usbMIDI.sendControlChange(CC5, 0, channel);
  }
  if (button6.risingEdge()) {
  usbMIDI.sendControlChange(CC6, 0, channel);
  }
  if (button7.risingEdge()) {
  usbMIDI.sendControlChange(CC7, 0, channel);
  }
  if (button8.risingEdge()) {
  usbMIDI.sendControlChange(CC8, 0, channel);
  }
  if (button9.risingEdge()) {
  usbMIDI.sendControlChange(CC9, 0, channel);
  }
  if (button10.risingEdge()) {
  usbMIDI.sendControlChange(CC10, 0, channel);
  }
  if (button11.risingEdge()) {
  usbMIDI.sendControlChange(CC11, 0, channel);
  }
  if (button12.risingEdge()) {
  usbMIDI.sendControlChange(CC12, 0, channel);
  }


  // MIDI Controllers should discard incoming MIDI messages.
  while (usbMIDI.read()) {
  }
}
 
I did some more digging, and I found the example code called AnalogControlChange. I think I can copy and paste from that. However, I opened up my project box and I'm looking at my Teensy board, and I'm realizing that it's not laid out quite the way I was thinking. I see that there are ten analog pins and a ground, but that's only two pins and an expression pedal has three pins. So where do I connect the third pin?
 
What's the spec on the 'expression pedal'? Is it self powered or is that third line feeding power to the pedal to feed/return the signal? If power make sure it can work with 3.3V max output to the Teensy.
 
Expression pedals used with MIDI keyboards etc. are effectively just voltage dividers oftenwith a floor side-circuit to set the range of the sweep (on the lower end).

There are two common polarities both with sleeve ground but swapping tip and ring for wiper and hot.

They will typically work with 3.3 volts but the long cable makes the noise problem potentially much worse. I've considered active circuits but for seven-bit MIDI even fairly simple 'filtering' has always provided usable results.

A capacitor across the wiper and ground is often recommended but commercial expressions pedals generally (universally?) lack this feature. Other circuitry can be tried if you have problems you can't sort in software. Usually the excellent ResponsiveAnalogRead() library is the best bet for anyone that doesn't want to write their own filter/hysteresis algorithms.

There are a small number of calls needed to use the default settings -- which usually are good enough to get a signal stable at seven digits and still responsive enough to increment the output if you have the control and the pot in the pedal is in good condition.

To have both that and your existing code you just need to add the missing analog steps before or after the switch code.

If I remove the array variable stuff from my many knobs and buttons code I get this:
Code:
	// update the ResponsiveAnalogRead object every loop
	analog.update(); 
	// if the repsonsive value has change, send out 'changed'
	if(analog.hasChanged()) {
	  data = analog.getValue()>>3;
	  if (data != dataLag){
		dataLag = data;
		usbMIDI.sendControlChange(CCID, data, channel);
	  }
	}

Which is pretty close to what's needed, minus the required declarations and setup of the analog pin

Here's the declaration for the library object:

ResponsiveAnalogRead analog(ANALOG_PIN, true);


It works by storing the last value you sent and only sending another if the value is different.

This lets you keep the ResponsiveAnalogRead resolution at 10 bits but you could also set it to seven bits and then the .hasChanged() function should do the same thing for you... In theory it should be a bit better as it gives his code more room but I never really tested it.

https://github.com/dxinteractive/ResponsiveAnalogRead#analog-resolution

My Many buttons and knobs code could be used as is if you configure it for one analog input. Late here... hope this helps for now.
 
Thanks for your help @oddson. I tested my pedal with a multimeter, and it looks like the tip is the wiper, and the ring and sleeve are the two ends of the resistor, which is about 20k Ohms. Anyway, I'm still not totally sure how to wire this. I'm guessing maybe the GND and 3.3V pins go to the ring and sleeve, and then I just pick one of the ten analog pins and that connects to the tip. Does that sound right?
 
That sounds right - just a potentiometer with a long cable and a cool pedal.

If ring and sleeve can be safely wired (without short) as GND and 3.3V the wiper tip will show the value vary with the pedal. Which is which will change the response direction with pedal movement and that may suggest which should go to which.
 
Yes that makes sense.

Think of some low value R(say 47R) between +3.3v and Ring to act as current limit in case something shorts while plugging in.

Some R (say 4k7) between tip and Analog pin and some C (47N) between analog pin and 0v at the Teensy end for some filtering may be helpful. Take care to avoid ground loops.
 
Status
Not open for further replies.
Back
Top