Go Down

Topic: MIDI Xilophone (over serial) to Ableton (Read 14218 times) previous topic - next topic

dxw00d

#30
Mar 28, 2012, 03:25 pm Last Edit: Mar 28, 2012, 04:46 pm by dxw00d Reason: 1
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.

Grumpy_Mike

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.

Code: [Select]


/* 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);
}

Grumpy_Mike

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

Code: [Select]

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.

dxw00d

Mike, your test code worked ok for me.

dxw00d

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

boguz

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

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...
;)

boguz

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:
Quote
*** 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?

Grumpy_Mike

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/

Quote
add also 4 knobs

Yes adding an extra multiplexer will do this.

Quote
to add 4 buttons

You should have some spare pins left on the arduino.

boguz

Quote
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.

Quote
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.


Grumpy_Mike

Quote
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.

Quote
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.

boguz

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:

Quote
//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!
=)


Grumpy_Mike

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.

Quote
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.

boguz

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?

Quote
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?

Grumpy_Mike

Quote
So would it be right to connect the like:

Yes that and the code is fine.

Quote
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);



boguz

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:
Quote
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:
Quote
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

Go Up