Lighting musical keys [Example 1]

I’m working on a musical instrument that turn on an Led based on with key in struck. 16 keys on on multiplexer and 16 LED on on port expander.
based on two project in the arduino playground.

I’m trying to add the statements
noteON = LedON
noteOFF =LedOFF

Midi_footsteps is an exact example to what I’m trying to accomplish
this is how Mike did it http://www.thebox.myzen.co.uk/Hardware/MIDI_Footsteps_files/Footsteps%20Software.zip it’s homepage MIDI Footsteps

Can anyone help implement the port expander and LED’s section of the about project into my sketch which is attached.

the musical instrument part of the my mod is based on YAAMI-Drum which could be found here http://sourceforge.net/projects/yaamidrum/

drumYledapril12.pde (10.3 KB)

Below are the parts that I’ve identified has to do with the i2c expander and LED. Now constructing the for statement and placing it at the right point in the program is still a little sketchy.

// Defines
// I2C registers
#define I2CregisterInput 0
#define I2CregisterOutput 2
#define I2CregisterPolarity 4
#define I2CregisterConfig 6
#define I2CregisterInterrupt 8
#define I2CregisterExpander 10
// I2C device addresses
#define ledAddress   (0x20 | 0x0)     // address of trigger LED indicators output
// Control Switch device bit masks
#define ddrTrigger 0x00000     // data direction register for trigger indictor LEDs

int lastLedVal;
#include <Wire.h>
   lastLedVal = 0;                       //leds off
 // Setup I2C devices
   Wire.begin();                      // start the I2C interface
   // Initilise registers 
   gpio_write(ledAddress, ddrTrigger, I2CregisterConfig);   // Make into outputs
   gpio_write(ledAddress, 0, I2CregisterInput);            // turn them all off

  int ledVal = 0;
  int ledMask = 1;
  for(int i=0; i<16; i++){
    if(currentState[i] < threshold) ledVal |= ledMask;   // add a 1 in the position of sensors under threshold
     ledMask = ledMask << 1;   // less than on So LEDs are off
   }
   if(lastLedVal != ledVal) {   // something has changed
   ledMask = 1;                     // LED ON
     for(int i=0; i<16; i++){
       if((ledMask & ledVal) != (ledMask & lastLedVal)){
         if((ledMask & ledVal) == 0) {
           // note off
         controlSend(0x80, control[i], 0x00);   // turn off control message
//noTone(8);
digitalWrite(ledPin,LOW);  
           }
         else{
           // note on
           controlSend(0x90, control[i], currentState[i]>>3);  // turn on control message
//tone(8, notes[i], 20);
digitalWrite (ledPin,HIGH);
           }
       }
       ledMask = ledMask << 1;  // Led HIGH
     }
     // Update the trigger LEDs
       gpio_writeByteInverse(ledAddress, ledVal, I2CregisterInput);   // update LEDs
   }
   lastLedVal = ledVal;        // record current state of LEDs and MIDI notes / messages
   digitalWrite(ledPin,LOW);
}           

void gpio_write(int address, int data, int reg) {
  //  Send output register address
  Wire.beginTransmission(address);
  Wire.send(reg);
  //  Connect to device and send two bytes
  Wire.send(0xff & data);  //  low byte
  Wire.send(data >> 8);    //  high byte
  Wire.endTransmission();
}

void gpio_writeByteInverse(int address, int data, int reg) {
  //  Send output register address
  Wire.beginTransmission(address);
  Wire.send(reg);
  //  Connect to device and send two bytes
    Wire.send(data >> 8);    //  high byte
    Wire.send(0xff & data);  //  low byte
  Wire.endTransmission();
}

int gpio_read(int address) {
  int data = 0;
 //  Send input register address
  Wire.beginTransmission(address);
  Wire.send(I2CregisterInput);
  Wire.endTransmission();
  //  Connect to device and request two bytes
 // Wire.beginTransmission(address);
  Wire.requestFrom(address, 2);
 if (!Wire.available()) { } // do nothing until data arrives
    data = Wire.receive();

 if (!Wire.available()) { } // do nothing until data arrives
    data |= Wire.receive() << 8;
  Wire.endTransmission();
  return data;
}

SpikenzieLabs Drumkit

SpikenzieLabs offers a pre-written code that looks like this:

/
// DESCRIPTION:
// Arduino analog input used to sense piezo drum hits then sent serialy to processing.

//*******************************************************************************************************************
// User settable variables
//*******************************************************************************************************************

unsigned char PadNote[6] = {52,16,66,63,40,65}; // MIDI notes from 0 to 127 (Mid C = 60)

int PadCutOff[6] = {600,600,600,600,600,600}; // Minimum Analog value to cause a drum hit

int MaxPlayTime[6] = {90,90,90,90,90,90}; // Cycles before a 2nd hit is allowed

#define midichannel 0; // MIDI channel from 0 to 15 (+1 in “real world”)

boolean VelocityFlag = true; // Velocity ON (true) or OFF (false)

//*******************************************************************************************************************
// Internal Use Variables
//*******************************************************************************************************************

boolean activePad[6] = {0,0,0,0,0,0}; // Array of flags of pad currently playing
int PinPlayTime[6] = {0,0,0,0,0,0}; // Counter since pad started to play

unsigned char status;

int pin = 0;
int hitavg = 0;

