MIDI Xilophone (over serial) to Ableton

FWIW, I can't get it to work either. I've done a number of Arduino to Processing serial things successfully. I have Lion - 10.7.3.

Just to make sure we are on the same page.
This is the arduino sketch I have been using to test the MIDI input. It just generates random chimes. Run it on the arduino and see if the Serial <> MIDI make sense of it:-
If you choose the Java Synth option you should here the chimes.

/* Midi note fire - Mike Cook March 2012
 *
 * ----------------- 
 * send MIDI serial data, automatically for a test
 * 
###############################################################################################

HARDWARE NOTE:
The MIDI Socket is connected to arduino TX through a PNP transistor to invert the MIDI signal.
A common anode RGB LED is pulled down through pins 9, 10, 11

################################################################################################
*/
 #define MIDI_TEST   // un comment for a test to format the data for the serial monitor

#define midiChannel (byte)0
void setup() {
 //  Setup serial
   Serial.begin(9600);    // Serial speed
   programChange(0xc0, 14);  // Change MIDI voice

}

//********************* MAIN LOOP ***********************************

void loop() {
  int val;
  val = random(20,100);
    noteSend(0x90, val, 127);
    delay(200);
    noteSend(0x80, val, 127);
   delay(800);
    } // end loop function
    
//********************* Functions *********************************** 


//  plays a MIDI note
 void noteSend(char cmd, char data1, char data2) {
  cmd = cmd | char(midiChannel);  // merge channel number
  Serial.write(cmd);
  Serial.write(data1);
  Serial.write(data2);
}
//  change the voice
 void programChange(char cmd, char data1) {
  cmd = cmd | char(midiChannel);  // merge channel number
  Serial.write(cmd);
  Serial.write(data1);
}

//  change the bank
void bankChange(char cmd, char data1) {
  Serial.write(0xB0 | char(midiChannel));  // control change
  Serial.write(cmd);
  Serial.write(data1);
}

OK I think I have cracked it.
You need to change the MIDI_TX() function in your code to this:-

void MIDI_TX(unsigned char MESSAGE, unsigned char PITCH, unsigned char VELOCITY)
{
  status = MESSAGE + midichannel;
  Serial.write(status);
  Serial.write(PITCH);
  Serial.write(VELOCITY);

Then make sure the baud rate is set the same between MIDI and Arduino.

Sorry for taking so long and not having spotted this before.

Mike, your test code worked ok for me.

It seems to be working fine for me now. I might have had the Midi setup wrong. I can pass midi into Live now.

oh nooooooooooooo, i can't believe it!!! It is actually WORKING!!! :smiley:

There are two piezos not working and one that plays two notes at the same time. But i'll take a look at this tomorrow when there is more light and i have some more energy (probably i have some connections in the breadboard that opened from all the moving around)!

THANK YOU SOOOO MUCH! I think this has been a great step towards making this project come true!
=)

Stay tuned for the next chapter...
:wink:

I took a close look and, indeed, some of the piezo wires were a bit loose from all the moving around. I fixed that and now they all play a different not and i run the Serial <> Converter through Processing.

When i now open the MIDI Monitor i get this kind of result:

*** ZERO *** From Xilof OUT Note On 1 D3 127
*** ZERO *** From Xilof OUT Note Off 1 D3 127
*** ZERO *** From Xilof OUT Note On 1 F3 127
*** ZERO *** From Xilof OUT Note Off 1 F3 127
*** ZERO *** From Xilof OUT Note On 1 A3 127
*** ZERO *** From Xilof OUT Note Off 1 A3 127

(from pressing 3 piezos in sequence)

So, is it now ok to assume the "assembly" and Midi Conversion parts are working fine?

= = = = = = = = = =

So, my next step would involve two things: add some LEDs and add some controls.

LEDs
I would like to add an LED to each piezo, that would light up when we play and then would slowly fade out (maybe 1 second)
What would be the easiest way to achieve this?

Controls
I would like to add 4 buttons (MIDI, that i could then assign for things like Play, Stop, trigger some event, change sound,...)
and add also 4 knobs (that could be assigned for things like volume, modulation, tempo,...)
Would this be easily done by just enabling one other multiplexer from the code?

Any thoughts about this two things?

Any extras you add are going to increase the latency because the code has to look at them as well. Anyway you can pile on the extras until it gets too much.

With the LEDs the simplest from a programming point of view is to add a shift register:-
http://www.elcojacobs.com/shiftpwm/

add also 4 knobs

Yes adding an extra multiplexer will do this.

to add 4 buttons

You should have some spare pins left on the arduino.

You should have some spare pins left on the arduino.

So i can just add normal buttons to a digital pin? This shouldn't then be a problem, at the moment i am using only 3 of the digital pins.

With the LEDs the simplest from a programming point of view is to add a shift register:-

for the LEDs, i have a couple of 74HC595N. I saw http://arduino.cc/en/Tutorial/ShiftOut that we can use it to plug several LEDs. But i would have really NO IDEA on how to right a code reading which piezo was played and telling which LED should light up!

Well, i think i will start with the buttons. Maybe that is something accessible for my level.
Anyway, i don't have anymore multiplexers, so i need to wait until tuesday when i'm going to town to buy one more.

So i can just add normal buttons to a digital pin?

Yes, you can even use an analogue pin and treat it as a digital one if you want.

I saw http://arduino.cc/en/Tutorial/ShiftOut that we can use it to plug several LEDs.

Two things, that schematic has an error, there should be no capacitor on the latch pin. Second that software will not give you the fading you want. Use the code in the link for that.
Just do a few examples, given in the link, and you will get the hang of how to control the shift registers.

So, today i am trying to make the 4 buttons work...
i have things setup in the breadboard and i have the buttons connected to Arduino like this:
Button 1 ---> Pin 8
Button 2 ---> Pin 9
Button 3 ---> Pin 10
Button 4 ---> Pin 11

Now, being that i have no experience writting code, i got a bit stuck with it.
I looked around internet, in arduino forum's and i actually think i got at least something i can work on...
right now the code i wrote (JUST for the buttons) is like this:

//trying to make 4 buttons work

// == = = = = = = = = = = = = = = = = = = =

//BUTTON 1
int button1Pin = 8; //Button input pin
int button1Val = 0; //Variable for reading the button status
int button1State = 0; //Variable to hold the button's current state
int bounce1Check = 0; //Variable for debouncing

//BUTTON 2
int button2Pin = 9;
int button2Val = 0;
int button2State = 0;
int bounce2Check = 0;

//BUTTON 3
int button3Pin = 10;
int button3Val = 0;
int button3State = 0;
int bounce3Check = 0;

//BUTTON 4
int button4Pin = 11;
int button4Val = 0;
int button4State = 0;
int bounce4Check = 0;

void setup() {
pinMode(button1Pin, INPUT); //Pin 8 as Button 1 Input
pinMode(button2Pin, INPUT); //Pin 9 as Button 2 Input
pinMode(button3Pin, INPUT); //Pin 10 as Button 3 Input
pinMode(button4Pin, INPUT); //Pin 11 as Button 4 Input
Serial.begin(57600); //Baud rate of 57600
}

void loop()
{
// Momentary buttons

//BUTTON 1
button1Val = digitalRead(button1Pin); //Read input value from button1 (pin8)
delay(10); //Delay of 10ms
bouce1Check = digitalRead(button1Pin); //Checking value from button1 (for debouncing)
if(button1Val == bounce1Check){
if (button1Val == HIGH && button1State == 1) {
MIDI_TX(0x90, 1, 127);
button1State = 0;
}
if(button1Val == LOW && button1State == 0) {
MIDI_TX(0x90, 1, 0);
button1State = 1;
}

//BUTTON 2
//BUTTON 3
//BUTTON 4

}

This would, of course, be incorporated with the rest of the code (that i posted already earlier in this thread).
I was adapting it from some one else's code and they have used their code to connect ONE button via MIDI, but i want to connect FOUR and use SERIAL. (right?)

In the code i have written only the void loop for the Button 1, but i would then copy it and adapt for the rest of the buttons.

i am really unsure about the "MIDI_TX(0x90, 1, ...)" lines...

I would like that the buttons are assignable to some midi event in the software (ableton, or Logic,...) like Play, Effect On, trigger sample,...

Would something like this work?

Thanks!
=)

How are the buttons wired exactly? Do you have an external pull up resistor?
The best way is to wire the button between the pin and ground and enable the internal pull up resistor.
Then you will read a LOW when it is pushed and a HIGH when it is not.

The code looks OK at first glance all be it a bit turgid. I would not bother about debounce at this stage as you will probably not need it in the end.

i am really unsure about the "MIDI_TX(0x90, 1, ...)" lines...

Here you put the MIDI message you want to send. 0x90 is note on for channel 1, you are best using something useful here like a CC message. Look up what bytes constitute one of these.

i had the buttons plugged like this in the button tutorial here in the arduino.cc forums.
I looked now what the internal pullup resistors are and indeed it seems a better solution.

So would it be right to connect the like:

pin1 ---> pin 8 in Arduino
pin2 ---> ground

and use a code like this?

int button1Pin = 8;

//BUTTON 1 (Connected to pin 8 )
void setup() {
pinMode(8, INPUT); //Input pin for Button 1 in Breadboard
digitalWrite(8, HIGH); // Activates internal resistor in Pin 8
}

void loop() {

if(digitalRead(8 ) = LOW){
MIDI_TX // HOW CAN I NOW SEND CC MESSAGE?
}
}

i also read that the MIDI has 4 defined Controller Numbers defined as "General Purpose Buttons".
They are the controllers 80, 81, 82 and 83.
How could i use them?

So would it be right to connect the like:

Yes that and the code is fine.

Control Change.
1011nnnn
0ccccccc
0vvvvvvv

This message is sent when a controller value changes. Controllers include devices such as pedals and levers. Controller numbers 120-127 are reserved as "Channel Mode Messages" (below). (ccccccc) is the controller number (0-119). (vvvvvvv) is the controller value (0-127).

So to send a controller change on channel 1 to controller 80 (decimal?) with a value of on:-
MIDI_TX(0xb0, 80, 127);
and for off:-
MIDI_TX(0xb0, 80, 0);

So, today i had some time off so i came back to the Xilophone project.

i am now working on having the buttons working.
The idea is to have 4 button assignable to any button,sample,..., in the music software, like for instance play, rec, trigger a sample, start an FX, mute, solo...

i have the button plugged to the arduino in pins 8,9,10, and 11 and i am using the internal pull up resistors.
this is the code i am using is this:

int button1Pin = 8;
int button2Pin = 9;
int button3Pin = 10;
int button4Pin = 11;

void setup() {
pinMode(8, INPUT); //Input pin for Button 1 in Breadboard
digitalWrite(8, HIGH); // Activates internal resistor in Pin 8
pinMode(9, INPUT); //Input pin for Button 2 in Breadboard
digitalWrite(9, HIGH); // Activates internal resistor in Pin 8
pinMode(10, INPUT); //Input pin for Button 3 in Breadboard
digitalWrite(10, HIGH); // Activates internal resistor in Pin 10
pinMode(11, INPUT); //Input pin for Button 4 in Breadboard
digitalWrite(11, HIGH); // Activates internal resistor in Pin 10
}

void loop() {
// BUTTON 1 (Connected to pin 8, CC channel 80)
if(digitalRead(8) = LOW){
MIDI_TX(0xB0, 80, 127);
}

// BUTTON 2 (Connected to pin 9, CC channel 81)
if(digitalRead(9) = LOW){
MIDI_TX(0xB0, 81, 127);
}

// BUTTON 3 (Connected to pin 10, CC channel 82)
if(digitalRead(10) = LOW){
MIDI_TX(0xB0, 82, 127);
}

// BUTTON 4 (Connected to pin 11, CC channel 83)
if(digitalRead(11) = LOW){
MIDI_TX(0xB0, 82, 127);
}
}

and the MIDI_TX that i am using for the whole code is:

void MIDI_TX(unsigned char MESSAGE, unsigned char PITCH, unsigned char VELOCITY)
{
status = MESSAGE + midichannel;
Serial.write(status);
Serial.write(PITCH);
Serial.write(VELOCITY);
}

Today i plugged everything in.
The piezo disks are working fine! =)
The buttons are working but there is one problem. Each time i press a button it send a message CONTINUOUSLY without stopping.
How could i change it so it will send a message when i push it down, and then wait and send again another message ONLY when i press the button again?

