matpi / EmbeddedSystemsUTU

This repository concerns the course KSA4 Embedded Systems (craft, design and technology education) in the University of Turku, Department of Teacher Education, Rauma Unit in the academic year 2014
4 stars 5 forks source link

Arduino-mikrokontrollerilla ohjattu virtuaalisoitin - Juha Pöykkö #15

Open jumap opened 9 years ago

jumap commented 9 years ago

Arduino-mikrokontrollerilla ohjatut virtuaaliurut (virtual pipe organ)

Aikomukseni on rakentaa kolmisormioinen jalkiolla varustettu harjoittelusoitin.

Laitteisto olisi seuraavanlainen:

Mekaanisten osien liikkeen muuntamiseen sähköiseksi suunnittelin ensin magneettitoimisia ns. reed-kytkimiä. Luin Colin Pykettin (http://www.pykett.org.uk/the_evolution_of_electric_actions.htm) arvioista, että reed-kytkimet ovat epätarkkoja, jolloin niiden käyttö varsinkin koskettimistossa ei ole järkevää, vaan olisi parempi käyttää optisia tai ir-kytkimiä. Reedit ovat toimintavarmoja niin pitkään, kuin niiden suojana oleva lasiampulli on ehjä eikä vieressä oleva magneettikenttä häiritse (vierekkäisisä koskettimissa niitä riittäisi). Mikäli rakennan korkettimistot niin, että MIDI-signaalista saadaan myös velocity -arvo, samalla koskettimella tulee olla kaksi lediä ja optista lukijaa. Optiset kytkimet ovat – ainakin pikaisen tarkastelun jälkeen xd.comissa melko kalliita. Parinsadan kytkimen hinta nousee pariin sataan euroon... Jos rakennan kytkimet itse, selviän halvemmalla mutta sarjatyötä pitää tehdä. Katselin netistä Vishay electronicsin TCST1103 -sensoreita.

Midilaitteisiin ja tarvittaviin kortteihin liittyen on melko paljon epäselvää. Arduino kuitenkin osannee käsitellä MIDIä? Www.midikits.net myy valmiiksi ohjelmoituja arduinoja, joten saman voinee toteuttaa muualta ostetuilla ja pd-skripteillä itse muokaten.

Muita osoitteita, joista kaavin tiedonmurusia: https://github.com/quarterturn https://github.com/rkistner/arduino-organ

Sitten se keinoäly... tämä projekti vain siirtää tietoa... Ehkä jalkiossa olevaan analogiseen säätimeen liitettävä epälineaarinen äänen voimakkuutta ja äänenväriä muuttava ohjelma , joka simuloisi soittimen paisutuskaappia... (taitaa mennä mahdottomaksi ...)

jumap commented 9 years ago

Netissä on paljon Teensy-konrollerilla toteutettuja projekteja. Sen väitetään olevan "arduino-yhteensopiva" - miten lie? Piireinä ATMEGA32U4, MK20DX128 tai MK20DX256.

Robojuchen commented 9 years ago

Tässä on hyvin mielenkiintoinen ja vaativa projekti, ei välttämättä monimutkaisuudeltaan mutta sisältää paljon mekaanista työtä, joka toisaalta kannattaa tehdä hyvin että projektilla on arvoa. Mutta tämähän ei soitinrakentajalle ole varmaankaan mitään uutta :)

Tuosta keinoälystä ei kannata ottaa paineita. Projekti on kyllä tarpeeksi vaativa ilmankin. Se sisältää kuitenkin mekatronisia haasteita kytkimien kanssa ja elektroniikan sisältjä matriiseissa. Tietokonerajapinta on vielä oma asiansa. Projetki on kyllä toimivaksi saatuna ihan kovassa sarjassa. Tosin tuo paisutuskaappi on ihan mahdollinen, sikäli kun tällainen paisutustieto pysytyään midiväylän komentoina simuloimaan.