//*******************************************************************************************************************
// Setup
//*******************************************************************************************************************

void setup()
{
Serial.begin(57600); // connect to the serial port 115200
}

//*******************************************************************************************************************
// Main Program
//*******************************************************************************************************************

void loop()
{
for(int pin=0; pin < 6; pin++)
{
hitavg = analogRead(pin); // read the input pin

if((hitavg > PadCutOff[pin]))
{
if((activePad[pin] == false))
{
if(VelocityFlag == true)
{
// hitavg = 127 / ((1023 – PadCutOff[pin]) / (hitavg – PadCutOff[pin])); // With full range (Too sensitive ?)
hitavg = (hitavg / 8) -1 ; // Upper range
}
else
{
hitavg = 127;
}

MIDI_TX(144,PadNote[pin],hitavg);
PinPlayTime[pin] = 0;
activePad[pin] = true;
}
else
{
PinPlayTime[pin] = PinPlayTime[pin] + 1;
}
}
else if((activePad[pin] == true))
{
PinPlayTime[pin] = PinPlayTime[pin] + 1;

if(PinPlayTime[pin] > MaxPlayTime[pin])
{
activePad[pin] = false;
MIDI_TX(128,PadNote[pin],127);
}
}
}
}

//*******************************************************************************************************************
// Transmit MIDI Message
//*******************************************************************************************************************
void MIDI_TX(unsigned char MESSAGE, unsigned char PITCH, unsigned char VELOCITY)
{
status = MESSAGE + midichannel;
Serial.print(status);
Serial.print(PITCH);
Serial.print(VELOCITY);
}

}
}

Here is the basic drum bit. Now my objective is to add the same of LEDs as there are Pads. (one per, in this example a total of 7). I have chosen the PCF8575C from Sparkfun Electronics because i’ll need 16+ led in the end project and this breakout board has 16. So upon a NoteON event the corresponding led should go HIGH on NoteOFF the led should be OFF and stay OFF until a note is ON again.

Area in the Drum Kit sketch where the user can tune the drum kit for their set-up.
Here is an explanation of the different areas where you can tune your drum kit.

PadNote: These are the MIDI notes that will be played when a drum pad is triggered. They range from 0 to 127, where middle C is the number 60. Do not use a value above 127.

PadCutOff: The Arduino reads analog values as a number from 0 to 1023. When you hit a drum pad the piezo creates a voltage spike and ripple. We are reading the value of this voltage spike. The padCutOff is the minimum value of this spike that we will accept as a drum hit. You can set it higher or lower. Lower will make more false triggers, but easier to make drum hits if your pads are thick. Higher will require you to hit the pads harder to make them sound, but you will get less false triggers from hitting a nearby pad if they are on the same surface.

MaxPlayTime: Is a delay based on the number of times the main loop of the program runs through. This delay is intended to keep the kit from sounding multiple hits for one drum hit, since the Arduino is fast enough to read the same voltage spike a few times. If you are getting two hits etc, when you hit the drum only once, increase this number if there is too large a delay when you play a drum roll, then decrease this number.

midichannel: Is simply the MIDI channel that will be send in the MIDI message.

VelocityFlag: Is a true or false setting to use velocity or not. Velocity is the value of how hard you hit the drum pad. A higher velocity would produce a louder drum sound.

My understanding is that PadcutOff is the On/OFF point for NoteOn/NoteOFF so at those points I need to trigger LED_on /Led_off on i2c.
again

Midi_footsteps is an exact example to what I’m trying to accomplish, as well as how my port expander is wired.
Here is how Mike did it http://www.thebox.myzen.co.uk/Hardware/MIDI_Footsteps_files/Footsteps%20Software.zip it’s homepage MIDI Footsteps

Help !

You want to find the parts in the code where you send the MIDI note on message, and follow that with a line that will turn the LED on.
You should then find the parts in the code where you send the MIDI note off message, and follow that with a line that will turn the LED off.

You send two bytes to the I2C port expander, each bit in those bytes will correspond to one of the LEDs. If you hold the current state of the lights in an int variable ( that is 16 bits ) then all you need to do is to set or clear the appropriate bit and then write it out to the port expander.

The MIDI will have a note number associated with the note, and the LED will have a bit number associated with its control. You have to make sure you set the right bit for the right note. There are many ways to do this, the best being a look up table. This is implemented with an array whose index represents the MIDI note and the contents represent the bit to set.
So if you are sending MIDI note 64 then you fine the bit to set in the look up array position 64.

bitToSet = lookUp[64];

then you set that bit by doing

ledBits |= 1 << bitToSet;

However you might find it easier to use a bunch of if statements:-

if(midiNote == 64) ledBits |= 0x1;
if(midiNote == 65) ledBits |= 0x2;
if(midiNote == 66) ledBits |= 0x4;
if(midiNote == 67) ledBits |= 0x8;
if(midiNote == 68) ledBits |= 0x10;

the same goes for turning the LED off:-

if(midiNote == 64) ledBits &= ~0x1;
if(midiNote == 65) ledBits &= ~0x2;
if(midiNote == 66) ledBits &= ~0x4;
if(midiNote == 67) ledBits &= ~0x8;
if(midiNote == 68) ledBits &= ~0x10;

Note here that ~0x10 is tilda 0x10 not minus.