hi guys!
searching on the web, i found some projects for turning a toy piano into a MIDI device, to send digital signals to the pc
i post the video link for let you know this project: https://www.youtube.com/watch?v=lXX8v-ZW6Tk
all is based on a scan matrix of the piano keys, so we need to program arduino for have a midi output when a piano key is pressed or relased
now i explain my problem:
i have an original arduino uno board, and a casio piano with 49 keys, divided by 15 wires (with a scan matrix of 6 columns and 9 rows - like this photo)
(consider only the number of wires written by pen, and the notes highlighted)
in the video tutorial, he use the shift register technique, using the 74hc595 chip, for demoltiply the columns number and use only the digital inputs of arduino
i have edited the code by adapting it to my piano, the output worked, and the pc receive the midi signals, but the problem is that the notes i press on the piano aren't the same that arrive on the pc (for exaple if i press the C note on piano, my pc receive a F note)
that's the code i used:
define NUM_ROWS 9
#define NUM_COLS 6#define NOTE_ON_CMD 0x90
#define NOTE_OFF_CMD 0x80
#define NOTE_VELOCITY 127//MIDI baud rate
#define SERIAL_RATE 31250// Pin Definitions
// Row input pins
const int row1Pin = 2;
const int row2Pin = 3;
const int row3Pin = 4;
const int row4Pin = 5;
const int row5Pin = 6;
const int row12Pin = 7;
const int row13Pin = 8;
const int row14Pin = 9;
const int row15Pin = 10;// 74HC595 pins
const int dataPin = 11;
const int latchPin = 12;
const int clockPin = 13;boolean keyPressed[NUM_ROWS][NUM_COLS];
uint8_t keyToMidiMap[NUM_ROWS][NUM_COLS];// bitmasks for scanning columns
int bits[] =
{
B11111110,
B11111101,
B11111011,
B11110111,
B11101111,
B11011111,
B10111111,
B01111111
};void setup()
{
int note = 36;for(int colCtr = 0; colCtr < NUM_COLS; ++colCtr)
{
for(int rowCtr = 0; rowCtr < NUM_ROWS; ++rowCtr)
{
keyPressed[rowCtr][colCtr] = false;
keyToMidiMap[rowCtr][colCtr] = note;
note++;
}
}// setup pins output/input mode
pinMode(dataPin, OUTPUT);
pinMode(clockPin, OUTPUT);
pinMode(latchPin, OUTPUT);pinMode(row1Pin, INPUT);
pinMode(row2Pin, INPUT);
pinMode(row3Pin, INPUT);
pinMode(row4Pin, INPUT);
pinMode(row5Pin, INPUT);
pinMode(row12Pin, INPUT);
pinMode(row13Pin, INPUT);
pinMode(row14Pin, INPUT);
pinMode(row15Pin, INPUT);Serial.begin(SERIAL_RATE);
}void loop()
{
for (int colCtr = 0; colCtr < NUM_COLS; ++colCtr)
{
//scan next column
scanColumn(colCtr);//get row values at this column
int rowValue[NUM_ROWS];
rowValue[0] = !digitalRead(row1Pin);
rowValue[1] = !digitalRead(row2Pin);
rowValue[2] = !digitalRead(row3Pin);
rowValue[3] = !digitalRead(row4Pin);
rowValue[4] = !digitalRead(row5Pin);
rowValue[5] = !digitalRead(row12Pin);
rowValue[6] = !digitalRead(row13Pin);
rowValue[7] = !digitalRead(row14Pin);
rowValue[8] = !digitalRead(row15Pin);// process keys pressed
for(int rowCtr=0; rowCtr<NUM_ROWS; ++rowCtr)
{
if(rowValue[rowCtr] != 0 && !keyPressed[rowCtr][colCtr])
{
keyPressed[rowCtr][colCtr] = true;
noteOn(rowCtr,colCtr);
}
}// process keys released
for(int rowCtr=0; rowCtr<NUM_ROWS; ++rowCtr)
{
if(rowValue[rowCtr] == 0 && keyPressed[rowCtr][colCtr])
{
keyPressed[rowCtr][colCtr] = false;
noteOff(rowCtr,colCtr);
}
}
}
}void scanColumn(int colNum)
{
digitalWrite(latchPin, LOW);if(0 <= colNum && colNum <= 7)
{
shiftOut(dataPin, clockPin, MSBFIRST, bits[colNum]); //left sr
}
else
{
shiftOut(dataPin, clockPin, MSBFIRST, bits[colNum-8]); //right sr
}digitalWrite(latchPin, HIGH);
}void noteOn(int row, int col)
{
Serial.write(NOTE_ON_CMD);
Serial.write(keyToMidiMap[row][col]);
Serial.write(NOTE_VELOCITY);
}void noteOff(int row, int col)
{
Serial.write(NOTE_OFF_CMD);
Serial.write(keyToMidiMap[row][col]);
Serial.write(NOTE_VELOCITY);
}
in my opinion the problem is in the managment of the shift register (i use only one, unlike twos used in the video project, and probably i do something wrong in the code)
please can you help me to find the error?
this a photo of the circuit:
the electrical connections are all correct, the scan matrix is correct because i checked it on the piano user manual and i have tested it with a multimeter
PS:
i found that the analog inputs of arduino can be used as digital one, simply call him in this mode:
A0 = pin14
A1 = pin15
A2 = pin16
A3 = pin 17
A4 = pin18
A5 = pin19
so, is possible to create a program without using the shift register, but using only the arduino imputs (in this case are enough for all the 15 wires of my piano)
by you, in this mode, how i can program arduino for send midi signals to the pc?