ARDUINO + musical instrument shield to make a Keyboard

Hello world :slight_smile:

After searching for hours a way to make a keyboard from Arduino and MI shield from sparkfun, and with the helps of few people, I finally get my program.
It will probably seems a bit simple for advanced users, but It was quite a lot of work for me to make it works as a beginner. I thought it could be great to save time for other beginners if I share this program in this topic, so here we go , but before, if advanced users have some suggestions to improve it, you are more than welcome to contact me as I’m waiting to learn more :

#include <SoftwareSerial.h>
SoftwareSerial mySerial(2, 3); //Soft TX on 3, we don’t use RX in this code

int inputPins = {5,6,7,8,9,10,11,12,13};
int note={72,74,76,77,79,81,83,84,86};
int pinCount = 9;

int buttonState[9];
int lastButtonState[9];

byte resetMIDI = 4; //Tied to VS1053 Reset line
int instrument = 13;

void setup() {

//Setup soft serial for MIDI control
mySerial.begin(31250);

for(int i=0; i<pinCount; i++){
pinMode(inputPins_, OUTPUT);//pinMode(outputPins*, OUTPUT);_
_ digitalWrite(inputPins, LOW);// this enables the pull up resistors to reduce noise*
pinMode(inputPins*, INPUT);
}
//Reset the VS1053*

* digitalWrite(resetMIDI, LOW);
delay(100);
digitalWrite(resetMIDI, HIGH);
delay(100);*_

* talkMIDI(0xB0, 0x07, 126); //0xB0 is channel message, set channel volume to near max (127)*
* talkMIDI(0xB0, 0, 0x79); //Default bank GM1*
* talkMIDI(0xC0, instrument, 0); //Set instrument number. 0xC0 is a 1 data byte command*
}
void loop() {

for (int i=0; i<pinCount; i++){
buttonState = digitalRead(inputPins*);*
* delay(1);*

if (buttonState != lastButtonState*) { *

_ if (buttonState == HIGH) {
noteOn(0,note,100);
}_

* }*
lastButtonState = buttonState*;*

* }*
}
//Send a MIDI note-on message. Like Pressing a piano key
void noteOn(byte channel, byte note, byte attack_velocity) {
* talkMIDI( (0x90 | channel), note, attack_velocity);
_}
//Send a MIDI note-off message. Like releasing a piano key*

void noteOff(byte channel, byte note, byte release_velocity) {
* talkMIDI( (0x80 | channel), note, release_velocity);*
}
//Plays a MIDI note. Doesn’t check to see that cmd is greater than 127, or that data values are less than 127
void talkMIDI(byte cmd, byte data1, byte data2) {
* mySerial.write(cmd);
mySerial.write(data1);
//Some commands only have one data byte. All cmds less than 0xBn have 2 data bytes*

* //(sort of: http://253.ccarh.org/handout/midiprotocol/)
if( (cmd & 0xF0) <= 0xB0)
mySerial.write(data2);
}*

Here is a link to see it working : http://www.youtube.com/watch?v=jNWv-yBQ84Y&feature=youtu.be
I also wrote the program to have this keyboard working with the Touch pad shield from Sparkfun. If people are interested , don’t hesitate to ask.
All the best,
Plankton._

Hi,
I like how you used a single header pin as the keys, I wanted to make something like a stylophone interface but this looks a lot easier.

I assume that you are sending midi messages from the Arduino to the keyboard ?

Have you tried going the other way midi into Ardiuno ?

I have bought a five dollar keyboard that I plan to drive some of my recent synth experiments with -

I am considering getting a simple midi keyboard to drive them with instead - the five dollar keyboard is pretty nasty.

Duane B

Hi Duane,

My keys are simple switches... then, as you guessed, the Arduino send midi data to the shield to play notes.
Regarding your case, have you take in consideration the possibility to connect a PS/2 keyboard to your Arduino, using the appropritate library ?

Hi,
The PS2 is a good idea, it looks like midi into Arduino is give a few people problems, I have already broken out the key scanning matrix from the 5 dollar keyboard so I will go with this for now.

