Pages: [1] 2   Go Down
Author Topic: ARDUINO + musical instrument shield to make a Keyboard  (Read 6123 times)
0 Members and 1 Guest are viewing this topic.
0
Offline Offline
Newbie
*
Karma: 0
Posts: 7
Arduino rocks
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

Hello world  smiley

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.




Logged

Dubai, UAE
Offline Offline
Edison Member
*
Karma: 22
Posts: 1675
View Profile
WWW
 Bigger Bigger  Smaller Smaller  Reset Reset

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 -

http://rcarduino.blogspot.com/2012/10/arduino-modular-synthesizer-part-one.html

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

  Duane B
 

Logged


0
Offline Offline
Newbie
*
Karma: 0
Posts: 7
Arduino rocks
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

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 ?

Logged

Dubai, UAE
Offline Offline
Edison Member
*
Karma: 22
Posts: 1675
View Profile
WWW
 Bigger Bigger  Smaller Smaller  Reset Reset

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
Logged


Offline Offline
Newbie
*
Karma: 0
Posts: 7
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

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.


* Music Instrument Shield_Keyboard_Error.jpg (106.77 KB, 1012x683 - viewed 44 times.)
Logged

Dubai, UAE
Offline Offline
Edison Member
*
Karma: 22
Posts: 1675
View Profile
WWW
 Bigger Bigger  Smaller Smaller  Reset Reset

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
Code:
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
« Last Edit: October 23, 2012, 07:05:56 am by DuaneB » Logged


Gosport, UK
Offline Offline
Faraday Member
**
Karma: 21
Posts: 3113
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

Quote
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.
Logged

Dubai, UAE
Offline Offline
Edison Member
*
Karma: 22
Posts: 1675
View Profile
WWW
 Bigger Bigger  Smaller Smaller  Reset Reset

Quote
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
Logged


Offline Offline
Newbie
*
Karma: 0
Posts: 7
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

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.


* Music Instrument Shield_Keyboard_with_[i]_Error.jpg (66.41 KB, 1008x657 - viewed 39 times.)

* Music Instrument Shield_Keyboard_with_[i]_pin_button_Error.jpg (39.08 KB, 1018x475 - viewed 31 times.)
Logged

Dubai, UAE
Offline Offline
Edison Member
*
Karma: 22
Posts: 1675
View Profile
WWW
 Bigger Bigger  Smaller Smaller  Reset Reset

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

Logged


Offline Offline
Newbie
*
Karma: 0
Posts: 7
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

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

Offline Offline
Newbie
*
Karma: 0
Posts: 7
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

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.

Code:
inputPins[i]
Code:
buttonState[i]
Code:
lastButtonState[i]

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


For example,
In the void loop()

Code:
    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.
Logged

Dubai, UAE
Offline Offline
Edison Member
*
Karma: 22
Posts: 1675
View Profile
WWW
 Bigger Bigger  Smaller Smaller  Reset Reset

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

Duane B

Logged


Offline Offline
Newbie
*
Karma: 0
Posts: 7
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

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.

Code:
//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.
Logged

Dubai, UAE
Offline Offline
Edison Member
*
Karma: 22
Posts: 1675
View Profile
WWW
 Bigger Bigger  Smaller Smaller  Reset Reset

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 -

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

to

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

Duane B
Logged


Pages: [1] 2   Go Up
Jump to: