Understanding MIDI signals

Hi
So I am tyring to learn a little bit about MIDI controllers and have been reading around about some of there features. I wondered if anyone could clear a few things up for me with the MIDI.h library here as setup doesnt seem to be performing exactly as I would expect.
Firstly I have flashed the mega126U2 with MIDI firmware to convert the arduino to a midi controller. I am programming the arduino (2560) with a AVRISP MKII.
My ultiamte aim is to have a few buttons being scanned by the arduino to check if they are being pressed. If they are send a midi signal out of the usb. I also want a pitch bend wheel and a modulator. Also I am thinking about an arpeggiator which will require tempo set by the midi software on the computer, so I will need to be able to pickup midi signal coming back.
So this is what I think has to happen:
In setup() I need midi.begin() - then in the brackets I set the channel. I am a bit confused about this. If I set the channel to 1 then does that mean the arduino will appear to midi softwre as midi instrument on channel 1? What would the difference to the software be if I set it to omni? And why in midi.sendNoteOn do I then have to set the channel again? Does that have to be the same channel?

Modulator's as i understand it send a CC message. Is that also a SendNoteOn method call with a different 'Type' or a different call alltogether?
The pitch bend, I have noticed has its own method to call, so I think once I understand sending SendNote commands, I should be able to handle that.

over receiving a tempo from the computer, can this be done along side sending to the pc? Remember I am using the usb cable for midi, with the firmware changed to the midi firmware...

Lastly just to check, When a user releases a button I need to send a SendNoteOff. Is it better to send a Send a SendNoteOff or a SendNoteOn with 0 velocity?

Thanks guys.

You might find this handy:

That decodes MIDI from a device and shows it on the terminal. That way you can see what is normal.

Lastly just to check, When a user releases a button I need to send a SendNoteOff. Is it better to send a Send a SendNoteOff or a SendNoteOn with 0 velocity?

There is a slight advantage to sending SendNoteOn with 0 velocity, because you can send multiple arguments to a single MIDI command, thus saving a byte. (eg. instead of NoteOff A, NoteOn B(63), you can send: NoteOn A(0), B(63). ).

Ahh Nice Nick!
So you've done the hard work of decoding the midi messages and i can stand on the shoulder of a giant before me? Sorry, very cliche...

So in terms of reading midi data back in, I can just poll it like you do once each time around the loop. I don't suppose there's an interupt I could set that to - I understand thats better than polling if you can do it.
So a midi controller sends a timing message 24 times a second (according to that page you link to). So you ignore if c = 11111000
and you ignore if the signal is active sensing.
Im not completely sure what your switch is check: (c >> 4) & 0x07, Are you cutting off the 4 MSB and then adding 0111 to the end of it? so that the 4LSB's become the MSB's? And then are you case statements checking whether c = 0 etc? can you do that? i.e compare a bianary to a decimal without any conversion? Didn't know that...

Due to the fact that I am not needing to read data unless it is a timing value (11111000) just produce it, is there a command for a modulation wheel, I noticed there is one for pitch bending.

Over my final point.
At the moment, my code checks to see if a button is pressed and outputs a SendNoteOn command if it is, but if the button isn't pressed it sends a SendNoteOff command, which means it is continuously sending data. is that ok/required, or should I just send the sendNoteOff once and then be done with it?

So my arduino midi controller is doing something I just don't get, first let me show you the code and the output.
Code:

#include <MIDI.h>;
const byte ROWS = 2; //two rows
const byte COLS = 4; //four columns
int buttonstate [ROWS][COLS] = {
  {
    0,0, 0, 0          }
  ,
  {
    0,0, 0, 0          }
};
int currentState = 1; //global...
byte colPins[COLS] = {
  8, 9, 10, 11}; //connect to the row pinouts of the keypad
byte rowPins[ROWS] = {
  12, 13}; //connect to the column pinouts of the keypad

void setup()
{ 
  for (byte r=0; r<ROWS; r++) {
    pinMode(rowPins[r],INPUT);
    digitalWrite(rowPins[r],HIGH);	// Enable the internal 20K pullup resistors.
  }
  //Setup MIDI:
  MIDI.begin(1);
  Serial1.begin(115200);

}

void loop(){

  for (int c=0; c<COLS; c++) {
    pinMode(colPins[c],OUTPUT);               // Prepare column pin for sending a pulse.
    digitalWrite(colPins[c], LOW);            // Pulse the pin colPins[c] low.
    for (int r=0; r<ROWS; r++) {


      currentState = digitalRead(rowPins[r]);

      if (currentState != buttonstate[r][c]){ // A key is PRESSED on row r, column c
        if (currentState == LOW){
          MIDI.sendNoteOn(60,127,1); // Send a Note (pitch 60, velo 127 on channel 1) velocity is piezo value (0-127)
          Serial1.print("Note On");
        }
        else {
          MIDI.sendNoteOff(60,127,1);
          Serial1.println("Note Off");

        }
      }

      buttonstate[r][c] = currentState;// Store PRESSED keys.
    }
    //Serial1.println("");
    digitalWrite(colPins[c], HIGH);          // End the pulse
    pinMode(colPins[c],INPUT);	         // Prevent shorts between columns when multiple keys are pressed.
  }
}

Terminal Output:

Note OnNote Off
Note OnNote Off
Note OnNote Off
Note OnNote Off
Note OnNote Off
Note OnNote Off
Note OnNote Off
Note OnNote Off
Note OnNote Off
Note OnNote Off

MIDI-OX output (application that displays midi data):

 TIMESTAMP IN PORT STATUS DATA1 DATA2 CHAN NOTE EVENT               
 00024D54   2   1     87    F8    00    8  G#19 Note Off              
 00025720   2   1     C7    F8    --    8  ---  PC: Guit Fret Noise   
 00025720   2   1     CF    80    --   16  ---  PC: Acc. Grand Piano  
 000267D1   2   1     87    F8    00    8  G#19 Note Off              
 00027112   2   1     C7    F8    --    8  ---  PC: Guit Fret Noise   
 00027113   2   1     CF    C0    --   16  ---  PC: Soprano Sax       
 000280D6   2   1     87    F8    00    8  G#19 Note Off

So you can see that only half of the midi signals seem to be getting through, compared to all of the serial signals - I pressed the first button (only) in my matrix 10 times - those Note Off messages in MIDI OX are coming in with the lines above them.
The other thing I don't get is why the data is coming in on channel 8 & 16

I also tried in fruity loops but thats not playing any sounds either, thats why I turned to MIDI OX. Any ideas why please?

Moderator edit: Changed quote tags to code tags so things would line up. (Nick Gammon)

What hardware are you using? Describe in detail.

I am using an Arduino mega2560. I am programming it with an AVR ISP MKII. I am sending MIDI down the USB port of the Arduino, and I have flashed the firmware of the atmega16U2 with MIDI firmware from here: http://hunt.net.nz/users/darran/weblog/52882/Arduino_UNO_MIDI_USB_version_02.html

The second download option says it is for the 2560.

I thought it was an atmega8U2 but AVR Studio 6 picked up it was the 16 version.

My buttons are in an array - 8 of them, with Diodes on each one. Using the code posted in my last post, you can see that the button goes LOW when a button is pressed
I am using serial 1 connected to the TX/RX of an AVR dev board I also have that has a serial port and max232 on board. I just took the chip out and connected header cables between the two. Then I have a serial to usb cable connected to my computer and that serial port so that I can read Serial1 from the Termite Serial terminal software.
The serial seems to be working properly as each time I press/release a button, Note OnNoteOff appears in the terminal window.
Have I missed any details out?
Thanks Nick.

Ah I see, you aren't using serial MIDI you are using USB MIDI. I haven't tried that myself. I am not able to say whether, or not, the reflashing of the U16 chip was successful for your purposes.

a.mlw.walker:
At the moment, my code checks to see if a button is pressed and outputs a SendNoteOn command if it is, but if the button isn't pressed it sends a SendNoteOff command, which means it is continuously sending data. is that ok/required, or should I just send the sendNoteOff once and then be done with it?

That doesn't seem ideal.

In the Arduino IDE, under File->Examples->Digital you'll find StateChangeDetection. That's a short example of how to do things only when the state of a button changes - it's also polled, like your code. There's a page about it here:

http://arduino.cc/en/Tutorial/ButtonStateChange

I agree with Andy2No. You will be flooding the MIDI with thousands of Note On commands, which is undesirable.

Yeah I changed it to a state change now thanks for feedback.
Over the midi firmware, i think I have to change the serial output rate to the usb to 115200, Im gonna try that and get back to you.
Cheers

My buttons are connected to a mux, this is my state change code. Does it look right, because the way the midi is responding on my pc is a little odd I think. It seems to recongise alternate button presses...

int counter = -1;
  for (int c=0; c<COLS; c++) {
    pinMode(colPins[c],OUTPUT);               // Prepare column pin for sending a pulse.
    digitalWrite(colPins[c], LOW);            // Pulse the pin colPins[c] low.
    for (int r=0; r<ROWS; r++) {
      counter++;
      readPiezo(counter);

      currentState = digitalRead(rowPins[r]);
        
        if (currentState != buttonstate[r][c]){ // A key is PRESSED on row r, column c
          if (currentState == LOW){
          MIDI.sendNoteOn(60+counter,127,1); // Send a Note (pitch 60, velo 127 on channel 1) velocity is piezo value (0-127)

          }
          else {
            MIDI.sendNoteOff(60+counter,127,1);


          }
        }

      buttonstate[r][c] = currentState;// Store PRESSED keys.
    }
    //Serial1.println("");
    digitalWrite(colPins[c], HIGH);          // End the pulse
    pinMode(colPins[c],INPUT);	         // Prevent shorts between columns when multiple keys are pressed.
  }