Thanks

Duane B

rcarduino.blogspot.com

MusicIntrument_Keyboard_Error

Hello.
Thank you very much for posting your Arduino Music Instrument_Keyboard.
I pasted your program on Arduino 1.01 and verified it.

Then I get lots of error messages as I post the image here.

For example,
In the void setup()
The line
" pinMode(inputPins, OUTPUT);//pinMode(outputPins, OUTPUT); "
is highlighted and there’s a message as
" invalid conversion from ‘int*’ to ‘uint8_t’ "

I cannot understand the error messages, because your code seems ok.
If I click “Upload” button, the result is the same.

What is wrong?
I’m looking forward your reply.

P.S.
The title name of the file is “MusicIntrument_Keyboard.ino”
I use Arduino Uno R2 and I use Windows XP.
Board and Serial port( Com4 ) is correctly setup on Arduino 1.01.

Hi,
inputPins is an array but the array access operator is missing throughout the pasted code.

To fix this, whereever you see inputPins replace it with inputsPins[i] this will access specific members of the array rather than the array base pointer. If none of that makes sense search the web for C Array or read this -

http://www.arduino.cc/en/Reference/Array

Duane B

rcarduino.blogspot.com

inputPins is an array but the array access operator is missing throughout the pasted code.

This is why we have code tags. It stops the forum software converting array indexes into italic tags.

This is why we have code tags. It stops the forum software converting array indexes into italic tags.

Oops. I only added code tags after rereading my own response and seeing no 's didn't occur to me that I had put them in and that they were the reason for the italics, same for the OP I guess.
Back on topic -
I have been messing around with my hacked keyboard, its still monophonic but by racing through the active tones at varying speeds I get a basic chord effect or arppegio's either way the monophonic version is much more interesting than I expected.
I will share the schematic and code shortly, the code should be easy enough to adapt to another instrument if the OP wants to experiment.
Duane B