Suosittelen tilaamaan optisia kytkimiä mahdollisimman nopeasti muutaman, vaikkapa vishaylta näytetkappaleena voisi saada tai kouluelektroniikasta elfan katalogista. sitten voisi kokeilla niiden lukemista, miten se onnistuu. Optiset kytkimet ovat varmasti toimintavarmimmat ja pitäisi olla hyvin kestävätkin...

Yritän itse vähän selvitellä noita midi juttuja vielä...

Robojuchen commented 9 years ago

Tässä olen tutkinut tätä midi-asiaa. Arduinolla on hyvin helppo antaa näitä midi-käskyjä. Sehän on ihan puhdasta sarjaliikennettä ja siihen on valmiita malleja olemassa. Juttu on vain siinä että käskyt pitää saada tietokoneelle, ja nykykoneelle tietenkin USBilla. On olemassa suoralla usb yhteydellä varustettu arduino midi-shieldi ja sitten tuo sparkfunin shieldi johon tarvitsee midi-to-usb kaapelin, joita saa halvalla tilattua.

http://openpipe.cc/products/midi-usb-shield/

Jos katsot sen sparkfunin shieldin kaaviota niin huomaat että se on erittäin yksinkertainen ja tehtävissä itsekin. Lähinnä jos arduinolle päin lähetetään midi-tietoa pitäisi olla nuo optocouplerit mutta tässä projetkissa siihen suuntaan ei taida dataa liikkua.

Olen miettinyt tuota midi-väylän toimintaa... laskin että jos jokaiseen käskyyn tarvitaan kolme tavua ja tahti on 31,250 bps. Jokaiseen tavuun vielä aloitus ja lopetus bitti niin yksi käsky vie noin 1ms. Matriiseja arduino lukee niin nopeasti että siitä ei juuri ongelmaa synny. Kuinka monta nappia pitäisi pystyä soittamaan yhtä aikaa ja mikä on suurin sallittava aika millä urkujen pitäisi reagoida? tätä pitäisi miettiä.

Joka tapauksessa yhdellä arduino megalla pitäisi pystyä mielestäni hoitamaan koko homman. Ainiin ja se paisutuskaappi, ei muuta kuin arduinolla paria potikkaa luetaan ja muutetaan velocity arvoa sen mukaan? Riittääkö urkuihin muuten on/off tunnistus koskettimiin?

jumap commented 9 years ago

Koskettimistot toimisivat ainoastaan midiohjaimina. Syntetisaattoriominaisuuksia ei tarvi.

Jos löytäisin helpon ja luotettavan midi-usb-kytkennän, voisi muunnospiirin kai tehdä itsekin Tai jos midi shield ei hyydytä järjestelmää, sitä voisi käyttää.

Kosketuksen tunnistava koskettimisto on pyörinyt ajatuksissani. Tällöin pitäisi pystyä lukemaan velocity-arvo. Antureita (diodi plus tunnistin) pitäisi olla 2 kpl per kosketin.

Yhtäaikaisten äänien määrä saattaa olla jopa 12 kerrallaan (teoreettinen kykyjeni yläraja: sormet ja jalkapari, ei varpaita :)), paitsi jos klustereita soittaa, niin enemmän... Jos lähdetään siitä, että soitin ei ole soittajalle esteenä, olipa soittajana kuka hyvänsä, laitteen pitäisi pystyä viestimään sekunnissa jopa 20 peräkkäistä ääntä (note on, note off). Tämä koettelee kyllä jo itse rakennetun koskettimistonkin rajoja. Ymmärsin niin, että arduino skannaa koko 61 koskettimen matriisin läpi n. 60 mllisekunnissa. Jos velocityarvo luetaan (anturipari), aikaa kuluu 120 ms. Tällöin juoksutuksessa voisi olla n. 8 nuottia sekunnissa. Laskinko oikein? Minun taitotasollani tuo riittää... Mutta joissakin kohtaa voi ääniä tipahdella pois.

Sitten pitänee laittaa kontrolleri erikseen joka koskettimistolle, jotta systeemi ei rupeaisi takkuamaan. Ja hinta nousee...

Olisiko hyötyä, jos koskettimistokohtaiset kontrollerit välittävät midi-datan arduinopohjaiselle keskittimelle, josta välitetään tieto tietokoneelle?

