MIDI Controller using 16 Rotary Encoders

Status
Not open for further replies.
I'm looking to make a box with 16 rotary encoders (ALPS EC12 series), to generate MIDI messages. Originally I was going to use an Arduino with an MCP23S17 and a hack to allow USB MIDI, then I discovered the Teensy 3.2.

I plan on hooking all 16 encoders up to 32 pins on the Teensy - is there any issue with this? Any pins recommended to avoid (e.g. pin 13 - LED)?

I will be using this with Ableton Live, which supports incremental MIDI messages, so each encoder will send a CC of either 0 or 127 – for CCW and CW rotation. Are there any other caveats to watch out for with this?

Am I OK sending the MIDI messages from an interrupt routine or do I need to queue up messages for sending separately?

The closest thing I can compare my project to is the MIDI Fighter Twister, although my project wont have the nice LED ring, but will have a nice 3D printed custom enclosure, and I will Open Source the project after because it's a neat little project :cool:
 
I'm looking to make a box with 16 rotary encoders (ALPS EC12 series), to generate MIDI messages. Originally I was going to use an Arduino with an MCP23S17 and a hack to allow USB MIDI, then I discovered the Teensy 3.2.

I plan on hooking all 16 encoders up to 32 pins on the Teensy - is there any issue with this? Any pins recommended to avoid (e.g. pin 13 - LED)?

I will be using this with Ableton Live, which supports incremental MIDI messages, so each encoder will send a CC of either 0 or 127 – for CCW and CW rotation. Are there any other caveats to watch out for with this?

Am I OK sending the MIDI messages from an interrupt routine or do I need to queue up messages for sending separately?

The closest thing I can compare my project to is the MIDI Fighter Twister, although my project wont have the nice LED ring, but will have a nice 3D printed custom enclosure, and I will Open Source the project after because it's a neat little project :cool:

I would avoid pin 13 if possible. I have non-interrupt driven code for multiple rotaries, if you like. I've never used it for so many encoders though. 4 is the most I've used it for. It has signal smoothing worked in, too, and digital fast reads ....

there are several good breakout boards available to get to the underside pins. I use Frank B's board.... I think he has made it more useable recently by numbering the breakout pins.... there are several others around.

good luck!

EDIT: a bit of advice .... get things working with one or two rotaries first ... code to send CC messages (presumably indexed to different channels 1 -16?) is easy, but taking small steps is advisable, to work up to a full solution ....
 
Last edited:
I would avoid pin 13 if possible. I have non-interrupt driven code for multiple rotaries, if you like. I've never used it for so many encoders though. 4 is the most I've used it for. It has signal smoothing worked in, too, and digital fast reads ....

Interesting, is there any reason you don't use interrupts? I don't imagine interrupts are essential for my purpose - maximum of two encoders will be used at a time, hand turned only, so it will be more than slow enough for the micro to read it. Although my board will be doing nothing else so no hassle using interrupts.

there are several good breakout boards available to get to the underside pins. I use Frank B's board.... I think he has made it more useable recently by numbering the breakout pins.... there are several others around.
Unfortunately, getting the breakouts to the UK is cost prohibitive, but I'm tempted to just spinout a custom board in Eagle that Ragworm.eu can print out for me. Would make mounting the Teensy much easier in my enclosure too as I can include mounting pins.

EDIT: a bit of advice .... get things working with one or two rotaries first ... code to send CC messages (presumably indexed to different channels 1 -16?) is easy, but taking small steps is advisable, to work up to a full solution ....

Yes this is sage advice. I've just put the long edge header pins on, and the 3D printer is printing a couple of knobs for my encoders so I can get down and write some code tonight!
 
Interesting, is there any reason you don't use interrupts? I don't imagine interrupts are essential for my purpose - maximum of two encoders will be used at a time, hand turned only, so it will be more than slow enough for the micro to read it. Although my board will be doing nothing else so no hassle using interrupts.

I found that interrupt driven code gave a lot of false readings, so I opted for smoothing, and interrupts was no good for that the way I structured my code.

Unfortunately, getting the breakouts to the UK is cost prohibitive, but I'm tempted to just spinout a custom board in Eagle that Ragworm.eu can print out for me. Would make mounting the Teensy much easier in my enclosure too as I can include mounting pins.

I have a couple of Frank B's breakout boards on me, spare, with the new screen printing ... In between originally posting about them and now, they arrived in the post!!!!! they are cheap as chips ... I ordered extr4a!!! if you can't be bothered waiting on digistump I could post you a couple...

Yes this is sage advice. I've just put the long edge header pins on, and the 3D printer is printing a couple of knobs for my encoders so I can get down and write some code tonight!

Here is my github .... you want 'myController'. It has the encoder code ... it works by callbacks ... there is a simple example...
 
I found that interrupt driven code gave a lot of false readings, so I opted for smoothing, and interrupts was no good for that the way I structured my code.

OK interesting, thanks for letting me know.


