Sunday, September 23, 2018
Gadgets - Midi USB keyboard
I'm not a musician, but always fascinated with electronic music and portable music tools. Yes I could use an ipad.. but why not make a usb midi keyboard?
Midi keyboards take up a lot of room. Full keys take up 7 inches per octave. So I wanted to stagger two octaves to make a more packable dimension. Octave up/down keys are included to cover the 88 key range. There is no force sensing, just simple on off. Overall dimensions are ~ 6"x3"x1". Power comes from the usb connection to the box.
Teensyduino have a great line of boards programmable through arduino using more modern chips. They can all do direct usb out and pretend to be HID - so you can make plug and play mice, midi, keyboards etc.This is done with the $10 Teensy LC - a 32 bit machine with 26 io - way more juice than an arduino.
The keys use non-clicky cherry mx red knockoffs (I tried clicky blue ones but the noise was annoying). These are nice to use in 3D printing, they pop neatly into 14mm square holes.
Housing is all home 3D printed. Code is here:
/* Buttons to USB MIDI 2 octave kbd
You must select MIDI from the "Tools > USB Type" menu
To view the raw MIDI data on Linux: aseqdump -p "Teensy MIDI"
Adapted from Teensy example code in the public domain.
Buttons 0-23 are two octaves
Buttons 24 and 25 are octave up/down buttons
Button 24+25 is all sound off
Humphrey Gardner 2017
*/
#include <Bounce.h>
// the MIDI channel number to send messages
const int channel = 1;
int oct=0;
// Create Bounce objects for each button. The Bounce object
// automatically deals with contact chatter or "bounce", and
// it makes detecting changes very simple.
Bounce button0 = Bounce(0, 5);
Bounce button1 = Bounce(1, 5); // 5 = 5 ms debounce time
Bounce button2 = Bounce(2, 5); // which is appropriate for good
Bounce button3 = Bounce(3, 5); // quality mechanical pushbuttons
Bounce button4 = Bounce(4, 5);
Bounce button5 = Bounce(5, 5); // if a button is too "sensitive"
Bounce button6 = Bounce(6, 5); // to rapid touch, you can
Bounce button7 = Bounce(7, 5); // increase this time.
Bounce button8 = Bounce(8, 5);
Bounce button9 = Bounce(9, 5);
Bounce button10 = Bounce(10, 5);
Bounce button11 = Bounce(11, 5);
Bounce button12 = Bounce(12, 5);
Bounce button13 = Bounce(13, 5);
Bounce button14 = Bounce(14, 5);
Bounce button15 = Bounce(15, 5);
Bounce button16 = Bounce(16, 5);
Bounce button17 = Bounce(17, 5);
Bounce button18 = Bounce(18, 5);
Bounce button19 = Bounce(19, 5);
Bounce button20 = Bounce(20, 5);
Bounce button21 = Bounce(21, 5);
Bounce button22 = Bounce(22, 5);
Bounce button23 = Bounce(23, 5);
Bounce button24 = Bounce(24, 5);
Bounce button25 = Bounce(25, 5);
Bounce button26 = Bounce(26, 5);
void setup() {
//Pullup removes need for external components
pinMode(0, INPUT_PULLUP);
pinMode(1, INPUT_PULLUP);
pinMode(2, INPUT_PULLUP);
pinMode(3, INPUT_PULLUP);
pinMode(4, INPUT_PULLUP);
pinMode(5, INPUT_PULLUP);
pinMode(6, INPUT_PULLUP);
pinMode(7, INPUT_PULLUP);
pinMode(8, INPUT_PULLUP);
pinMode(9, INPUT_PULLUP);
pinMode(10, INPUT_PULLUP);
pinMode(11, INPUT_PULLUP);
pinMode(12, INPUT_PULLUP);
pinMode(13, INPUT_PULLUP);
pinMode(14, INPUT_PULLUP);
pinMode(15, INPUT_PULLUP);
pinMode(16, INPUT_PULLUP);
pinMode(17, INPUT_PULLUP);
pinMode(18, INPUT_PULLUP);
pinMode(19, INPUT_PULLUP);
pinMode(20, INPUT_PULLUP);
pinMode(21, INPUT_PULLUP);
pinMode(22, INPUT_PULLUP);
pinMode(23, INPUT_PULLUP);
pinMode(24, INPUT_PULLUP);
pinMode(25, INPUT_PULLUP);
pinMode(26, INPUT_PULLUP);
}
void loop() {
// Update all the buttons. There should not be any long
// delays in loop(), so this runs repetitively at a rate
// faster than the buttons could be pressed and released.
button0.update();
button1.update();
button2.update();
button3.update();
button4.update();
button5.update();
button6.update();
button7.update();
button8.update();
button9.update();
button10.update();
button11.update();
button12.update();
button13.update();
button14.update();
button15.update();
button16.update();
button17.update();
button18.update();
button19.update();
button20.update();
button21.update();
button22.update();
button23.update();
button24.update();
button25.update();
button26.update();
// Check each button for "rising" edge.
// Send a MIDI Note On message when each button presses
// Update the Joystick buttons only upon changes.
// rising = high (not pressed - voltage from pullup resistor)
// to low (pressed - button connects pin to ground)
if (button0.fallingEdge()) {
usbMIDI.sendNoteOn(60+oct, 99, channel); // 60 = C4
}
if (button1.fallingEdge()) {
usbMIDI.sendNoteOn(61+oct, 99, channel); // 61 = C#4
}
if (button2.fallingEdge()) {
usbMIDI.sendNoteOn(62+oct, 99, channel); // 62 = D4
}
if (button3.fallingEdge()) {
usbMIDI.sendNoteOn(63+oct, 99, channel); // 63 = D#4
}
if (button4.fallingEdge()) {
usbMIDI.sendNoteOn(64+oct, 99, channel); // 64 = E4
}
if (button5.fallingEdge()) {
usbMIDI.sendNoteOn(65+oct, 99, channel); // 65 = F4
}
if (button6.fallingEdge()) {
usbMIDI.sendNoteOn(66+oct, 99, channel); // 66 = F#4
}
if (button7.fallingEdge()) {
usbMIDI.sendNoteOn(67+oct, 99, channel); // 67 = G4
}
if (button8.fallingEdge()) {
usbMIDI.sendNoteOn(68+oct, 99, channel); // 68 = G#4
}
if (button9.fallingEdge()) {
usbMIDI.sendNoteOn(69+oct, 99, channel); // 69 = A5
}
if (button10.fallingEdge()) {
usbMIDI.sendNoteOn(70+oct, 99, channel); // 70 = A#5
}
if (button11.fallingEdge()) {
usbMIDI.sendNoteOn(71+oct, 99, channel); // 71 = B5
}
if (button12.fallingEdge()) {
usbMIDI.sendNoteOn(72+oct, 99, channel); // 72 = D5
}
if (button13.fallingEdge()) {
usbMIDI.sendNoteOn(73+oct, 99, channel); // 73 = D#5
}
if (button14.fallingEdge()) {
usbMIDI.sendNoteOn(74+oct, 99, channel); // 74 = E4
}
if (button15.fallingEdge()) {
usbMIDI.sendNoteOn(75+oct, 99, channel); // 75 = F4
}
if (button16.fallingEdge()) {
usbMIDI.sendNoteOn(76+oct, 99, channel); // 76 = F#4
}
if (button17.fallingEdge()) {
usbMIDI.sendNoteOn(77+oct, 99, channel); // 77 = G4
}
if (button18.fallingEdge()) {
usbMIDI.sendNoteOn(78+oct, 99, channel); // 78 = G#4
}
if (button19.fallingEdge()) {
usbMIDI.sendNoteOn(79+oct, 99, channel); // 79 = A5
}
if (button20.fallingEdge()) {
usbMIDI.sendNoteOn(80+oct, 99, channel); // 80 = A#5
}
if (button21.fallingEdge()) {
usbMIDI.sendNoteOn(81+oct, 99, channel); // 81 = B5
}
if (button22.fallingEdge()) {
usbMIDI.sendNoteOn(82+oct, 99, channel); // 82 = C5
}
if (button23.fallingEdge()) {
usbMIDI.sendNoteOn(83+oct, 99, channel); // 83 = C#5
}
// Octave up/down buttons handler
if (button24.fallingEdge())
{ //up an octave button
if(oct<48){
oct+=12;}
if(digitalRead(25)==0){
oct=0;
for (int i =1;i<132;i++){
usbMIDI.sendNoteOff(i, 0, channel);
}
} //if both buttons, reset octaves and sound
}
if (button25.fallingEdge()) { //down an octave button
if(oct>-48){
oct-=12;
}
}
// Check each button for "rising" edge
// Send a MIDI Note Off message when each button releases
// For many types of projects, you only care when the button
// is pressed and the release isn't needed.
// rising = low (pressed - button connects pin to ground)
// to high (not pressed - voltage from pullup resistor)
if (button0.risingEdge()) {
usbMIDI.sendNoteOff(60+oct, 0, channel); // 60 = C4
}
if (button1.risingEdge()) {
usbMIDI.sendNoteOff(61+oct, 0, channel); // 61 = C#4
}
if (button2.risingEdge()) {
usbMIDI.sendNoteOff(62+oct, 0, channel); // 62 = D4
}
if (button3.risingEdge()) {
usbMIDI.sendNoteOff(63+oct, 0, channel); // 63 = D#4
}
if (button4.risingEdge()) {
usbMIDI.sendNoteOff(64+oct, 0, channel); // 64 = E4
}
if (button5.risingEdge()) {
usbMIDI.sendNoteOff(65+oct, 0, channel); // 65 = F4
}
if (button6.risingEdge()) {
usbMIDI.sendNoteOff(66+oct, 0, channel); // 66 = F#4
}
if (button7.risingEdge()) {
usbMIDI.sendNoteOff(67+oct, 0, channel); // 67 = G4
}
if (button8.risingEdge()) {
usbMIDI.sendNoteOff(68+oct, 0, channel); // 68 = G#4
}
if (button9.risingEdge()) {
usbMIDI.sendNoteOff(69+oct, 0, channel); // 69 = A5
}
if (button10.risingEdge()) {
usbMIDI.sendNoteOff(70+oct, 0, channel); // 70 = A#5
}
if (button11.risingEdge()) {
usbMIDI.sendNoteOff(71+oct, 0, channel); // 71 = B5
}
if (button12.risingEdge()) {
usbMIDI.sendNoteOff(72+oct, 99, channel); // 72 = D4
}
if (button13.risingEdge()) {
usbMIDI.sendNoteOff(73+oct, 99, channel); // 73 = D#4
}
if (button14.risingEdge()) {
usbMIDI.sendNoteOff(74+oct, 99, channel); // 74 = E4
}
if (button15.risingEdge()) {
usbMIDI.sendNoteOff(75+oct, 99, channel); // 75 = F4
}
if (button16.risingEdge()) {
usbMIDI.sendNoteOff(76+oct, 99, channel); // 76 = F#4
}
if (button17.risingEdge()) {
usbMIDI.sendNoteOff(77+oct, 99, channel); // 77 = G4
}
if (button18.risingEdge()) {
usbMIDI.sendNoteOff(78+oct, 99, channel); // 78 = G#4
}
if (button19.risingEdge()) {
usbMIDI.sendNoteOff(79+oct, 99, channel); // 79 = A5
}
if (button20.risingEdge()) {
usbMIDI.sendNoteOff(80+oct, 99, channel); // 80 = A#5
}
if (button21.risingEdge()) {
usbMIDI.sendNoteOff(81+oct, 99, channel); // 81 = B5
}
if (button22.risingEdge()) {
usbMIDI.sendNoteOff(82+oct, 99, channel); // 82 = C4
}
if (button23.risingEdge()) {
usbMIDI.sendNoteOff(83+oct, 99, channel); // 83 = C#4
}
// MIDI Controllers should discard incoming MIDI messages.
// http://forum.pjrc.com/threads/24179-Teensy-3-Ableton-Analog-CC-causes-midi-crash
while (usbMIDI.read()) {
// ignore incoming messages
}
}
Subscribe to:
Posts (Atom)