I have tried a couple of times to write something using a "buttonState" var, but i didn't manage to make it work.
Any ideas or pointers in the right direction?

Thanks

Each time i press a button it send a message CONTINUOUSLY without stopping.

Yes that is what your code has been written to do.
By the way can you post code using the # icon not the quote one next to it. It will stop smillies appearing in your code.

What you have to do is to remember the state of your button push just before you exit the loop() function, in a variable, call it something like lastState. Then only send your MIDI when current state is LOW and the lastState was HIGH.
Do your digital reads into a variable rather than directly in the if statement, then this is easy.

ai, ai, ai...

i think i understand the idea... but i can't really make it work!!!
i was trying it with the LED from pin13 in the arduino with just one button from pin8.

in the end i came to a code that seems to work but i am worried on how it would work with more buttons.
Please let me know what you think about this:

int lastState = HIGH;
 
void setup() {
  pinMode(13, OUTPUT);    
  pinMode(8, INPUT);      
  digitalWrite(8, HIGH);  
}
 
void loop() {
  bool buttonState = digitalRead(8);
  if (buttonState == LOW && buttonState != lastState) {
    digitalWrite(13, buttonState);
    delay(1000);
    lastState = LOW;
  }
  else {
    digitalWrite(13, buttonState);
    lastState = HIGH;
  }
}

where there is now the digitalWrite on pin 13 and the delay, i would then replace it with the MIDI_TX ( MIDI_TX(0xB0, 80, 127); ) that i am using with the rest of the code.

Would this be an effective way to do it?
When i change for the MIDI messages what should i have inside the else? Just "lastState = HIGH;"?

Thank you

i have inside the else?

nothing.

bool lastState = HIGH, currentState;

void setup() {
pinMode(13, OUTPUT);
pinMode(8, INPUT);
digitalWrite(8, HIGH);
}

void loop() {
currentState = digitalRead(8);
if (currentState == LOW && currentState != lastState) {
// do your MIDI stuff here
}
lastState = currentState;
}

You need currentState and lastState variables for each button you want to monitor.

If you want to be grown up then make these into an array:-
http://www.thebox.myzen.co.uk/Tutorial/Arrays.html
but if it is too much then just repeat that code.

Arrays

hey, that was cool reading!!! Of course understanding 100% what it means will take long time, but still i found it really interesting. THANKS!
(and, by the way, when i was looking at the other things there in the website, i found your Hexome. WOW!!! Amazing! i loved it!!! Congratulation)...

Well, after reading your article on arrays, i decided to give it a go.
i tried a couple of times, but in the end when i press the "Verify" button i always get some errors that i cannot fix.
Here is what i have at the moment:

bool lastState = HIGH, currentState;

void setup() {
  int buttonPins[4] = { 8, 9, 10, 11 };
  for (int i=0; i<4; i++) pinMode(buttonPins[i], INPUT);
  for (int i=0; i<4; i++) digitalWrite(buttonPins[i], HIGH);
  
}

void loop() {
  for (button=0; button<4; button++) {
    currentState[button] = digitalRead(buttonPins[button]);
  if(currentState[button] == LOW && currentState(button) != lastState(button)) {
    //STILL MISSES MY MIDI_TX HERE
  }
  lastState[button] = currentState[button];
  }
}

and i get the errors

sketch_apr07a.cpp: In function 'void loop()':
sketch_apr07a:12: error: invalid types 'bool[int]' for array subscript
sketch_apr07a:12: error: 'buttonPins' was not declared in this scope
sketch_apr07a:13: error: invalid types 'bool[int]' for array subscript
sketch_apr07a:13: error: 'currentState' cannot be used as a function
sketch_apr07a:13: error: 'lastState' cannot be used as a function
sketch_apr07a:16: error: invalid types 'bool[int]' for array subscript
sketch_apr07a:16: error: invalid types 'bool[int]' for array subscript

Well, if i am kind of close maybe i can still try to fix it, if not maybe i need to stay simple (at least for this project) and just repeat the code for the four button.

What do you think?

You have to declare the arrays outside of any function if you want to use them in more than one function. The one declared in setup() will not be valid in loop()