New Encoder library suggestion

Kitwn

Member
Last year I built a MIDI controller for a software guitar amplifier using rotary encoders, a Teensy 4.1 and the Encoder library. It worked very well but the need for 2 pins per encoder rather than 1 for a potentiometer restricts the number of encoders which are the preferred device where one knob may be used to adjust several inputs.
I wondered if it would be possible to devise a library that uses one pin per encoder plus 2 ( or possibly just 1 with an external inverter) additional pins. The idea is that instead of commoning the centre (c) pins of the encoders and reading the other two (a,b), the a and b pins are each commoned to an output pin with the c pins having an input pin each. By setting the a pins high and b pins low, reading the c pins will indicate which are connected to a. Reversing the polarity of the a and b pins will allow you to read the b pins. Putting this data into arrays and compare readings on each program cycle will derive the same information as the normal process.
This method may not be fast enough for motor driven encoders but might work for manually operated knobs on a control surface.
My skills are limited to some basic Arduino-Speak coding so I'm throwing this idea out to those who will know whether or not it is practical and how to make it work if it is.
 
But a quadrature encoder works by comparing the phases of A and B to determine direction and magnitude. How can it possibly work if A and B are connected?
 
I'm also not imagining exactly how it would work. Maybe some crafty trick with resistors? Whatever rapid polling is used, it needs to be able to distinguish all 4 possible quadrature states.
 
You probably want to take a look at EncoderTool, which provides various ways of creating larger encoder arrays using fewer pins. I haven’t used it much, but the author is on here as @luni, though hasn’t posted for about a year.

If you’re tempted to use the “matrix” version, I think there may be a gotcha. The example schematic shows 15 encoders wired up in 5 columns of 3 encoders, using 3 row pins per encoder (A, B and switch), for a total of 5+3*3=14 pins. However, there’s no diode isolation shown, which is typically needed for such an arrangement, though tiny diode symbols are visible inside the encoders themselves. If such encoders exist, fine. If not, you’d need to add 3 diodes per encoder. Essentially it’s just a 45-key keyboard, so if you google “keyboard matrix diode isolation” I’m sure you’ll find an explanation of why that’s necessary.
 
Sure, there's something there. On a JPG image.

