Multiplexing with control_surface

hello! i'm a complete beginner with arduino (and with programming in general) and like many before me i'm trying to build a custom MIDI-controller. i'm having trouble with jittery/noisy/unwanted output from my potentiometers, and i know this is a common issue for beginners but all the posts i could find were based on the old library MIDI_controller and i wonder if there are simpler ways of dealing with this in control_surface. apologies if i've missed an old thread that addresses my specific problem!

so, the problem is: when i connect my potentiometers directly to the arduino they work fine, but if i try to multiplex them they start outputting a continuous stream of values and they don't respond linearly, so it's basically impossible to use them. i'm on an arduino leonardo and i'm just trying to implement a simple prototype that i would want to scale up at a later point (because my goal is to have a midi controller with up to 96 elements between potentiometers and buttons, using 16-channel multiplexers). i took the code on this page and tweaked it to begin making a first prototype. here's the result:

// Include the library
#include <Control_Surface.h>
 
// Instantiate a MIDI Interface to use
USBMIDI_Interface midi;
 
// Instantiate an analog multiplexer
CD74HC4051 mux {
  A0,       // Analog input pin
  {0, 1, 2} // Address pins S0, S1, S2
};
 
// Create an array of potentiometers that send out
// MIDI Control Change messages when you turn the
// potentiometers connected to the eight input pins of
// the multiplexer
  CCPotentiometer volumePotentiometers[] {
  { mux.pin(0), {10, CHANNEL_1 } },
  { mux.pin(1), {20, CHANNEL_1 } },
  { mux.pin(2), {30, CHANNEL_1 } },
  { mux.pin(3), {40, CHANNEL_1 } },
  };


CCPotentiometer potentiometer_01 { A5, {17, CHANNEL_1} };
 
// Initialize the Control Surface
void setup() {
  Control_Surface.begin();
}
 
// Update the Control Surface
void loop() {
  Control_Surface.loop();
}

i'm working on a small bread board and i can only fit 4 potentiometers onto it. while testing my prototype, i unplugged one of them and connected it to A5 and it worked perfectly. only the potentiometers connected to the multiplexer behave erratically. i tried the same thing with a 4-bit multiplexer and had exactly the same issue. i swapped the potentiometers for buttons (and adapted the code for this configuration) and the buttons worked fine.
the potentiometers are 10k, i tried to power them separately from the multiplexer through leonardo's 3.3v outlet but it didn't change a thing.

any help would be greatly appreciated :pray:

