DIY: Arduino MIDI Xylophone
Ένα μουσικό όργανο - MIDI controller για τον υπολογιστή. Ένα μουσικό όργανο - MIDI controller για τον υπολογιστή.
Σίγουρα όσοι ασχολείστε με τα DIY, τις πλακέτες ανάπτυξης και άλλα συναφή, θα έχετε παρατηρήσει την modular φύση τους που σας επιτρέπει να φτιάξετε και να ελέγξετε σχεδόν τα πάντα. Στα "πάντα" συμπεριλαμβάνονται και τα μουσικά όργανα και σε αυτό το DIY θα φτιάξουμε ένα USB MIDI controller με την εμφάνιση ενός ξυλόφωνου, το οποίο θα στέλνει τις πληροφορίες σε ένα DAW (Digital Audio Workstation) της επιλογής μας. Το concept παραμένει το ίδιο ακόμα και όταν θέλετε να φτιάξετε ένα drum kit ακόμη και ένα απλό πιάνο, πάντα με ένα Arduino ανά χείρας.
Σίγουρα όσοι ασχολείστε με τα DIY, τις πλακέτες ανάπτυξης και άλλα συναφή, θα έχετε παρατηρήσει την modular φύση τους που σας επιτρέπει να φτιάξετε και να ελέγξετε σχεδόν τα πάντα. Στα "πάντα" συμπεριλαμβάνονται και τα μουσικά όργανα και σε αυτό το DIY θα φτιάξουμε ένα USB MIDI controller με την εμφάνιση ενός ξυλόφωνου, το οποίο θα στέλνει τις πληροφορίες σε ένα DAW (Digital Audio Workstation) της επιλογής μας. Το concept παραμένει το ίδιο ακόμα και όταν θέλετε να φτιάξετε ένα drum kit ακόμη και ένα απλό πιάνο, πάντα με ένα Arduino ανά χείρας.
Βήμα 1. Για τις ανάγκες του DIY λοιπόν θα χρειαστούμε: Arduino Mega 2560, Piezo Element, 1M Ohm αντιστάσεις, καλώδια, PCB, USB καλώδιο TypeA σε TypeB και ένα housing για το ξυλόφωνο από απλό, φθηνό ξύλο (κόντρα πλακέ). Από εργαλεία θα χρειαστούμε laser cutter, ψαλίδι, κατσαβίδι.
Βήμα 2. Αρχικά θα επεξεργαστούμε τα piezo's αφαιρώντας τους το καπάκι και κολλώντας μακρύτερο καλώδιο για να τα βάλουμε στο ξυλόφωνό μας.
Βήμα 3. Όσον αφορά το casing του ξυλόφωνου χρησιμοποιούμε το CorelDraw για τη σχεδίαση του κουτιού και ξύλο κόντρα πλακέ για την κατασκευή ενώ οι πλάκες φτιάχνονται από ακρυλικό υλικό 10x2 ιντσών. Το κουτί που κατασκευάσαμε έχει διαστάσεις 10.5x30x3.
Βήμα 4. Σε αυτό το βήμα θα κολλήσουμε τους πιεζο-αισθητήρες με τις ακρυλικές πλάκες αφού τις περάσουμε μέσα από το ξύλο όπως φαίνεται στις φωτογραφίες.
Βήμα 5. Έπειτα θα δώσουμε απόσταση στις πλάκες για μια πιο αυθεντική αίσθηση. Χρησιμοποιούμε μεγάλες βίδες 1 1/2" (δύο για κάθε πλάκα) και για την μείωση των δονήσεων κατά το παίξιμο χρησιμοποιούμε ένα μικρό κομμάτι από σωλήνα υδρόψυξης.
Βήμα 6. Ακολουθεί η σύνδεση των πιεζο-αισθητήρων με το Arduino όμως προτού προχωρήσουμε, παρεμβάλλουμε μια αντίσταση 1MΩ για να προστατέψουμε τις αναλογικές εισόδους του Arduino από την τάση που παράγει ο πιεζο-αισθητήρας. Τα κοντά πορτοκαλί καλώδια, ορίστηκαν ως οι γειώσεις και ενώνουν τη μια πλευρά της εκάστοτε αντίστασης με την εξωτερική πλευρά του PCB όπως διακρίνεται στο σχεδιάγραμμα.
Βήμα 7. Μαρκάρουμε τα καλώδια με το όνομα τις εκάστοτε αναλογικής εισόδου του Arduino και τα συνδέουμε. Όλες οι αναλογικές είσοδοι που περισσεύουν πρέπει να γειωθούν για να μην επηρεάσουν την σειριακή έξοδο από το Arduino. Αφού ολοκληρώσουμε το κύκλωμα ήρθε η ώρα για τον κώδικα:
[SPOILER]//Xylophone
//Adapted for an ArduinoMega
//from Jenna deBoisblanc and Spiekenzie Labs initial code
//*******************************************************************************************************************
// User settable variables
//*******************************************************************************************************************
int pinRead;
char pinAssignments[6] ={
'A0','A1','A2','A3','A4','A5','A6','A7','A8','A9','A10','A11'};
byte PadNote[16] = {
57,58,59,60,61,62,63,64,65,66,67,68,69,70,71,72}; // MIDI notes from 0 to 127 (Mid C = 60)
int PadCutOff[16] =
{
400,400,200,800,400,400,400,400,400,400,400,400,400,400,400,400}; // Minimum Analog value to cause a drum hit
int MaxPlayTime[16] = {
90,90,90,90,90,90,90,90,90,90,90,90,90,90,90,90}; // Cycles before a 2nd hit is allowed
#define midichannel 1; // MIDI channel from 0 to 15 (+1 in "real world")
boolean VelocityFlag = true; // Velocity ON (true) or OFF (false)
//*******************************************************************************************************************
// Internal Use Variables
//*******************************************************************************************************************
boolean activePad[16] = {
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0}; // Array of flags of pad currently playing
int PinPlayTime[16] = {
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0}; // Counter since pad started to play
byte status1;
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 < 16; pin++) //
{
//int pin = 3;
// for (pinRead=0; pinRead < 16, pin++){
hitavg = analogRead(pinAssignments[pin]);
//Serial.println(hitavg);
// 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); //note on
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(144,PadNote[pin],0);
}
}
}
}
//*******************************************************************************************************************
// Transmit MIDI Message
//*******************************************************************************************************************
void MIDI_TX(byte MESSAGE, byte PITCH, byte VELOCITY)
{
status1 = MESSAGE + midichannel;
Serial.write(status1);
Serial.write(PITCH);
Serial.write(VELOCITY);
}
[/SPOILER]
[SPOILER]//Xylophone
//Adapted for an ArduinoMega
//from Jenna deBoisblanc and Spiekenzie Labs initial code
//*******************************************************************************************************************
// User settable variables
//*******************************************************************************************************************
int pinRead;
char pinAssignments[6] ={
'A0','A1','A2','A3','A4','A5','A6','A7','A8','A9','A10','A11'};
byte PadNote[16] = {
57,58,59,60,61,62,63,64,65,66,67,68,69,70,71,72}; // MIDI notes from 0 to 127 (Mid C = 60)
int PadCutOff[16] =
{
400,400,200,800,400,400,400,400,400,400,400,400,400,400,400,400}; // Minimum Analog value to cause a drum hit
int MaxPlayTime[16] = {
90,90,90,90,90,90,90,90,90,90,90,90,90,90,90,90}; // Cycles before a 2nd hit is allowed
#define midichannel 1; // MIDI channel from 0 to 15 (+1 in "real world")
boolean VelocityFlag = true; // Velocity ON (true) or OFF (false)
//*******************************************************************************************************************
// Internal Use Variables
//*******************************************************************************************************************
boolean activePad[16] = {
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0}; // Array of flags of pad currently playing
int PinPlayTime[16] = {
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0}; // Counter since pad started to play
byte status1;
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 < 16; pin++) //
{
//int pin = 3;
// for (pinRead=0; pinRead < 16, pin++){
hitavg = analogRead(pinAssignments[pin]);
//Serial.println(hitavg);
// 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); //note on
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(144,PadNote[pin],0);
}
}
}
}
//*******************************************************************************************************************
// Transmit MIDI Message
//*******************************************************************************************************************
void MIDI_TX(byte MESSAGE, byte PITCH, byte VELOCITY)
{
status1 = MESSAGE + midichannel;
Serial.write(status1);
Serial.write(PITCH);
Serial.write(VELOCITY);
}
[/SPOILER]
Βήμα 8. Συνδέουμε το "Arduino driven" ξυλόφωνό μας με τον υπολογιστή. Ανοίγουμε και μια τρύπα στο housing για να περάσουμε το USB καλώδιο.
Βήμα 9. Το Arduino "βγάζει" σήμα σειριακής μορφής και θα πρέπει με κάποιο τρόπο να το μετατρέψουμε σε MIDI ούτως ώστε να χρησιμοποιούμε το ξυλόφωνο με προγράμματα σύνθεσης μουσικής (Digital Audio Workstations - DAW) όπως τα Ableton Live, Apple Logic/GarageBand και πολλά πολλά ακόμα. Για αυτή τη δουλειά επιστρατεύουμε το πρόγραμμα Hairless, το οποίο λειτουργεί σε MacOS, Windows και Linux.
Σημείωση: Κάθε φορά που θα πρέπει να ανανεώσετε ή να διορθώσετε κάτι στον κώδικα του Arduino θα πρέπει να επιστρέφετε σε serial signal "mode" για να το προγραμματίσετε.
Σημείωση: Κάθε φορά που θα πρέπει να ανανεώσετε ή να διορθώσετε κάτι στον κώδικα του Arduino θα πρέπει να επιστρέφετε σε serial signal "mode" για να το προγραμματίσετε.
Βήμα 10. Και τέλος, ξεκινάμε το τζαμάρισμα! Φορτώνουμε κάποιο MIDI όργανο από το πρόγραμμα της επιλογής μας και γράφουμε MIDI νότες!