I opened the KiCad and the PCB layout does indeed have components with A and K labels on the pins. But nothing on the schematic (apart from tiny symbols within the encoder outlines, implying they're part of the encoder itself). Nothing appears in the Bill of Materials, either.

Is that really the standard of documentation which we'd expect someone whose "skills are limited" to be able to build from successfully, without a bit of assistance?
 
Is that really the standard of documentation which we'd expect someone whose "skills are limited" to be able to build from successfully, without a bit of assistance?
No, I would not have recommended OP use code that is designed for a custom-made PCB with SMD components.
 
My explanation of the idea was not as clear as it could have been, but wouldn't work as described anyway as I had missed one glaring error which is that for one of the 4 possible states the C pin shorts the As and Bs together, at which point the whole cunning plan fails!

I've made several drawings over the last hour, which is what I should have done before posting in the first place!
The attached drawing shows two rotary encoders C1 and C2. The A pins are connected to the 'A COMMON PIN' via diodes as shown, same for the B bins. C pins connect to individual pins set as INPUT_PULLUP.
If the A COMMON pin is LOW and the B HIGH then diodes D2 and D4 are reverse biased and effectively open circuit. IN1 is pulled LOW via D1 showing the C-A connection. IN2 is HIGH indicating C-A is open.
Reversing the polarity of the common pins indicates that C-B connections are made for both encoders. All 4 possible quadrature states can be detected from these two measurements. The total number of coders possible is N-2 where N is the number of available pins on your chosen controller board.

But there's more! If we make both A and B common rails HIGH both the encoders are effectively isolated by their diodes and the two inputs could be used by another pair of encoders connected in parallel using another pair of A and B common pins. The total number of encoders is now (N-4)x2. We can extend this to (N-6)x3, (N-8)x4 and so on. For example 22 pins could connect to up to 60 separate encoders.
For manual encoders being used for, say, a control surface for a DAW I doubt if a Teensy 4.x running at 600MHz would introduce a significant delay by having to scan all these inputs into arrays, debounce them and process the data into MIDI outputs.
The fact that the A-C and B-C states ae not being read at exactly the same time may introduce the occasional error, but for this kind of aplication I doubt that would be noticed.
Encoder Mplex.jpg
 
Last edited:
But even if your idea doesn’t work, your goal is achievable, as discussed in my post #4. Just use EncoderTool and one of its various hardware options. Despite the comment in post #7, the code does not require a PCB or surface mount components, though of course such things are very helpful on occasion. Just go slow, be neat, test often :)

The matrix variant shown uses 15 pins for 15 encoders (though it could be 16 encoders if they were wired 8x2 rather than 5x3). For those 15 encoders you’d need 45 diodes, or 30 if you don’t use the switches. 1N4148 are often recommended, but that may date back to the days of 5V logic where the voltage levels were a bit different. Something like a 1N5187 Schottky diode might be a better choice, but I’m not 100% sure. You can get a lot of diodes for the cost of the other hardware options…

Do come back and let us know if you try this.
 
In my synth project, I use a total of 7 encoders and an MCP23017 GPIO expansion module. This works very well.
When the encoders are moved, the MCP23017 sends an interrupt signal to the Teensy MCU. The Teensy then queries the GPIO lines connected to the encoders via the I2C bus. Up to 7 encoders can be queried simultaneously. The 16-bit data is then masked, and I receive the encoder data.

The drawing shows only two encoders. Seven encoders per MCP23017 are possible.
Screenshot 2026-05-03 121759.png


Video
 
You probably want to take a look at EncoderTool, which provides various ways of creating larger encoder arrays using fewer pins. I haven’t used it much, but the author is on here as @luni, though hasn’t posted for about a year.

If you’re tempted to use the “matrix” version, I think there may be a gotcha. The example schematic shows 15 encoders wired up in 5 columns of 3 encoders, using 3 row pins per encoder (A, B and switch), for a total of 5+3*3=14 pins. However, there’s no diode isolation shown, which is typically needed for such an arrangement, though tiny diode symbols are visible inside the encoders themselves. If such encoders exist, fine. If not, you’d need to add 3 diodes per encoder. Essentially it’s just a 45-key keyboard, so if you google “keyboard matrix diode isolation” I’m sure you’ll find an explanation of why that’s necessary.
Thank you, I will definately have a look at that.
But even if your idea doesn’t work, your goal is achievable, as discussed in my post #4. Just use EncoderTool and one of its various hardware options. Despite the comment in post #7, the code does not require a PCB or surface mount components, though of course such things are very helpful on occasion. Just go slow, be neat, test often :)

The matrix variant shown uses 15 pins for 15 encoders (though it could be 16 encoders if they were wired 8x2 rather than 5x3). For those 15 encoders you’d need 45 diodes, or 30 if you don’t use the switches. 1N4148 are often recommended, but that may date back to the days of 5V logic where the voltage levels were a bit different. Something like a 1N5187 Schottky diode might be a better choice, but I’m not 100% sure. You can get a lot of diodes for the cost of the other hardware options…

Do come back and let us know if you try this.
Having looked at the EncoderTools explanation it appears I have partially re-invented their wheel. The difference in our methods is that Luni sets just one of the common C lines HIGH and then interrogates the A and B coder lines and the switch whereas I have opted to set just one of the common A or B lines LOW and interrogate the C, which does not include a means of reading the switch.
Thank you to everyone who replied to me and especially for the introduction to the EncoderTool library which is exactly what I need.
 
In my synth project, I use a total of 7 encoders and an MCP23017 GPIO expansion module. This works very well.
When the encoders are moved, the MCP23017 sends an interrupt signal to the Teensy MCU. The Teensy then queries the GPIO lines connected to the encoders via the I2C bus. Up to 7 encoders can be queried simultaneously. The 16-bit data is then masked, and I receive the encoder data.

The drawing shows only two encoders. Seven encoders per MCP23017 are possible.
View attachment 39276

Video
I was hoping to avoid having to learn how to use multiplexing if possible, especially as it would make for a more complex layout on veroboard for which a stand-alone Teensy 4.1 is perfect.
My previous MIDI controller for a software guitar amp managed to connect 12 encoders and their switches, 2 12-way rotary switches, an expression pedal, 6 foot switches and 18 LEDs directly to one Teensy 4.1 (see attached picture), but I'm currently wondering what kind of control surface is going to be best to create a simple to use recording/mixing set-up for the Cubase DAW. Preferably on Veroboard once again.MIDI Controller Board-1.jpg
 
That’s a very impressive amount of I/O already! I make it 85 “pins” if everything is done individually, plus however you’ve done the MIDI. I’d be curious to know how you’ve achieved that, if you have a diagram you can easily post.

Just by adopting EncoderTool and adding diodes, you could get the encoders, rotary switches and foot switches done with 12+6=18 I/O pins* and 66 diodes. Any vaguely sensible number of LEDs can be done by using a single pin and WS2812 addressable LEDs, for which there is extensive and easy to use library support.

currently wondering what kind of control surface is going to be best
Always best to plan before doing … advice I don’t always manage to adhere to!

I was hoping to avoid having to learn how to use multiplexing if possible, especially as it would make for a more complex layout on veroboard
Ideally you wouldn’t have to learn too much, as a suitable library would do it for you. But I’m not sure if an encoder library exists for Teensy and MCP23017 (I2C) or MCP23S17 (SPI). Pretty sure @Rolfdegen has rolled his own. Not having to learn too much is a good way to getting a project completed, for sure. I love the learning aspect, which is why I hardly ever complete a project.

* in case it’s not obvious, that’s 12 “row” inputs, and 6 “column” outputs; each rotary switch is its own column, plus 3 columns of 4 encoders, and one part-used column of foot switches.
 
That’s a very impressive amount of I/O already! I make it 85 “pins” if everything is done individually, plus however you’ve done the MIDI. I’d be curious to know how you’ve achieved that, if you have a diagram you can easily post.

Just by adopting EncoderTool and adding diodes, you could get the encoders, rotary switches and foot switches done with 12+6=18 I/O pins* and 66 diodes. Any vaguely sensible number of LEDs can be done by using a single pin and WS2812 addressable LEDs, for which there is extensive and easy to use library support.


Always best to plan before doing … advice I don’t always manage to adhere to!


Ideally you wouldn’t have to learn too much, as a suitable library would do it for you. But I’m not sure if an encoder library exists for Teensy and MCP23017 (I2C) or MCP23S17 (SPI). Pretty sure @Rolfdegen has rolled his own. Not having to learn too much is a good way to getting a project completed, for sure. I love the learning aspect, which is why I hardly ever complete a project.

* in case it’s not obvious, that’s 12 “row” inputs, and 6 “column” outputs; each rotary switch is its own column, plus 3 columns of 4 encoders, and one part-used column of foot switches.
Lots of helpful information there. Addressable LEDs are a new one to me.
MIDI output is via USB, the rest of the 'magic' was achieved as follows:

24 pins for the encoders.
1 analogue pin each for the 12 way switches which are wired with resistors as stepped potentiometers and the inputs detect 12 different input voltages.
1 analogue pin each for 2 rows of 6 encoder switches and 1 set of 6 footswitches (can be extended to 12 if required) which are wired much as the rotary switches. Only press one from each set at a time!
1 analogue pin for the expression pedal.
2 sets of 6 LEDs each are Charlieplexed onto 3 pins each. Only one LED of each 6 will be on a time so there's no need for complex multiplexing. The other 6 LEDs have dedicated pins.
Every standard pin on the Teensy is used. I did try soldering wires onto the pads for inputs 48-54 but only succeeded in pulling the pads off.

There is a video of the controller in use but it's not very exciting as I had Covid at the time!
 
Last edited:
Back
Top