Soundipankista (urkujen äänikerrat), joka on talletettu ääninäytteinä tietokoneen ohjelmaan, valitaan kerrallaan soitettavat yhdistelmät ja voidaanpa niitä vaihtaa kesken soitonkin. Tämäkin pitäisi saada viestittyä kontrollerin kautta tietokoneelle. Tällöin äänikertavalitsimet voisivat näkyä yhtenä koskettimistona, mutta käskyt määritellään soundipankkiin äänikerta päälle / pois.

Tuumailin, että mitä jos paisutuskaapin simuloisi jotenkin niin, että lukisi potentiometriltä arvot, asettaisi arvojen pohjalta midin äänenvoimakkuusviestille sopivat volyymirajat ja liittäisi siihen jollakin tavoin diskanttivaimentimen (suuri resistanssi, suuri vaimennus). Tarkoitus olisi myös saada vaimennus jyrkimmäksi "kaapin ollessa kiinni tai melkein kiinni".

Muuten, olisiko järkevää suunnitella ja rakentaa atmega-piirien ympärille omat piirikortit, ladata vain ohjelma arduinossa kiinni olevalle piirille, minkä jälkeen siirtäisin kontrollerin omalle piirikortilleen.

jumap commented 9 years ago

Huomasin ucapps.de -sivustolla MIDIbox -alustan /MIDI-sillan, jonka tyyppisen sarjaliittymän laitteen käytöstä projektissani kiinnostuin. Sivulla oli kaavio, jossa I2C-väylään liitetään MIDI-soittimia masterille (mikrokontrolleri). Sivustolla oli ratkaisuja PIC-, LPC17- ja STM32F4- pohjaisille kontrollereille. Selviäisikö samoilla kytkentäkaavioilla Arduinon kanssa? Jos tämä onnistuisi pienillä muutoksilla, valmis riiriratkaisu olisi tässä, muuten pitänee löytää piirikaavio MIDI-matriisin jälkeiselle liittymälle sarjaväylään. Oman suunnitteluun taitoni eivät riittäne... Ja melkein valmis ohjelma (tai ainakin toimiva malli) pitää löytää.

(Btw, LPC17- ja STM32F4- ohjausyksikkö muistutti jonkin verran Arduinon piirilevyjä. Olisiko muuta sukulaisuutta?)

SIvun kaavion mukaisesta järjestelmästä tulisi selkeä. Tämä kai toimisi myös minun projektissani? Neljä koskettimistoa (yht. ~215 kytkintä, 1-2 sormiota volyymi-/sävysäädöllä) liitettäisiin orjana masteriin (Arduino). Vaikuttaako kontrollerissa / väylässä olevien kytkimien määrä MIDI-järjestelmän skannausnopeuteen?

Muistelen, että joku malli Arduinon "sukulaismalli" on kellotettu suuremmille kellotaajuuksille ja oli suuremmalla muistimäärällä kuin Uno ja Mega. Mikä?

Tuntuisi järkevältä, että soundivalinta hoidettaisiin omaa väyläänsä pitkin. Soitto (musiikki) omalla väylällään ja soittimet (äänikerrat) omalla väylällään - jo loogisen jaottelun vuoksi? Voisiko tällä tavalla selvitä Arduino Unon pinnimäärällä ?

SPI-väylä on tiettävästi nopeampi kuin I2C, mutta onko hyödyksi käyttää projektissani sitä?

Tässä liuta kysymyksiä, ja lisää riittää, kun hoksaa...

Robojuchen commented 9 years ago

voisitko linkittää sen kytkentäkaavion kun en sitä löydä. Pikaisella silmäyksellä katselin että eikö noita näppäinmatriiseja lueta shiftregistereillä. I2c tai spi vaatisi että joku toinen mikrokontrolleri lukee noita nappeja ja lähettää tiedon arduinolle.

Arduino due on nopea (82mhz) arduino. Megassa ja duessa on monta sarjaportti piiriä joten niihin saisi useita rinnakkaisia MIDI väyliä. En tullutkaan tätä ajatelleeksi aiemmin. Jokainen väylä tarvitsee tietenkin oman midi to usb piirin ja olettettavasti pc-softasi pystyy lukemaan montaa midilaitetta yhtä aikaa?

