hi everybody I am building a midi piano. When you press a button it should go down(noteon signal) on the piano and when you release button should go up(noteoff signal) well I managed to make that happen for 1 button however when I start pressing second or third button program starts acting weirdly such as releasing the first note or not sending note off sign even if I Release it. I am using 64 i/o expander (sx1509) from sparkfun and 16 button pad from sparkfun too. For the processor I am using teensy 3.1 However I am having difficulties to make my code run properly. Maybe it is the reason that I couldn't understood how i/o expander send data(like what type, how etc.)I will attach the code below. I think there is a mistake at func() function but I cant find it Thanks for your help
![]()
#include <Wire.h> // Wire.h library is required to use SX1509 lib
#include <sx1509_library.h> // Include the SX1509 library
const byte SX1509_ADDRESS = 0x3E; // SX1509 I2C address (00)
// MY teensy3.1 pin definitions
const byte resetPin = 1;
const byte interruptPin = 0;
// Here we'll define the number of rows and columns our keypad
// matrix has. Each of these values can be between 1 and 8.
// 4x4 = 16 buttons
const byte numRows = 4;
const byte numCols = 4;
// This key map will be used to define what keypress is sent to
// the computer when a key on the keypad is pressed.
int keyMap[numRows][numCols] = {
{50,70,3,4},
{80,90,6,7},
{9,10,13,11},
{25,1,53,55}};
// Create a new sx1509Class object
sx1509Class sx1509(SX1509_ADDRESS, resetPin, interruptPin);
void setup()
{
Serial.begin(9600);
// Must first initialize the sx1509:
sx1509.init();
// In order to use the keypad, the clock must first be
// configured. We can call configureClock() with the default
// parameters (2MHz internal oscillator, no clock in/out).
sx1509.configClock();
// Next call the keypad function with the number of rows
// and columns.
//sx1509.keypad(numRows, numCols); // Basic keypad init
// There are two optional parameters in the keypad method:
// sleepTime and scanTime. Each of these values can be between
// 0 and 7. If not set, these values default to 0 (sleep off
// scan time set to 1ms).
byte sleepTime = 7;
byte scanTime = 2; // Scan time per row
sx1509.keypad(numRows, numCols, sleepTime, scanTime); // Advanced keypad init
// We can also debounce the keypad inputs. The debounceConfig
// method takes one parameter. Similar to the scanTime it's a
// 3-bit value (0-7). This value must be <= scanTime!
byte debounceTime = 1; // The debounce config value
sx1509.debounceConfig(debounceTime);
}
//////////////////////////////////
//// Loop Variables /////////////
//////////////////////////////////
unsigned int keyData; // The raw data from the key press register
unsigned int previousKeyData = 0; // previously read raw data
byte activeRow; // The row of the button being pressed
byte activeColumn; // The column of the button being pressed
// These variables are used to emulate a key-hold. While the key
// is held down, there's a long delay before the second character
// is printed. Then a shorter delay between the remaining key presses
unsigned int holdCount = 0;
// This behavior is highly dependent on scanTime and debounceConfig
// which are set in the setup.
const byte holdCountMax = 25;
// These releaseCount variables
// The keypad engin on the SX1509 doesn't generate an interrupt
// when a key is relased. So we'll use this counter to generate
// releases.
unsigned int releaseCount = 0; // Our counter
unsigned int releaseCountMax = 100;// Top, in about milliseconds
int oldkey1=0;
int oldkey2=0;
int oldkey3=0;
int newkey1=0;
int newkey2=0;
int newkey3=0;
// The loop will poll the interrupt pin. If the pin
// is pulled low by the SX1509, we'll read the keypad data and
// sort it into row and column, and send the corresponding key
// press out to the computer.
void loop()
{
if (!digitalRead(interruptPin))
{
newkey1=func(); //I think problem is caused by somewhere here
newkey2=func();
newkey3=func();
if(oldkey1!=newkey1){
usbMIDI.sendNoteOn(newkey1, 99, 1);
usbMIDI.sendNoteOff(oldkey1, 99, 1);
oldkey1=newkey1;}
if(oldkey2!=newkey2){
usbMIDI.sendNoteOn(newkey2, 99, 1);
usbMIDI.sendNoteOff(oldkey2, 99, 1);
oldkey2=newkey2;}
if(oldkey3!=newkey3){
usbMIDI.sendNoteOn(newkey3, 99, 1);
usbMIDI.sendNoteOff(oldkey3, 99, 1);
oldkey3=newkey3;}
if (keyData != previousKeyData)
{
holdCount = 0;
}
releaseCount = 0;
// Set keyData as previousKeyData
previousKeyData = keyData;
}
// If no keys have been pressed we'll continuously increment
// releaseCount. Eventually creating a release, once the count
// hits the max.
releaseCount++;
if (releaseCount == releaseCountMax)
{
releaseCount = 0;
previousKeyData = 0;
usbMIDI.sendNoteOff(oldkey1, 99, 1);
usbMIDI.sendNoteOff(oldkey2, 99, 1);
usbMIDI.sendNoteOff(oldkey3, 99, 1);
oldkey1=0;
oldkey2=0;
oldkey3=0;
}
delay(1); // This gives releaseCountMax a more intuitive unit
}
// This function scours a byte and returns the position of the
// first byte it sees a 1. Great if our data bytes only have
// a single 1 in them! Should return 0-7 if it sees a 1, 255 otherwise
byte getBitPosition(byte dataByte)
{
for (int i=0; i<8; i++)
{
if (dataByte & (1<<i))
{
return i;
}
}
return 255; // Otherwise return an error
}
int func(){
keyData = sx1509.readKeyData();
activeRow = keyData & 0xFF; // The row is the lower 8-bits
activeColumn = keyData >> 8; // column is the upper 8-bits
activeRow = getBitPosition(activeRow);
activeColumn = getBitPosition(activeColumn);
return keyMap[activeRow][activeColumn];
}