(p.s. i understand that using hysteresis should help with this issue as the values outputted are all within a relatively small range but i couldn't figure out how to implement that from reading control_surface's documentation and i kind of gathered from an old post by the library's author that it should work automatically :thinking: if i scratch my head a bit more i can soon start a career as a brain surgeon!)

This sounds like a hardware or wiring issue. Especially with 10kΩ pots, you shouldn't notice a difference between multiplexed and non-multiplexed pots.

This is going to be very challenging. You'll need to take into account how long it takes to sample a single analog input, and how much memory all those Control Surface elements will require.

Why 3.3V? You'll want to power the pots and the multiplexer all from the 5V power line of the Leonardo, because that's the reference level it uses for its analog inputs.

Indeed, Control Surface applies this automatically for the xPotentiometer classes. It uses the FilteredAnalog class explained here: Arduino Helpers: 1.FilteredAnalog.ino

To get more filtering, you could increase the ANALOG_FILTER_SHIFT_FACTOR by editing ~/Arduino/libraries/Control-Surface/src/AH/Settings/Settings.hpp (and optionally increasing ANALOG_FILTER_TYPE to 32 bits as well).

You are partaking on a very complex project even for an experienced engineer. Helping you is very difficult without a roadmap (Schematic showing all connections including power and ground would be a good starting point). Frizzy pictures do not count as a schematic. It appears you are working in the digalog (digital/analog) arena. I have no idea of your resources and electronics background.

Thanks for your reply, and thanks for the amazing work in maintaining this library!

This sounds like a hardware or wiring issue.

I have a bag of 10 pots and they all did the same thing. I tried to wire them both to a 3-bit and a 4-bit multiplexer and the result was the same :frowning: I'm going through a couple of very busy weeks but I'll post a diagram of my connections as soon as I can!

This is going to be very challenging. You'll need to take into account how long it takes to sample a single analog input, and how much memory all those Control Surface elements will require.

If I manage to get this thing to work (and that's a big if) I might try to split it to two separate boards or to build it with a higher-specs board. Do you have a recommendation?

Why 3.3V?

I just tried out of desperation to see if it would make a difference but it didn't.

To get more filtering, you could increase the ANALOG_FILTER_SHIFT_FACTOR by editing ~/Arduino/libraries/Control-Surface/src/AH/Settings/Settings.hpp (and optionally increasing ANALOG_FILTER_TYPE to 32 bits as well).

I haven't had the time to try that out, I'll post about it as soon as I have!
Thanks again!

ok, so I simplified my prototype to see if it would make it easier to figure out the problem. This is the schematic (sorry if it's a bit chaotic, I'm doing this for the first time!):


and this is the sketch:


#include <Control_Surface.h>  // Include the library

USBMIDI_Interface casareccia;  // Instantiate a MIDI Interface to use

// Instantiate an analog multiplexer
CD74HC4051 mux {
  A0,       // Analog input pin
  {0, 1, 2} // Address pins S0, S1, S2
};

  // Create an array of CCPotentiometer objects that send out MIDI Control Change
  // messages when you turn the potentiometers connected to the 8 inputs of the mux.
 
  CCPotentiometer volumePotentiometers[] {
  { mux.pin(0), {10, CHANNEL_1 } },
  { mux.pin(1), {20, CHANNEL_1 } },
/* 
  { mux.pin(2), {30, CHANNEL_1 } },
  { mux.pin(3), {40, CHANNEL_1 } },
*/
  };


CCPotentiometer potentiometer_01 { A5, {17, CHANNEL_1} };
/*
CCPotentiometer potentiometer { A1, {17, CHANNEL_1} };
CCPotentiometer potentiometer { A1, {27, CHANNEL_1} };
*/

void setup() {
/*  pinMode(A0, INPUT_PULLUP);
  pinMode(A5, INPUT_PULLUP);
*/  Control_Surface.begin();  // Initialize the Control Surface
}

void loop() {
  Control_Surface.loop();  // Update the Control Surface
}

So here's the new version of my problem: the potentiometer that's wired directly into the board works perfectly well. The other two, they work OK as long as I keep one of them on low values (MIDICC from 0 to maybe 50). If they both go over a certain threshold (I can't put an exact number on this but it's something around MIDICC 50) they latch to each other (i.e. they start outputting the same value) and start flickering and not behaving linearly. I'm assuming that the problem is some kind of signal leak between the wires, I'm doing all of this on a small breadboard and with just these elements it's already crammed. So I ordered a bigger one to see if it works better, but maybe someone has some tips about how to wire things to avoid this issue? Are there also things to look out for when I start soldering things? In the end I wanted to have quite a lot of elements on a relatively small surface and I didn't think/know that the wiring could be an issue, any and all advice is much appreciated :relaxed:

I tried doing this but it didn't really change anything, I really think it's a hardware problem...

  • Connection to the 74HC4051 Ebar pin 6 is not shown but should be tied to GND to enable the mux.

  • Connections to the 74HC4051 channel select (address) pins not shown. In your code, it shows digital pin D0, D1 and D2 being assigned, but D0 and D1 are used for serial communication and should be avoided.

Try ...

CD74HC4051 mux {
  A0,       // Analog input pin
  {2, 3, 4} // Address pins S0, S1, S2
};

Optionally, you could connect only S0 to D2. The 74HC4051 address pins S1 and S2 can be tied to GND as they're not needed when only the first 2 channels are required.

I'm not familiar with the library, but shouldn't you be controlling the mux address pins to select the pot on CHANNEL_0 and the pot on CHANNEL_1 ?

No worries, even hand-drawn would have been fine.
It's common to use ground symbols and +5V/Vcc/Vdd symbols rather than routing all the power wires to the Arduino, that reduces the number of wires and intersections, making the schematic much easier to read.

As mentioned by dlloyd, you have to connect the address lines, and tie the inhibit/enable pin to ground to turn on the chip. Tie all unused inputs to ground as well, and make sure that the unused address lines are at a known level as well (either +5V or ground).

On the Leonardo, D0 and D1 are Serial1, which is not used here, so using them as GPIO pins is fine.

The channel here refers to the MIDI channel, the mux channel is handled internally (based on the argument to mux.pin(n)).

1 Like

This topic was automatically closed 180 days after the last reply. New replies are no longer allowed.