jumap commented 9 years ago

Kuva löytyi ucapps.de -sivustolta: http://www.ucapps.de/mbhp_iic_midi.html. Vaihtorekisteri on täällä: http://www.ucapps.de/mbhp_dio_matrix.html. 74HC165-piirillä voinee toteuttaa omankin.

jumap commented 9 years ago

Löysin tuolta (https://teensyhauptwerk.wordpress.com/2014/01/17/pedalboard-encoder/) tällaisen, ymmärrettävän jalkioenkooderiohjelman. Toimisiko tämä suoraan?Muutettavat muuttaen voisi kokeilla 61 koskettimen koskettimistolla? Pitäisi vain vaihtaa eri boardeilla olevat kanavat omikseen.

Viittaavatko nuo usbMIDI.sendNote* -komennot siihen, että boardi tunnistuisi suoraan usb:lla midiohjaimeksi?

//SET MIDI CHANNEL const int midichannel=1;

//array to hold button status boolean pressed[34];

// the note value each pin send, needed to 'skip' pin 13 byte notevalue[34] = { 60,61,62,63,64,65,66,67,68,69,70,71,72,0,73,74,75,76,77,78,79,80,81,82,83,84,85,86,87,88,89,90,91,92 };

// the setup routine runs once when you press reset: void setup() {

// initialise appropiate pins as inputs, skipping any that aren't used for (int pin=0 ; pin < 34; pin++) {
if (notevalue[pin] != 0) { pinMode(pin,INPUT_PULLUP); } } }

// the loop routine runs over and over again forever: void loop() { for (int pin=0 ; pin < 34; pin++) {
//if pin is LOW (pressed) and pin is not already marked as pressed, then send MIDI NOTE ON if (notevalue[pin] != 0) { if ((! digitalRead(pin)) && (pressed[pin] == false)) { usbMIDI.sendNoteOn(notevalue[pin],99,midichannel); pressed[pin]=true; //debounce a bit delay(25); }

  //if pin in question is HIGH, and has recently been LOW  then reset "pressed"
  if ( (digitalRead(pin)) && (pressed[pin]==true) ) {
    pressed[pin]=false; 
    usbMIDI.sendNoteOff(notevalue[pin],99,midichannel);
  }
}

}

usbMIDI.send_now(); // don't let any incoming MIDI build up, drain it! while (usbMIDI.read()) { } }

jumap commented 9 years ago

Teensyn koodit eivät näyttäneet toimivat. Samoin komennot MIDI.begin tms. toivat ilmoituksia "was not declared...", vaikka olin sisällyttänyt #include-komennolla ja oikeaan kansioon MIDI.h -tiedoston. Kummastuttaa...

USB:n kautta toimivia midi-kontrollereita ja niiden sketsejä oli mm. seuraavilla sivuilla: http://www.instructables.com/id/Turn-your-Arduino-Uno-into-an-USB-HID-Mididevice/ http://cryptomys.de/horo/V-USB-MIDI/ https://sites.google.com/site/bharatbhushankonka/home/diy-midi-over-usb-using-arduino-uno http://hunt.net.nz/users/darran/weblog/52882/Arduino_UNO_MIDI_USB_version_02.html

Kannattaisiko jotain noista lähteä kokeilemaan, jottei tarvi käyttää MIDI-USB -konvertteria?

jumap commented 8 years ago

Rakentelin piiriä hall-sensorien lukemiseen- Mallin ja koodin otin sivustolta http://www.codetinkerhack.com/2012/11/how-to-turn-piano-toy-into-midi.html ja muokkasin niitä hall-sensoreilla toimivaa kytkinmatriisia varten (Arduino -opassivuston. Hall-sensorimatriisin rakensin kuvan mukaan niin, että vaihtorekisteripiiri (hc595 - serial in - parallel out) ajaa sarjadatan vuorollaan kullekin Q-liitännälle ja samalla matriisin sarakkeille (high). Matriisin riveiltä luetaan, minkä sensorin tila on vedetty alas (low). Tämä tapa koskettimiston lukemiseen on esitelty sivulla Samantapaisen kytkennän rakensin jo aiemmin ja sain siitä sarjaporttiin muuttuvia lukemia. Nyt sarjaportti ei näytä yhtään mitään.