Thank you very much for your comment.
I replaced inputsPins with inputsPins*.*
The number of errors has decreased.
But still there were 6 error messages as I post the image-1 here.
For example,
In the void loop()
The line
_ buttonState = digitalRead(inputPins*);_
is highlighted and there’s a message as
_
" incompatible types in assignment of ‘int’ to ‘int[9]’ "_
_So I also added * to all “buttonState” and “lastButtonState”
The number of errors has decreased further.
But still there were 3 error messages as I post the image-2 here.
For example,
In the void loop()
if (buttonState == HIGH) {
noteOn(0,note,100);

The line
* noteOn(0,note,100);
is highlighted and there’s a message as
" invalid conversion from ‘int’ to ‘byte’ "
In my understanding, talkMIDI() is a message with 3 bytes.
How do you define the data type of noteOn()?
I feel I’m getting better with your help.
I’m looking forward your reply.
Thank you very much._


*

Why not post your code and using the code tag, its the # on the menu above, it stops the forum software from replacing your array index with italics (thanks dxw00d for point this out) ?

Duane B

rcarduino.blogspot.com

Very sorry. I could not understand how to use the code tag, # on the menu.
I'll post in a day.

This is a re-post with a code tag.
This time is the first time to use code tags. If I'm wrong, please tell me.

MusicIntrument_Keyboard Errors
Thank you very much for your comment.

I replaced "inputsPins" ,"buttonState" "lastButtonState" as follows.

inputPins[i]
buttonState[i]
lastButtonState[i]

The number of errors has decreased.
But still there are 3 error messages.

For example,
In the void loop()

    if (buttonState[i] == HIGH) {                      
    noteOn(0,note,100);

The line
noteOn(0,note,100);
is highlighted and there are messages as
" invalid conversion from 'int' to 'byte' "
" initializing argument 2 of 'noteOn(byte,byte,byte)' "

In my understanding, talkMIDI() is a message with 3 bytes.
How do you define the data type of noteOn()?

I feel I'm getting better with your help.

I'm looking forward your reply.
Thank you very much.

Hi,
I meant the whole code, its not possible to figure out from snippets of code.

Duane B

MusicIntrument_Keyboard Errors

Sorry!

I pasted this topic’s first contributer’s ( Plankton’s ) code and added array suffixes to “inputsPins” ,“buttonState” “lastButtonState”

The full code is as follows.

//Music Instrument Shield_Keyboard  renew
//MusicIntrument_Keyboard
// Music Instrument Shield_Keyboard

#include <SoftwareSerial.h>
SoftwareSerial mySerial(2, 3); //Soft TX on 3, we don't use RX in this code

int inputPins[] = {5,6,7,8,9,10,11,12,13};
int note[]={72,74,76,77,79,81,83,84,86};
int pinCount = 9;

int buttonState[9];
int lastButtonState[9];  

byte resetMIDI = 4; //Tied to VS1053 Reset line
int instrument = 13;

void setup() {

  //Setup soft serial for MIDI control
  mySerial.begin(31250);
  
  for(int i=0; i<pinCount; i++){
  pinMode(inputPins[i], OUTPUT);//pinMode(outputPins, OUTPUT);
  digitalWrite(inputPins[i], LOW);// this enables the pull up resistors to reduce noise
  pinMode(inputPins[i], INPUT);
  }


  //Reset the VS1053
  digitalWrite(resetMIDI, LOW);
  delay(100);
  digitalWrite(resetMIDI, HIGH);
  delay(100);
 
  talkMIDI(0xB0, 0x07, 126); //0xB0 is channel message, set channel volume to near max (127)
  talkMIDI(0xB0, 0, 0x79); //Default bank GM1
  talkMIDI(0xC0, instrument, 0); //Set instrument number. 0xC0 is a 1 data byte command

}

void loop() {
  
for (int i=0; i<pinCount; i++){

  buttonState[i] = digitalRead(inputPins[i]);
  delay(1);
  
  if (buttonState[i] != lastButtonState[i]) {       
    
    if (buttonState[i] == HIGH) {                      
    noteOn(0,note,100);                      
    } 
    
  }

  lastButtonState[i] = buttonState[i];
  
  }
}

//Send a MIDI note-on message.  Like Pressing a piano key
void noteOn(byte channel, byte note, byte attack_velocity) {
  talkMIDI( (0x90 | channel), note, attack_velocity);
}

//Send a MIDI note-off message.  Like releasing a piano key
void noteOff(byte channel, byte note, byte release_velocity) {
  talkMIDI( (0x80 | channel), note, release_velocity);
}

//Plays a MIDI note. Doesn't check to see that cmd is greater than 127, or that data values are less than 127
void talkMIDI(byte cmd, byte data1, byte data2) {
  mySerial.write(cmd);
  mySerial.write(data1);

  //Some commands only have one data byte. All cmds less than 0xBn have 2 data bytes 
  //(sort of: http://253.ccarh.org/handout/midiprotocol/)
  if( (cmd & 0xF0) <= 0xB0)
    mySerial.write(data2);

}

Thank you very much for your comments and am looking forward to them.

Hi,
I wanted to see the full code to make sure there are no values that would not fit into a byte (values > 255). There aren’t any so you can change -

int inputPins[] = {5,6,7,8,9,10,11,12,13};
int note[]={72,74,76,77,79,81,83,84,86};

to

byte inputPins[] = {5,6,7,8,9,10,11,12,13};
byte note[]={72,74,76,77,79,81,83,84,86};

Duane B

MusicIntrument_Keyboard Errors

Thank you very much for your comments.

Your suggestion such as declaration of “byte note” seemed reasonable.
However, there still exist errors.

The line
noteOn(0,note,100);
is still highlighted and there are messages as
" invalid conversion from ‘byte’ to ‘byte’ "
" initializing argument 2 of void ‘noteOn(byte,byte,byte)’ "

The full code is as follows.

//Music Instrument Shield_Keyboard  renew
//MusicIntrument_Keyboard
// Music Instrument Shield_Keyboard

#include <SoftwareSerial.h>
SoftwareSerial mySerial(2, 3); //Soft TX on 3, we don't use RX in this code

byte inputPins[] = {5,6,7,8,9,10,11,12,13};
byte note[]={72,74,76,77,79,81,83,84,86};
int pinCount = 9;

int buttonState[9];
int lastButtonState[9];  

byte resetMIDI = 4; //Tied to VS1053 Reset line
int instrument = 13;

void setup() {

  //Setup soft serial for MIDI control
  mySerial.begin(31250);
  
  for(int i=0; i<pinCount; i++){
  pinMode(inputPins[i], OUTPUT);//pinMode(outputPins, OUTPUT);
  digitalWrite(inputPins[i], LOW);// this enables the pull up resistors to reduce noise
  pinMode(inputPins[i], INPUT);
  }


  //Reset the VS1053
  digitalWrite(resetMIDI, LOW);
  delay(100);
  digitalWrite(resetMIDI, HIGH);
  delay(100);
 
  talkMIDI(0xB0, 0x07, 126); //0xB0 is channel message, set channel volume to near max (127)
  talkMIDI(0xB0, 0, 0x79); //Default bank GM1
  talkMIDI(0xC0, instrument, 0); //Set instrument number. 0xC0 is a 1 data byte command

}

void loop() {
  
for (int i=0; i<pinCount; i++){

  buttonState[i] = digitalRead(inputPins[i]);
  delay(1);
  
  if (buttonState[i] != lastButtonState[i]) {       
    
    if (buttonState[i] == HIGH) {                      
    noteOn(0,note,100);                      
    } 
    
  }

  lastButtonState[i] = buttonState[i];
  
  }
}

//Send a MIDI note-on message.  Like Pressing a piano key
void noteOn(byte channel, byte note, byte attack_velocity) {
  talkMIDI( (0x90 | channel), note, attack_velocity);
}

//Send a MIDI note-off message.  Like releasing a piano key
void noteOff(byte channel, byte note, byte release_velocity) {
  talkMIDI( (0x80 | channel), note, release_velocity);
}

//Plays a MIDI note. Doesn't check to see that cmd is greater than 127, or that data values are less than 127
void talkMIDI(byte cmd, byte data1, byte data2) {
  mySerial.write(cmd);
  mySerial.write(data1);

  //Some commands only have one data byte. All cmds less than 0xBn have 2 data bytes 
  //(sort of: http://253.ccarh.org/handout/midiprotocol/)
  if( (cmd & 0xF0) <= 0xB0)
    mySerial.write(data2);

}

It seems difficult but welcomes any suggestions.

  if (buttonState[i] != lastButtonState[i]) {       
    
    if (buttonState[i] == HIGH) {                      
    noteOn(0,note[i],100);                      
    } 
    
  }

Spot the difference.

It compiles for me with this change - if you can spot it.

Duane B

MusicInstrument_Keyboard -- No more Errors

Wow! Thank you very much for all of your suggestions.
The program is finally verified and the program is running with beautiful sounds.

As "note" is also an array, there should has been a suffix.
I did not notice it.
Once again, thank you very much.

Now I'm trying to make an infrared keyboards.
About 6 Infrared beams(38KHz) are emitted and if a peson blocks a beam, the receiver gives a 5V voltage.
This is the signal for the "inputPins" of this "ARDUINO + musical instrument shield."

I'll post within a few days.

Thank you.

DuaneB was correct... your note is an array of integers so you must identify the index... that is, which note you want to generate...

To play: 79 use: note[4]....

You've probably already worked that out... :wink:

Congratulations Plankton,
I have a very similar project and I am eager to follow your footsteps. Thank you for posting your results!
Besides being able to generate sounds directly with sparkfun MI interface, or alternatively to it, I want my keyboard to send MIDI data to the computer (PC) with the help of the MIDI library.
I am not quite sure though how to receive the data on the PC side.
In particular, I need to find a program (possibly free, for the time being, while I am experimenting) that receive the MIDI data from the Arduino and plays them right away (with the WIndows GM synth table or something else). So far, no luck.
Do you have any hint or advice to point me the right way?

Thanks

Luca