Control-Surface
Control-Surface copied to clipboard
matrix keyboard not working with mux
Hi! I build a midi controller using Your great library. Everything works except matrix keyboard. Electrically everything is correct, columns are 5V pulled up by internal resistors, rows are connected to mux inputs. During button press there is voltage transition LOW to HIGH on each row, measured by voltmeter Every other part of sketch is working correctly : 4 pots, 4 faders, 2 encoders, 5 CC buttons. Except keyboard.
Below there is full code, board is Arduino Leonardo
Cannot fight this issue, could You help, please?
// Include the library
#include <Encoder.h> // Include the Encoder library.
#include <Control_Surface.h>
// Instantiate a MIDI Interface to use
//USBMIDI_Interface midi;
USBDebugMIDI_Interface usbmidi(115200); // for serial monitor in ide
CD74HC4067 mux = {
A0, // analog pin
{9, 10, 11, 12}, // Address pins S0, S1, S2, S3
//NO_PIN, // Optionally, specify the enable pin
};
// 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), {MIDI_CC::Channel_Volume, CHANNEL_1}},
{mux.pin(1), {MIDI_CC::Channel_Volume, CHANNEL_2}},
{mux.pin(2), {MIDI_CC::Channel_Volume, CHANNEL_3}},
{mux.pin(3), {MIDI_CC::Channel_Volume, CHANNEL_4}},
{mux.pin(4), {MIDI_CC::Channel_Volume, CHANNEL_5}},
{mux.pin(5), {MIDI_CC::Channel_Volume, CHANNEL_6}},
{mux.pin(6), {MIDI_CC::Channel_Volume, CHANNEL_7}},
{mux.pin(7), {MIDI_CC::Channel_Volume, CHANNEL_8}},
};
// Instantiate a CCButton object
CCButton button1 = { mux.pin(8),{MIDI_CC::General_Purpose_Controller_1, CHANNEL_1},
};
CCButton button2 = { mux.pin(9),{MIDI_CC::General_Purpose_Controller_1, CHANNEL_1},
};
CCButton button3 = { 15,{MIDI_CC::General_Purpose_Controller_1, CHANNEL_1},
};
CCButton button4 = { 16,{MIDI_CC::General_Purpose_Controller_1, CHANNEL_1},
};
CCButton button5 = { 17,{MIDI_CC::General_Purpose_Controller_1, CHANNEL_1},
};
// Instantiate a CCAbsoluteEncoder object
CCAbsoluteEncoder enc1 = {
{3, 2}, // pins
MIDI_CC::Pan, // MIDI address (CC number + optional channel)
1, // optional multiplier if the control isn't fast enough
4, //pulse per step
};
CCAbsoluteEncoder enc2 = {
{1, 0}, // pins
MIDI_CC::Pan, // MIDI address (CC number + optional channel)
1, // optional multiplier if the control isn't fast enough
4, //pulse per step
};
const AddressMatrix<4, 5> addresses = {{
{ 1, 2, 3, 4, 5},
{ 6, 7, 8, 9, 10},
{11, 12, 13, 14, 15},
{16, 17, 18, 19, 20},
}};
NoteButtonMatrix<4, 5> buttonmatrix = {
{mux.pin(10), mux.pin(11), mux.pin(12), mux.pin(13)}, // row pins
{4, 5, 6, 7, 8}, // column pins
addresses, // address matrix
CHANNEL_1, // channel and cable number
};
/*
// Instantiate a shift register as output for the LEDs
SPIShiftRegisterOut<24> sreg = {
19, // Latch pin (ST_CP)
MSBFIRST, // Byte order
};
using namespace MIDI_Notes;
// Create a range of LEDs that listens for MIDI Note messages, turning on and off
// the LEDs connected to the eight output pins of the shift register
NoteRangeLEDs<24> leds = { sreg.pins(), note(C, 4) };
*/
// Initialize the Control Surface
void setup() {
Control_Surface.begin();
}
// Update the Control Surface
void loop() {
Control_Surface.loop();
}
You can only use the mux pins as inputs, not outputs. The row pins are outputs, the column pins are inputs, see https://tttapa.github.io/Control-Surface-doc/Doxygen/d2/daf/classNoteButtonMatrix.html#a7b57c72549e335d4aad8f364db6ef299.
Try moving the mux pins to the columns, and use the Arduino pins for the rows.
You are completely right. swapping pins, and reordering code solves the keyboard issue.
I stumbled upon next fail in my project - inverted leds. I soldered them in opposite polarity. Is there any software trick to solve that, some logic inversion? I already resoldered common cathode/anode, so every led lights up after start. Unfortunately also they doesn't respond to MIDI Input i suppose. Recording pushbuttons and, playing them back doesn't switch led state. There are 20 leds connected to 3 shift register connected in series, to ISP port
But I need to admit that Your library is very well documented, pleasure to use... GREAT WORK!!! Thank You for that
Code:
// Include the library
#include <Encoder.h> // Include the Encoder library.
#include <Control_Surface.h>
// Instantiate a MIDI Interface to use
USBMIDI_Interface midi;
//USBDebugMIDI_Interface usbmidi(115200); // for serial monitor in ide
CD74HC4067 mux = {
A0, // analog pin
{9, 10, 11, 12}, // Address pins S0, S1, S2, S3
//NO_PIN, // Optionally, specify the enable pin
};
// 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
const AddressMatrix<4, 5> addresses = {{
{48, 49, 50, 51, 52},
{53, 54, 55, 56, 57},
{58, 59, 60, 61, 62},
{63, 64, 65, 66, 67},
}};
NoteButtonMatrix<4, 5> buttonmatrix = {
{ 7, 6, 5, 4}, // row pins
{mux.pin(10), mux.pin(11), mux.pin(12), mux.pin(13), mux.pin(14)}, // column pins
addresses, // address matrix
CHANNEL_1, // channel and cable number
};
CCPotentiometer volumePotentiometers[] = {
{mux.pin(0), {MIDI_CC::Channel_Volume, CHANNEL_1}},
{mux.pin(1), {MIDI_CC::Channel_Volume, CHANNEL_2}},
{mux.pin(2), {MIDI_CC::Channel_Volume, CHANNEL_3}},
{mux.pin(3), {MIDI_CC::Channel_Volume, CHANNEL_4}},
{mux.pin(4), {MIDI_CC::Channel_Volume, CHANNEL_5}},
{mux.pin(5), {MIDI_CC::Channel_Volume, CHANNEL_6}},
{mux.pin(6), {MIDI_CC::Channel_Volume, CHANNEL_7}},
{mux.pin(7), {MIDI_CC::Channel_Volume, CHANNEL_8}},
};
// Instantiate a CCButton object
CCButton button1 = { mux.pin(8),{MIDI_CC::General_Purpose_Controller_1, CHANNEL_1},
};
CCButton button2 = { mux.pin(9),{MIDI_CC::General_Purpose_Controller_1, CHANNEL_1},
};
CCButton button3 = { 15,{MIDI_CC::General_Purpose_Controller_1, CHANNEL_1},
};
CCButton button4 = { 16,{MIDI_CC::General_Purpose_Controller_1, CHANNEL_1},
};
CCButton button5 = { 17,{MIDI_CC::General_Purpose_Controller_1, CHANNEL_1},
};
// Instantiate a CCAbsoluteEncoder object
CCAbsoluteEncoder enc1 = {
{3, 2}, // pins
MIDI_CC::Pan, // MIDI address (CC number + optional channel)
1, // optional multiplier if the control isn't fast enough
4, //pulse per step
};
CCAbsoluteEncoder enc2 = {
{1, 0}, // pins
MIDI_CC::Pan, // MIDI address (CC number + optional channel)
1, // optional multiplier if the control isn't fast enough
4, //pulse per step
};
// Instantiate a shift register as output for the LEDs
SPIShiftRegisterOut<24> sreg = {
19, // Latch pin (ST_CP)
MSBFIRST, // Byte order
};
using namespace MIDI_Notes;
// Create a range of LEDs that listens for MIDI Note messages, turning on and off
// the LEDs connected to the eight output pins of the shift register
NoteRangeLEDs<24> leds = { sreg.pins(), note(C, 4) };
// Initialize the Control Surface
void setup() {
Control_Surface.begin();
}
// Update the Control Surface
void loop() {
Control_Surface.loop();
}
Is there any software trick to solve that, some logic inversion? I already resoldered common cathode/anode, so every led lights up after start.
Not directly, but I think you should be able to override the SPIShiftRegisterOut::digitalWrite() method to invert the values:
template <uint16_t N>
class InvertedSPIShiftRegisterOut : public SPIShiftRegisterOut<N> {
public:
using SPIShiftRegisterOut<N>::SPIShiftRegisterOut;
void digitalWrite(pin_t pin, PinStatus_t val) override {
SPIShiftRegisterOut<N>::digitalWrite(pin, val == HIGH ? LOW : HIGH);
}
void digitalWriteBuffered(pin_t pin, PinStatus_t val) override {
SPIShiftRegisterOut<N>::digitalWriteBuffered(pin, val == HIGH ? LOW : HIGH);
}
void begin() override {
for (uint8_t i = 0; i < this->buffer.getBufferLength(); ++i)
this->buffer.setByte(i, 0xFF);
SPIShiftRegisterOut<N>::begin();
}
};
Unfortunately also they doesn't respond to MIDI Input i suppose. Recording pushbuttons and, playing them back doesn't switch led state. There are 20 leds connected to 3 shift register connected in series, to ISP port
Time to use a simpler sketch then to isolate the problem. Have you tried the RGB-LED-Chaser example, for instance? Or just try a simple blink sketch to make sure that the shift registers are wired up correctly and that you can control the LEDs. If the LED chaser example works but the LEDs don't do anything when using the NoteLEDRange, you know somethings up with the MIDI input.
But I need to admit that Your library is very well documented, pleasure to use... GREAT WORK!!! Thank You for that
I'm glad to hear that, it's always a struggle to find a balance between a complete API reference, and examples/guides that are actually useful to get started easily and quickly.
Must admit that I'm astonished by response time and accuracy of Your every reply.
Code that You posted works like a charm, and RGB-LED-Chaser example revealed another bug in sketch - wrongly named LatchPin port of Shift Registers (19/A5). Now everything blinks. You ROCK!
Last thing I need to figure out is to how to enable midi output in DAW(ableton), so that LED Change state during playback. But now I know that hardware is configured. Thank You very much for support!
Good afternoon @tttapa .
A question regarding this case.
we want to make a controller based on atmega 32u4
With two encoders and a potentiometer, everything is working perfectly.
But we want two button arrays the first of 4 rows by 10 columns
and the second matrix of 6 columns by 4 rows
The question is the following, we could use a CD74HC4067 multiplexer for the rows and another for the columns so we can put one as input and another as output.
If you could confirm that this is possible, I can send my pcb to be built.
Thank you very much for your great work
No, this is not possible. For future reference: #906