Osaatko sanoa, mikä tässä mättää?

Ehkä koodi voisi olla selkeämpikin, ja kannattaisi käyttää midi-kirjastoa...

16 hall sensor matrice - hc595 - codetinkerhack piano toy- edited_bb

Koodi on tässä:

include

// Pin Definitions // Rows are connected to const int row1 = 5; const int row2 = 6; const int row3 = 7; const int row4 = 8;

// The 74HC595 uses a serial communication // link which has three pins const int clock = 9; const int latch = 10; const int data = 11;

//software serial SoftwareSerial midiSerial(2 , 3); // digital pins that we'll use for soft serial RX & TX

uint8_t keyToMidiMap[16];

boolean keyPressed[16];

int noteVelocity = 127;

// use prepared bit vectors instead of shifting bit left everytime int bits[] = { B00000001, B00000010, B00000100, B00001000, B00010000, B00100000, B01000000, B10000000 };

// 74HC595 shift to next column void scanColumn(int value) { digitalWrite(latch, LOW); //Pulls the chips latch low shiftOut(data, clock, MSBFIRST, value); //Shifts out the 8 bits to the shift register digitalWrite(latch, HIGH); //Pulls the latch high displaying the data }

void setup() {

// Map scan matrix buttons/keys to actual Midi note number. Lowest num 41 corresponds to F MIDI note.
keyToMidiMap[0] = 44;
keyToMidiMap[1] = 41;
keyToMidiMap[2] = 42;
keyToMidiMap[3] = 43;

keyToMidiMap[4] = 48;
keyToMidiMap[1 + 4] = 45;
keyToMidiMap[2 + 4] = 46;
keyToMidiMap[3 + 4] = 47;

keyToMidiMap[8] = 52;
keyToMidiMap[1 + 8] = 49;
keyToMidiMap[2 + 8] = 50;
keyToMidiMap[3 + 8] = 51;

keyToMidiMap[12] = 56;
keyToMidiMap[1 + 12] = 53;
keyToMidiMap[2 + 12] = 54;
keyToMidiMap[3 + 12] = 55;

/*keyToMidiMap[16] = 64;
keyToMidiMap[1 + 16] = 57;
keyToMidiMap[2 + 16] = 58;
keyToMidiMap[3 + 16] = 59;
keyToMidiMap[4 + 16] = 60;
keyToMidiMap[5 + 16] = 61;
keyToMidiMap[6 + 16] = 62;
keyToMidiMap[7 + 16] = 63;

keyToMidiMap[24] = 72;
keyToMidiMap[1 + 24] = 65;
keyToMidiMap[2 + 24] = 66;
keyToMidiMap[3 + 24] = 67;
keyToMidiMap[4 + 24] = 68;
keyToMidiMap[5 + 24] = 69;
keyToMidiMap[6 + 24] = 70;
keyToMidiMap[7 + 24] = 71;

*/ // setup pins output/input mode pinMode(data, OUTPUT); pinMode(clock, OUTPUT); pinMode(latch, OUTPUT);

pinMode(row1, INPUT);
pinMode(row2, INPUT);
pinMode(row3, INPUT);
pinMode(row4, INPUT);

// Serial.begin(31250); // Serial.begin(9600); // Set MIDI baud rate: Serial.begin(9600); midiSerial.begin(31250); delay(1000);

}