I have a couple of Frank B's breakout boards on me, spare, with the new screen printing ... In between originally posting about them and now, they arrived in the post!!!!! they are cheap as chips ... I ordered extr4a!!! if you can't be bothered waiting on digistump I could post you a couple...

Thats very kind of you. I've looked at his breakout but it might cause me issues with the enclosure box, as I plan to place the USB as close to a wall as possible so I can plug directly, so I might need a custom job.


Here is my github .... you want 'myController'. It has the encoder code ... it works by callbacks ... there is a simple example...

Oh neat! I'll take a look.
 
I have noticed a slight issue, I've loaded the Basic encoder example, with the encoder set to pins 0 & 1. Running the serial monitor I just get the following output:
Code:
1
0

1 here indicates the encoder is turning towards a detent, 0 means it has hit the detent. This is the same behaviour whether I turn CW or CCW.

I have hooked the encoders up as follows

TUnhNtn.png

Am I missing something crucial? Full sketch here:

Code:
/* Encoder Library - Basic Example
 * http://www.pjrc.com/teensy/td_libs_Encoder.html
 *
 * This example code is in the public domain.
 */

#include <Encoder.h>

// Change these two numbers to the pins connected to your encoder.
//   Best Performance: both pins have interrupt capability
//   Good Performance: only the first pin has interrupt capability
//   Low Performance:  neither pin has interrupt capability
Encoder myEnc(0, 1);
//   avoid using pins with LEDs attached

void setup() {
  Serial.begin(9600);
  Serial.println("Basic Encoder Test:");
}

long oldPosition  = -999;

void loop() {
  long newPosition = myEnc.read();
  if (newPosition != oldPosition) {
    oldPosition = newPosition;
    Serial.println(newPosition);
  }
}

I'm unsure the exact part number of my encoder, but its a 24 detent ALPS encoder, quite possibly EC12 series. I don't know if its relevant, but I've tried on both OS X 10.11.6, and Windows 10, with Arduino 1.6.8 and the latest Teensyduino. I also don't get the "Basic Encoder Test:" line during setup.
 
Last edited:
should have used my library :rolleyes:.....

... why not just Serial.println (myEnc.read()); see what you get.

I think the encoder library just returns a count ....

I have a 24 alps encoder too... maybe a different model .... works fine..
 
should have used my library :rolleyes:.....

... why not just Serial.println (myEnc.read()); see what you get.

I think the encoder library just returns a count ....

I have a 24 alps encoder too... maybe a different model .... works fine..

Lol fair point. I wanted to just ensure I had everything connected correctly before experimenting. I've got a sneaky feeling the encoder isn't making good enough contact with my breadboard pins. I'll solder wires to the pins tomorrow and see if that helps out.

Slightly off topic, how do you find the MIDI resolution of encoders? it just occurred to me if one detent is an increment of 1, wouldn't it take around 5 rotations to get a full range of 0-127? Do you use any acceleration?
 
I have noticed a slight issue, I've loaded the Basic encoder example, with the encoder set to pins 0 & 1. Running the serial monitor I just get the following output:
Code:
1
0

1 here indicates the encoder is turning towards a detent, 0 means it has hit the detent. This is the same behaviour whether I turn CW or CCW.
That's "normal". Depending on the encoder, it may or may not generate multiple steps per detent. The encoder may be "unstable" right at the detent (have a switching point at the dentent). E.g. look at the output wave for Alps EC12D and EC12E:
http://www.alps.com/prod/info/E/PDF/Switch/Encoder/EC12E/EC12E.PDF
 
Maybe try input pull-ups too, just to be safe...

And yeah the waveform of the encoder ... its the internal mechanics of the switch ...you kind of get the feel of two detents for one on some of the rotaries I've used ... and of course if you want 127 steps for midi you are limited by the switching capability of your encoder .... you can always count in twos, byut then you will only get 64 steps obviously, for midi .... one solution to the need for many turns is to get one of those scrub wheels so you can turn really fast
 
I've soldered on some wires and I'm definitely getting something now. Turning CW gives me about 4 steps per detent, which is good. Turning CCW is bugged though. If I turn CW to 40, then turn CCW, it displays the following:
Code:
40
42
41
40

So it jumps up 2, then -1, -1.
 
I've soldered on some wires and I'm definitely getting something now. Turning CW gives me about 4 steps per detent, which is good. Turning CCW is bugged though. If I turn CW to 40, then turn CCW, it displays the following:
Code:
40
42
41
40

So it jumps up 2, then -1, -1.

Interrupts with 'average' mechanical rotaries can do that. smoothing is good... ignore fast changes and only record an event if there is '4 in a row' or something like that
 
I've soldered on some wires and I'm definitely getting something now. Turning CW gives me about 4 steps per detent, which is good. Turning CCW is bugged though. If I turn CW to 40, then turn CCW, it displays the following:
Code:
40
42
41
40

So it jumps up 2, then -1, -1.
A change of 2 means that both A and B channels switched at the same time. That should be impossible. The channels should mechanically offset so that only one can switch at a time (and the other one is sliding). Are both your encoders doing this? Does it happen consistently?

