Haluan tehdä oman MIDI-pedaalin Axe FX III:lle.
Syyt:
- Fractal Audion sinänsä mahtava pedaali maksaa lähes 1.000 €.
- Haluan, että pedaalissa on hyvät kytkimet.
- Rahaa saa palaa max. 100 €.
- MIDI-pedaalin tekemiseen tarvittavan mikrokontrollerin ohjelmointi on mukava alkutalven haaste.
Ostin projektia varten Arduino Unon ja asensin tietokoneeseen siihen liittyvän kehitysympäristön, jolla Arduinon voi ohjelmoida. Ohjelmointi on suoraviivaista: kytketään Arduino USB-kaapelilla koneeseen, tehdään ohjelma, käännetään se ja sen jälkeen lähetetään se tietokoneesta Arduinoon. Ohjelma jää talteen Arduinoon ja käynnistyy automaattisesti.
Arduino Unon ohjelmointikieli muistuttaa C:tä. Koodasin sillä viimeksi joskus 1990-luvun puolella, mutta perusasioiden syntaksi on suunnilleen sama kuin Javascriptissä. Koodissa on kaksi pääfunktiota, setup() ja loop(). Setup() kutsutaan, kun Arduino kytketään päälle ja sen jälkeen Arduino suorittaa loop()-funkiota hamaan tulevaisuuteen asti. Tässä esimerkki yksinkertaisesta ohjelmasta, joka ei kuitenkaan tee mitään ulospäin näkyvää:
void setup() {
Serial.begin(9600);
}
void loop() {
// Tätä toistetaan niin kauan kun Arduino on päällä
delay(100); // 100 ms viive
}
MIDI-signaalia Arduinolla pystyy lähettämään suoraviivaisesti: kolmesta MIDI-kaaplin johdosta yksi kytketään TX-pinniin 220 Ohm vastuksen kautta, toinen maihin GND-pinniin ja kolmas +5V-pinniin myös 220 Ohm vastuksen kautta. Tässä prototyyppi yllä kuvatusta kytkennästä:
Arduinon virransyötön voi hoitaa USB-kaapelin tai ulkoisen virtalähteen kautta. Ohjelmoinnissa käytän USB:tä, mutta kun MIDI-pedaali on valmis, käytän 5 V DC-tuloa. Kitarapedaalilaudassani on säädettäviä jännitelähteitä ja siitä saa helposti ulos myös 5 voltin tasajänniteen, joten nyt ei ole tarvetta rakentaa virransyöttöä muuntajalla ja regulaattorilla.
Kotelon suunnittelen Blenderillä. Tässä kuvakaappaus juuri alkaneesta suunnitelusta:
Ohjelman suunnittelu
Tuki Expression-pedaaleille
En ole vielä varma, montako expression-pedaalia haluan kytkeä MIDI-pedaaliini (jos yhtään), mutta tein ohjelmakoodin täysin skaalautuvaksi.
Expression-pedaalien alustaminen:
/*
Expression-pedaalit
*/
int expressionPedalCount = 2;
int expressionPedalPort[] = {0, 1}; // Expression-pedaali – Analog-portin numero
int expressionPedalcc[] = {23, 32}; // Expression-pedaali – cc-kanavan numero
int expressionPedalLastValue[] = {0, 0};
bool expressionPedalUsed[] = {false, false}; // 0=arvoa ei päivitetty, 1=arvo on päivitetty
int expressionMinimumValueToRoundTo0 = 2; // pienin analog inputista luettu arvo, joka pyöristetään nollaksi
int expressionMaximumValueToRoundTo127 = 125; // suurin analog inputista luettu arvo, joka pyöristetään 127:ksi
Expression-pedaalien lukeminen:
/*
readExpressionPedals
Lukee expression-pedaalit ja lähettää cc-komennot MIDInä ulos, jos pedaaleita on liikutettu.
*/
void readExpressionPedals() {
// Luetaan Expression-pedaalit
for (int i=0; i < expressionPedalCount; i++) {
int analogValue = analogRead( expressionPedalPort[i] );
int expressionPedalValue = map( analogValue, 0, 1023, 0, 127) ; // Luetaan Expression-pedaali, Muunnetaan int 0…1023 => byte 0…127
if (!expressionPedalUsed[i] || expressionPedalLastValue[i] != expressionPedalValue) {
expressionPedalUsed[i] = true;
expressionPedalLastValue[i] = expressionPedalValue;
if (expressionPedalValue <= expressionMinimumValueToRoundTo0) expressionPedalValue = 0; // arvot 0-2 muunnetaan 0:ksi
if (expressionPedalValue >= expressionMaximumValueToRoundTo127) expressionPedalValue = 127; // arvot 125-127 muunnetaan 127:ksiccChange( expressionPedalcc[i], expressionPedalValue ); // Lähetetään MIDI cc-komento
}
}
}
Painonappien lukeminen:
void readButtons() {
for (int i=0; i<buttonCount; i++) {
int arvo = readDigitalButtonState( buttonPort[i] );
if ( arvo != buttonStatus[i]) {
// Nappia painettu
buttonStatus[i] = arvo;
buttonUsed[i] = true;
Serial.println( ”Digital Button Input ” + String( buttonPort[i] ) + ”: ” + String(buttonStatus[i]));
}
}
}
int readDigitalButtonState( int port ) {
int arvo = digitalRead( port );
if (arvo > 0) return 1;
return 0;
}
Program Change -komennon lähettäminen:
/*
programChange
Lähettää program change -komennon MIDInä
Käytetään globaalisti asetettua MIDI-kanavaa.
*/
void programChange(int programNumber) {
// xC0 – xcF
byte cmd = 0xC0 + MIDIChannel;
midiSerial.write(cmd);
midiSerial.write( byte(programNumber));Serial.print(”programChange: cmd: ”);
Serial.print(cmd);
Serial.print(” programNumber: ”);
Serial.println(programNumber);delay(150);
}
CC:n lähettäminen:
/*
ccChange
Lähettää cc-komennon MIDInä
Käytetään globaalisti asetettua MIDI-kanavaa.
*/
void ccChange(int ccNumber, int value) {
/* 0xB0 to 0xBF where the low nibble is the MIDI channel.
Data
Two data bytes follow the Status.
The first data is the controller number (0 to 127). This indicates which controller is affected by the received MIDI message.
The second data byte is the value to which the controller should be set, a value from 0 to 127.
*/
byte cmd = 0xB0 + MIDIChannel;
midiSerial.write(cmd);
midiSerial.write( byte(ccNumber));
midiSerial.write( byte(value) );Serial.print(”ccChange cmd: ”);
Serial.print(cmd);
Serial.print(” ccNumber: ”);
Serial.print(ccNumber);
Serial.print(” value: ”);
Serial.println(value);
}
Ohjelmakoodi on vielä ihan alkutekijöissä – parantelen sitä matkan varrella kun pedaali alkaa kehittyä. Testasin expression-pedaalin ja kytkimien lukemisen toiminnallisuuden prototyypillä, mutta en ole vielä lähettänyt MIDI-signaalia ulkomaailmaan. Jatkuu seuraavassa numerossa (eli artikkeli päivittyy!). 🙂
Ensimmäinen MIDI-testi
Kytkin Arduinon vanhaan Korg M3R-syntikkaani testatakseni kytkentöjen toimivuutta. Testiohjelma vaihtaa soundia ikuisessa silmukassa soittaen aina yhden nuotin kullakin soundilla:
#include <MIDI.h>
MIDI_CREATE_DEFAULT_INSTANCE();void setup()
{
MIDI.begin();
}void loop()
{for (int ProgramNumber=0; ProgramNumber < 99; ProgramNumber++ ) {
MIDI.sendProgramChange( ProgramNumber, 1);MIDI.sendNoteOn ( 0x40, 100, 1);
delay(500);MIDI.sendNoteOff( 0x40, 0, 1);
delay(100);
}
}
Toimii!!! 🙂
Päivitetty ohjelmakoodi
/*
Panun MIDI-kontrolleri – Arduino Uno
(c) Pulu Studio, Panu Pentikäinen, 2022->
*/
#include <MIDI.h>
MIDI_CREATE_DEFAULT_INSTANCE();
/*
Globaali MIDI-kanava
*/
byte MIDIChannel = 1;
/*
Expression-pedaalit
*/
const int expressionPedalCount = 2;
const int expressionPedalPort[] = {0, 1}; // Expression-pedaali – Analog-portin numero
const int expressionPedalcc[] = {23, 32}; // Expression-pedaali – cc-kanavan numero
int expressionPedalLastValue[] = {0, 0};
bool expressionPedalUsed[] = {false, false}; // 0=arvoa ei päivitetty, 1=arvo on päivitetty
const int expressionMinimumValueToRoundTo0 = 2; // pienin analog inputista luettu arvo, joka pyöristetään nollaksi
const int expressionMaximumValueToRoundTo127 = 125; // suurin analog inputista luettu arvo, joka pyöristetään 127:ksi
/*
Painikkeet
*/
const int buttonCount = 6;
const int buttonPort[] = {2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13}; // Expression-pedaali – Analog-portin numero
int buttonStatus[] = {0,0,0,0,0,0,0,0,0,0};
int buttonUsed[] = {false,false,false,false,false,false,false,false,false,false};
int buttonLedPort[] = {8,9,10,11,12,13};
void setup() {
MIDI.begin();
for (int i=0; i<buttonCount; i++) {
pinMode(i, INPUT_PULLUP);
}
}
void loop() {
readButtons();
readExpressionPedals();
delay(50);
} // loop
/*
programChange
Lähettää program change -komennon MIDInä
Käytetään globaalisti asetettua MIDI-kanavaa.
*/
void programChange(int programNumber) {
// xC0 – xcF
MIDI.sendProgramChange( programNumber, MIDIChannel);
delay(250);
}
/*
ccChange
Lähettää cc-komennon MIDInä
Käytetään globaalisti asetettua MIDI-kanavaa.
*/
void ccChange(int ccNumber, int value) {
MIDI.sendControlChange( ccNumber, value, MIDIChannel);
}
void readButtons() {
for (int i=0; i<buttonCount; i++) {
int arvo = readDigitalButtonState( buttonPort[i] );
if ( arvo != buttonStatus[i]) {
// Nappia painettu
buttonStatus[i] = arvo;
buttonUsed[i] = true;
}
}
}
int readDigitalButtonState( int port ) {
int arvo = digitalRead( port );
if (arvo > 0) return 1;
return 0;
}
/*
readExpressionPedals
Lukee expression-pedaalit ja lähettää cc-komennot MIDInä ulos, jos pedaaleita on liikutettu.
*/
void readExpressionPedals() {
// Luetaan Expression-pedaalit
for (int i=0; i < expressionPedalCount; i++) {
int analogValue = analogRead( expressionPedalPort[i] );
int expressionPedalValue = map( analogValue, 0, 1023, 0, 127) ; // Luetaan Expression-pedaali, Muunnetaan int 0…1023 => byte 0…127
if (!expressionPedalUsed[i] || expressionPedalLastValue[i] != expressionPedalValue) {
expressionPedalUsed[i] = true;
expressionPedalLastValue[i] = expressionPedalValue;
if (expressionPedalValue <= expressionMinimumValueToRoundTo0) expressionPedalValue = 0; // arvot 0-2 muunnetaan 0:ksi
if (expressionPedalValue >= expressionMaximumValueToRoundTo127) expressionPedalValue = 127; // arvot 125-127 muunnetaan 127:ksi
ccChange( expressionPedalcc[i], expressionPedalValue ); // Lähetetään MIDI cc-komento
}
}
}