void loop() {

for (int col = 0; col < 4; col++) {

    // shift scan matrix to following column
    scanColumn(bits[col]);

    // check if any keys were pressed - rows will have HIGH output in this case corresponding
    int groupValue1 = digitalRead(row1);
    int groupValue2 = digitalRead(row2);
    int groupValue3 = digitalRead(row3);
    int groupValue4 = digitalRead(row4);

    // process if any combination of keys pressed
    if (groupValue1 != 0 || groupValue2 != 0 || groupValue3 != 0
            || groupValue4 != 0) {

        if (groupValue1 != 0 && !keyPressed[col]) {
            keyPressed[col] = true;
            noteOn(0x91, keyToMidiMap[col], noteVelocity);
        }

        if (groupValue2 != 0 && !keyPressed[col + 4]) {
            keyPressed[col + 8] = true;
            noteOn(0x91, keyToMidiMap[col + 4], noteVelocity);
        }

        if (groupValue3 != 0 && !keyPressed[col + 8]) {
            keyPressed[col + 16] = true;
            noteOn(0x91, keyToMidiMap[col + 8], noteVelocity);
        }

        if (groupValue4 != 0 && !keyPressed[col + 12]) {
            keyPressed[col + 24] = true;
            noteOn(0x91, keyToMidiMap[col + 12], noteVelocity);
        }

    }

    //  process if any combination of keys released
    if (groupValue1 == 0 && keyPressed[col]) {
        keyPressed[col] = false;
        noteOn(0x91, keyToMidiMap[col], 0);
    }

    if (groupValue2 == 0 && keyPressed[col + 4]) {
        keyPressed[col + 8] = false;
        noteOn(0x91, keyToMidiMap[col + 4], 0);
    }

    if (groupValue3 == 0 && keyPressed[col + 8]) {
        keyPressed[col + 16] = false;
        noteOn(0x91, keyToMidiMap[col + 8], 0);
    }

    if (groupValue4 == 0 && keyPressed[col + 12]) {
        keyPressed[col + 24] = false;
        noteOn(0x91, keyToMidiMap[col + 12], 0);
    }

}

}

void noteOn(int cmd, int pitch, int velocity) {

midiSerial.write(cmd);
midiSerial.write(pitch);
midiSerial.write(velocity);

   //prints the values in the serial monitor so we can see what note we're playing
Serial.print("cmd: ");
 Serial.print(cmd);
   Serial.print(", pitch: ");

Serial.print(pitch); Serial.print(", velocity: "); Serial.println(velocity);

/* Serial.write(cmd); Serial.write(pitch); Serial.write(velocity);

Serial.print(cmd); Serial.print(pitch); Serial.println(velocity); */ } Muokkaamani koodi on tässä:

oyli commented 8 years ago

Olen tässä viime aikoina ajatellut itsekin tälläisten urkujen rakentamista ja tämä keskustelu on ollut suureksi avuksi asiaan perehtymisessä.

Sellainen pikku ongelma on kuitenkin, että mistä nuita koskettimistoja kannattais lähtä katteleen? Tarkotus olis että tuntuma olisi mahdollisimman aito eikä olis pahitteeksi jos hintakaan ei montaa sataa olis.

http://www.johnsorganworks.co.uk/ myy valmiita midi tulolla olevia konsoleita, mutta hinta on vähän turhan korkea ja lisäksi siinä pääsis vähän turhan helpolla koko hommasta.

Joten olisiko jotain suuntaa antavaa vinkkiä tähän ongelmaan.

jumap commented 8 years ago

Olen rakentamassa itse sormioita, mikä on osoittautunut aikaa vieväksi, suuritöiseksi projektiksi. Suureksi avuksi suunnittelussa on ollut Stuart C. Blanchardin sivut: http://stuartblanchard.com/virtual-pipe-organs/. Muun koskettimistosuunnittelun olen tehnyt tarkastelemalla kirkkojen soittimien rakennetta, useiden nettisivujen rakenne- ja valokuvien sekä aiemman tietoni perusteella. Moni rakentaja on käyttänyt koskettimistoja halvoista midisoittimista ja modannut de tarpeisiinsa. Vidal Fagerjord on rakentanut ainakin jalkion kokonaan itse (http://www.fagerjord.org). Myös Lars Palo on rakentanut virtuaaliurut käyttämällä syntikoiden koskettimistorakenteita ja komponentteja sekä rakentanut itse jalkion (http://www.familjenpalo.se/vpo).