I have encoders that do 2 steps per detent and encoders that do 4 steps per detent. They can glitch a single step up/down (sometimes bouncing quite a few times back and forth) but I have NEVER seen a glitch where they do 2 steps at once (using the encoder library).
 
A change of 2 means that both A and B channels switched at the same time. That should be impossible. The channels should mechanically offset so that only one can switch at a time (and the other one is sliding). Are both your encoders doing this? Does it happen consistently?

I have encoders that do 2 steps per detent and encoders that do 4 steps per detent. They can glitch a single step up/down (sometimes bouncing quite a few times back and forth) but I have NEVER seen a glitch where they do 2 steps at once (using the encoder library).

No, sorry I think I wasn't clear - what I mean is the serial monitor output jumps up 2 steps, then down 1, then down 1 again, then repeats. So if my current value is 35, rotating ccw results in 37, 36, 35, 37, 36, 35, etc.

Moving CW correctly performs value++
 
No, sorry I think I wasn't clear - what I mean is the serial monitor output jumps up 2 steps, then down 1, then down 1 again, then repeats. So if my current value is 35, rotating ccw results in 37, 36, 35, 37, 36, 35, etc.
If that's happening consistently, either your encoder is faulty or not wired correctly. Try all 3 pins for the ground connection to the encoder (if A and B are swapped, only the direction will change).
 
I swapped what I thought were pins A & C, and it works. Very interesting that one side worked when the ground was connected to the wrong pin.
 
I've completed the code for this project now, source code is available on GitHub. There is some spectacularly awful acceleration code. Now to draw up a PCB and 3D enclosure! Thanks for all the help all!
 
not to put a spanner in the works, but....

Have you seen these?

https://www.sparkfun.com/products/10982

I'm using them for a reasonably similar project - photos attached ;)

This project falls squarely into the category of "Should have done a PCB". It was, and continues to be a complete wiring nightmare.

dark.jpglight.jpgp1gutz.jpg

If you do look at them - One thing to note is that the pushbutton is a switch between the 5v LED supply and the pin, which on a Teensy-LC is too high a voltage. I didn't notice this until i'd wired the whole lot - So I had to bodge it to run the LEDs @ 3,3v which actually works, but they are unfortunately running on the 3.3v from the Teensy, and i'd added resistors to drive them at 5v, so now they are a touch too dim at 100%. :) :)

The right thing to do is either use a teensy 3.2 or even better use either and drop the voltage from the button 5v into the pin.
 
Last edited:
I have actually! I discounted them for a couple of reasons - firstly the cost. Secondly, I've been a bit lazy just attaching each encoder to a pair of interrupts. I actually have a couple of IO expanders (MCP23S17) that I could try and figure out to minimise the pins I use.

I did have an idea of making a PCB with a ring of SMD LEDs, but that's just floating round in my head at the moment.

Those arcade switches look fantastic! Which ones are they? Are they RGB LEDs?

I recognise your name from another thread - did you ever figure out how to change the USB product name of your project? That's on my to do list for today, so if you have any pointers I'd welcome them.
 
The arcade buttons are just adafruit ones, with a circle of black card inserted in the middle. This was a mistake - I should have used Sanwa ones, the adafruit ones are ok but sanwa are so much nicer. The LEDs are adafruit WS2812B mini-pcbs wired up with thick solid core cable and hot glued into position, and i created a cardboard cowl to wrap around the button to prevent leakage.

I did play with changing the name of the product but I keep updating my Teensy and i've decided to leave this until the very end. It's possible but windows ignores your changes so you have to plug it into a fresh pc to see if its worked. If it hasn't.........well you need to find a new fresh pc.

If i'm correct a linux PC would report the updated name properly each time? I don't know.
 
I did have an idea of making a PCB with a ring of SMD LEDs, but that's just floating round in my head at the moment.

you dont have to make them, mayhew labs used to make some and the encoder manufacturer sells a number options of LED rings designed for this (or any other) encoder.

But its going get expensive.
 
The arcade buttons are just adafruit ones, with a circle of black card inserted in the middle. This was a mistake - I should have used Sanwa ones, the adafruit ones are ok but sanwa are so much nicer. The LEDs are adafruit WS2812B mini-pcbs wired up with thick solid core cable and hot glued into position, and i created a cardboard cowl to wrap around the button to prevent leakage.

Yeah sanwa are proven very reliable, I'm just not sure if they do any low profile, with clear rings. Although I suppose they have to as the MIDI Fighter uses them.

I did play with changing the name of the product but I keep updating my Teensy and i've decided to leave this until the very end. It's possible but windows ignores your changes so you have to plug it into a fresh pc to see if its worked. If it hasn't.........well you need to find a new fresh pc.

It seems that you can just override the USB names, which would prevent having to hack the core code. I'll give it a go and see what happens.

If i'm correct a linux PC would report the updated name properly each time? I don't know.

I'm on a Mac which shares a lot in common with Linux, so hopefully it will be reflected.
 
Status
Not open for further replies.
Back
Top