I am building a new version of my teensy-based synth (here's v1: https://www.youtube.com/watch?v=MxDHKpysxYs), and I'm having some issues with keypresses when four or more keys are pressed at the same time.
This time I'm using a teensy 3.6 and the keybed from a Korg Microkey, which includes two 74HC138 multiplexers and a chip select signal to switch between the two. The PCB of the keyboard includes diodes, so ghost notes are not an issue. The 37 keys each have two switches, and I also got velocity-sensitivity working. Everything works fine when I press up to three keys, but when a fourth key is pressed, I get random readings from all pressed keys, which triggers a lot of note on and note off events.
Things I tried:
- Checked that all the used pins are not in use by the audio library (I'm using pins 0-4 as outputs for the chip selector and the three multiplexer inputs, and pins 24-31 as INPUT_PULLUP to read the switches in a matrix row).
- Commenting out the audio library from my project. I thought that could affect timing somehow, but that wasn't the issue.
- Increased the delay that addresses propagation in the multiplexer, that also didn't help.
- Power the keybed from the Vin pin of the teensy instead of using the 3.3V pin. The 74HC138 supports up to 6V, but somehow with that setup I don't get any keypresses detected.
After a good amount of debugging, I checked the voltage of the VIN of the keybed PCB (which is connected to the Teensy 3.3V pin), and I got a reading of 2.6V. Each time a key is pressed, that voltage drops a bit, and crosses 2.5V when four keys are pressed simultaneously.
What I'm now wondering is why the voltage is only 2.6V in the default state (the cables are only around 15cm long) and why the voltage drops with each key pressed? I'm less experienced on the electronics/hardware side, and I'm aware that this is a bit of a complicated setup, any ideas what could be going on or what to try next?
Here is my code as well:
This time I'm using a teensy 3.6 and the keybed from a Korg Microkey, which includes two 74HC138 multiplexers and a chip select signal to switch between the two. The PCB of the keyboard includes diodes, so ghost notes are not an issue. The 37 keys each have two switches, and I also got velocity-sensitivity working. Everything works fine when I press up to three keys, but when a fourth key is pressed, I get random readings from all pressed keys, which triggers a lot of note on and note off events.
Things I tried:
- Checked that all the used pins are not in use by the audio library (I'm using pins 0-4 as outputs for the chip selector and the three multiplexer inputs, and pins 24-31 as INPUT_PULLUP to read the switches in a matrix row).
- Commenting out the audio library from my project. I thought that could affect timing somehow, but that wasn't the issue.
- Increased the delay that addresses propagation in the multiplexer, that also didn't help.
- Power the keybed from the Vin pin of the teensy instead of using the 3.3V pin. The 74HC138 supports up to 6V, but somehow with that setup I don't get any keypresses detected.
After a good amount of debugging, I checked the voltage of the VIN of the keybed PCB (which is connected to the Teensy 3.3V pin), and I got a reading of 2.6V. Each time a key is pressed, that voltage drops a bit, and crosses 2.5V when four keys are pressed simultaneously.
What I'm now wondering is why the voltage is only 2.6V in the default state (the cables are only around 15cm long) and why the voltage drops with each key pressed? I'm less experienced on the electronics/hardware side, and I'm aware that this is a bit of a complicated setup, any ideas what could be going on or what to try next?
Here is my code as well:
Code:
// Possible key states
typedef enum {
KEY_IS_UP,
KEY_IS_DOWN,
KEY_IS_GOING_UP, // We increment the timer in this state
KEY_IS_GOING_DOWN, // We increment the timer in this state
} state_t;
typedef struct {
byte midi_note;
state_t state; // Bit fields
long t; // Microsecond timestamp
} Key;
const int multiplexAPin = 1;
const int multiplexBPin = 2;
const int multiplexCPin = 3;
const int chipSelect = 0;
int propdelay = 50;
const int inputs[] = {24, 25, 26, 27, 28, 29, 30, 31};
// The interval between the first and second switch while hitting keys with the
// highest velocity.
const float shortestInterval = 2000.0;
// Every time the interval between the first and second switch doubles, lower
// the midi velocity by this much:
const int velocityAttenuation = 20;
// Keep track of state.
Key keys[88];
bool isKeyBlack[] = {0, 1, 0, 1, 0, 0, 1, 0, 1, 0, 1, 0};
void setup() {
// put your setup code here, to run once:
pinMode(multiplexAPin, OUTPUT);
pinMode(multiplexBPin, OUTPUT);
pinMode(multiplexCPin, OUTPUT);
pinMode(chipSelect, OUTPUT);
for (int i = 0; i < 8; i++) {
pinMode(inputs[i], INPUT_PULLUP);
}
Serial.begin(9600);
delay(500);
// Init keys state
for ( int key = 0; key < 88; key++) {
keys[key].midi_note = 21 + key;
keys[key].t = 0;
keys[key].state = KEY_IS_UP;
}
digitalWrite(multiplexAPin, LOW);
digitalWrite(multiplexBPin, LOW);
digitalWrite(multiplexCPin, LOW);
}
void loop() {
for (int chip = 0; chip <= 1; chip++) {
digitalWrite(chipSelect, chip);
// 0
digitalWrite(multiplexCPin, LOW);
delayMicroseconds(propdelay);
readKeys(0 + chip * 8);
// 1
digitalWrite(multiplexAPin, HIGH);
delayMicroseconds(propdelay);
readKeys(1 + chip * 8);
// 3
digitalWrite(multiplexBPin, HIGH);
delayMicroseconds(propdelay);
readKeys(3 + chip * 8);
// 2
digitalWrite(multiplexAPin, LOW);
delayMicroseconds(propdelay);
readKeys(2 + chip * 8);
// 6
digitalWrite(multiplexCPin, HIGH);
delayMicroseconds(propdelay);
readKeys(6 + chip * 8);
// 7
digitalWrite(multiplexAPin, HIGH);
delayMicroseconds(propdelay);
readKeys(7 + chip * 8);
// 5
digitalWrite(multiplexBPin, LOW);
delayMicroseconds(propdelay);
readKeys(5 + chip * 8);
// 4
digitalWrite(multiplexAPin, LOW);
delayMicroseconds(propdelay);
readKeys(4 + chip * 8);
}
}
void readKeys(int note_offset) {
for (int i = 0; i < 4; i++) {
int key_index = 3 + note_offset * 4 + i;
bool switchA = !digitalRead(inputs[i * 2]);
bool switchB = !digitalRead(inputs[i * 2 + 1]);
if (switchA) {
if (switchB && keys[key_index].state == KEY_IS_GOING_DOWN) {
keys[key_index].state = KEY_IS_DOWN;
unsigned long t = micros() - keys[key_index].t;
if (t < shortestInterval) {
t = shortestInterval;
}
if (isBlackKey(keys[key_index].midi_note)) {
// Black keys are shorter, we need to compensate to get an even velocity.
t = t*2;
}
int velocity = 127 - log(t / shortestInterval) / log(2) * velocityAttenuation;
if (velocity < 0) {
velocity = 0;
}
usbMIDI.sendNoteOn(keys[key_index].midi_note, velocity, 0);
}
if (!switchB) {
if (keys[key_index].state == KEY_IS_UP) {
keys[key_index].state = KEY_IS_GOING_DOWN;
keys[key_index].t = micros();
}
else if (keys[key_index].state == KEY_IS_DOWN) {
keys[key_index].state = KEY_IS_GOING_UP;
}
}
}
else if (keys[key_index].state != KEY_IS_UP) {
keys[key_index].state = KEY_IS_UP;
usbMIDI.sendNoteOff(keys[key_index].midi_note, 127, 0);
}
}
}
bool isBlackKey(byte midi_note) {
return isKeyBlack[midi_note % 12];
}