Stredná priemyslená škola Elektrotechnická Prešov Plzenská 1, Prešov STREDOŠKOLSKÁ ODBORNÁ ČINNOSŤ č. odboru: 12 Elektrotechnika a hardware MIDI Controller 2013 riešitelia Matej Semančík Prešov ročník štúdia : štvrtý
Stredná priemyslená škola Elektrotechnická Prešov
Plzenská 1, Prešov
STREDOŠKOLSKÁ ODBORNÁ ČINNOSŤ
č. odboru: 12
Elektrotechnika a hardware
MIDI Controller
2013
riešitelia
Matej Semančík
Prešov
ročník štúdia : štvrtý
Stredná priemyslená škola Elektrotechnická Prešov
Plzenská 1, Prešov
STREDOŠKOLSKÁ ODBORNÁ ČINNOSŤ
č. odboru: 12
Elektrotechnika a hardware
MIDI Controller
2013
riešitelia
Matej Semančík
Prešov Zriaďovateľ
ročník štúdia : štvrtý
Prešovský samosprávny kraj školiteľ Mgr. Ján Benko, PhD.
Čestné vyhlásenie
Vyhlasujem, že celú prácu stredoškolskej odbornej činnosti na tému „Názov
práce“ som vypracoval/a samostatne, s použitím uvedenej literatúry. Som si vedomý
zákonných dôsledkov, ak v nej uvedené údaje nie sú pravdivé.
Prešov, 15. január 2013 ..........................................
vlastnoručný podpis
Obsah
Úvod ...................................................................................................................................... 5
1 Cieľ a metodika práce ...................................................................................................... 6
2 Teoretická časť ................................................................................................................. 8
2.1 MIDI ....................................................................................................................... 8 2.1.1 MIDI Správa .................................................................................................... 8 2.1.2 Spôsob posielania MIDI správ ...................................................................... 10
3 Vlastná práca .................................................................................................................. 11
3.1 Doska plošného spoja ........................................................................................... 14 3.2 Program pre Arduino ............................................................................................ 16
3.2.1 Triedy ............................................................................................................ 16
4 Praktická časť práce ...................................................................................................... 17
4.1 Funkčné modely, technické zariadenia a iné súčasti práce ................................... 17
4.1.1 Plošný spoj ..................................................................................................... 17 4.1.2 Konštrukcia .................................................................................................... 17
5 Výsledky .......................................................................................................................... 20
6 Závery práce ................................................................................................................... 21
Zhrnutie .............................................................................................................................. 22
Prílohy ................................................................................................................................ 23
5
Úvod
V dnešnej dobe sa dá drahá hudobná technika ľahko nahradiť lacnejšími alternatívami,
mám na mysli mixéry, prehrávače a iné zariadenia, ktoré sa používajú pri mixovaní hudby
– na festivaloch, diskotékach a iných podujatiach. Dá sa nahradiť počítačmi, je to
univerzálne a hlavne lacnejšie. Existuje veľa aplikácií, ktoré sa zameriavajú práve na
mixovanie hudby, poskytujú všetko, čo poskytuje drahý profesionálny hardware – CD
prehrávače, mixážny pult, atď., taktiež tu odpadá nevýhoda množstva káblov. Medzi takéto
aplikácie patrí napríklad Traktor (Native Instruments), Virtual DJ (Atomix Productions)
ale aj open-source aplikácie, ako napríklad Mixxx. Celé spracovanie zvuku prebieha
v aplikácii a výsledkom je už len výstup zvukovej karty. Je to v podstate celý mixážny
pult, len v digitálnej podobe. Tu sa ale naskytá otázka – ako ovládať takýto program ?
Hardware sme nahradili softwarom, predtým sme mali ruky, fyzické tlačidlá,
potenciometre, enkódery. Teraz máme to isté, len virtuálne. Myš je dosť obmedzujúca keď
príde na ovládanie takýchto aplikácií, hlavne, ak treba robiť viac vecí naraz. Práve pre túto
potrebu sa začali vyrábať MIDI controllery. Ich jedinou úlohou je ovládať takéto aplikácie.
Fyzicky sa podobajú na mixážny pult, no fungujú iba ako ovládač, nemajú väčšinou žiadne
audio vstupy/výstupy (až na tie prepracovanejšie), všetko čo je potrebné je iba USB port na
pripojenie k PC a niekedy aj sieťový adaptér. Ako tému som si vybral výrobu takéhoto
MIDI controllera, pretože ma táto tématika zaujíma. Vždy som si chcel vyskúšať
mixovanie hudby, no výbava je drahá, aj preto veľa ľudí siahne po takomto riešení.
V podstate im stačí len PC a MIDI controller.
6
1 Cieľ a metodika práce
Mojou úlohou je vytvoriť MIDI controller, „mozgom“ celého zariadenia bude Arduino
UNO R3 s osadeným procesorom ATmega328. Arduino som si zvolil práve preto, že som
ho mal k dispozícii už dlhšiu dobu. Je ľahko programovateľné cez USB port a poskytuje
široké spektrum využitia. Arduino osadím na dosku plošného spoja, navrhnutú v EAGLE.
Arduino bude po sériovej linke komunikovať s počítačom, na ktorom pobeží Serial-MIDI
konvertor – ten prepošle dáta zo sériovej linky do virtuálneho MIDI portu počítača, takže
aplikácia používajúca MIDI controller s ním bude vedieť komunikovať. Je to trochu
zložitejšie, ale nakoľko Arduino UNO sa nevie správať ako plug-and-play zariadenie,
budem to riešiť pravdepodobne takto. Ďalšou možnosťou je preprogramovať sériový
prevodník na Arduine (integrovaný obvod zabezpečujúci sériovú komunikáciu s
počítačom, Atmega 16U2), tak, aby sa správal ako plug-and-play MIDI zariadenie. Na to
je však potrebný externý programátor.
Controller bude mať viacero ovládacích prvkov. Na rozšírenie digitálnych vstupov
použijem paralelno-sériové posuvné registre 74HC165N, na rozšírenie analógových
vstupov použijem analógové multiplexory/demultiplexory HCF4051BE, controller bude
tiež obsahovať 2 rotačné enkódery, na ich obsluhu použijem hardvérové prerušenia v
Arduine. Celý MIDI controller bude osadený v plechovo-drevenom pulte, ovládacie prvky
budu osadené na vrchnej plechovej doske, v ktorej budú vyrezané diery na tlačidlá a
ostatné súčiastky pomocou CNC. Tá sa osadí na drevenú konštrukciu, na zadnej strane
bude vyrezaná diera pre USB port Arduina, ktoré bude osadené na plošnom spoji vnútri
pultu.
Ako aplikáciu pre mixovanie hudby používam Traktor 2 od Native Instruments, je to moja
osobná preferencia a každý ju ma inú, existuje veľa iných platených, či freeware/open-
source aplikácií, ktoré dokážu pracovať s MIDI, no všetky pracujú na rovnakom princípe.
Pre tlačidlá/klávesy je správne použiť Note On/Off MIDI správy. Jedna sa pošle pri
stlačení a druhá pri pustení tlačidla. Pre potenciometre a iné súčiastky, ktoré nevyžadujú
takúto funkcionalitu sa používa Control Change správa. Posiela sa iba raz a nesie so sebou
určitú hodnotu (potenciometra, akým smerom sa otáča enkóder, atď). V aplikácii si už len
namapujeme jednotlivé tlačidlá, potenciometre, resp. MIDI správy na určitú funkciu danej
aplikácie, väčšinou v MIDI nastaveniach. Preto je MIDI controller univerzálne zariadenie.
Dá sa použiť na ovládanie hociakej aplikácie podporujúcej MIDI, stačí si len priradiť
7
jednotlivé ovládacie prvky controllera na funkcie v aplikácii, ako je napríklad začatie
hudobnej stopy, alebo zapnutie filtra tlačidlom, potenciometre sa dajú namapovať na
ekvalizér alebo intenzitu efektu a podobne.
8
2 Teoretická časť
2.1 MIDI
MIDI je skratkou pre Musical Instrument Digital Interface, čo sa dá preložiť ako
digitálne rozhranie pre hudobné zariadenia.
MIDI sa skladá z 2 hlavných častí:
1. Jazyk, pozostávajúci z MIDI správ alebo príkazov
2. Detaily elektrického prenosu, posielania a príjimania týchto správ a príkazov
MIDI sa používa v rôznych zariadeniach. MIDI zariadenie je hocičo, čo má MIDI
rozhranie, ako napríklad MIDI klávesy, syntetizátory, MIDI controllery alebo počítačové
USB MIDI rozhranie.
MIDI neprenáša zvuk samotný, MIDI slúži iba na prenos informácií. MIDI zariadenia si
posielajú informácie o tom, aké tlačidlo/kláves bol stlačený a akou silou (využívané pri
klávesách), akú hodnotu má potenciometer, všeobecne - informácie o ovládacom prvku
daného zariadenia. Druhé zariadenie tieto informácie prijíma a podľa nich vykonáva ďalšie
úkony, napríklad zahraje tón o určitej výške alebo zmení vlastnosť zvuku, atď. Ďalej si
zariadenie vymieňajú informácie potrebné na ich synchronizáciu alebo nastavenie –
napríklad príkaz na vyresetovanie stavu všetkých tlačidiel.
Všetky MIDI zariadenia komunikujú výlučne sériovo a rýchlosťou 31250 baudov (bit/s).
Pre MIDI sa štandardne používa 5-pinový MIDI konektor, avšak, vie komunikovať aj cez
USB, keďže USB je schopné sériovej komunikácie.
4 ... +5V
2 ... GND
5 ... sériový výstup
ostatné piny sú nepripojené
Obr. 1 - MIDI konektor
2.1.1 MIDI Správa
MIDI správa sa skladá z 2 a viac bajtov, pričom prvý bajt je stále stavový bajt (status byte),
ten sa stále začína 1, napr. 10010000, a preto môže mať dekadickú hodnotu 128-255. Za
ním nasledujú dátové bajty, začínajú sa na 0, takže ich hodnota sa pohybuje v rozmedzí 0 –
127.
9
2.1.1.1 Stavový bajt
Stavový bajt hovorí o type správy, ktorá sa posiela, napr. číslo 144 – 10010000 - Note On
(stlačili sme tlačidlo), 128 – 10000000 – Note Off (pustili sme tlačidlo). Stavový bajt je
rozdelený na 2 časti – 2 krát po 4 bity, prvé 4 bity označujú typ správy, posledné 4 bity
označujú MIDI kanál, takže napríklad 10010001 bude znamenať že sa pošle Note On na
kanáli 2. MIDI ma celkovo 16 kanálov, na ktorých sa môže prenášať správa.
Obr. 2 – Príklady stavového bajtu
Existuje viacero typov správ, medzi tie, ktoré budeme používať patrí Note On, Note Off
a Control Change. Každá z nich sa začína iným stavovým bajtom.
Note On/Off budeme používať pri tlačidlách. Note On sa začína hodnotou 144 (Kanál 1)
a podľa toho, na akom kanáli sa posiela, môže mať najvyššiu hodnotu 159 (kanál 16). Note
Off má číslo 128 až 143 podľa kanálu. Control Change budeme používať pri
potenciometroch a enkóderoch. Stavový bajt pre Control Change sa začína číslom 176,
max. hodnota je 191 na kanáli 16. Všetky MIDI správy budeme posielať na prvom kanáli.
2.1.1.2 Dátový bajt
Dátový bajt obsahuje dáta danej správy, podľa toho, o aký typ správy ide. Pri tlačidlách
alebo klávesách (Note On/Off) sa posielajú min. 2 dátové bajty, pričom prvý obsahuje
číslo noty/tlačidla a druhý silu stlačenia v rozsahu 0-127. Pri Control Change sa posielajú 2
dátové bajty, prvý obsahuje číslo ovládacieho prvku (potenciometra) a druhý jeho hodnotu
v rozsahu 0-127. Dátové bajty môžu mať najvyššiu hodnotu 127, pretože hodnota 128 by
už znamenala, že sa jedná o stavový bajt.
Obr. 3 - Príklad MIDI správy po stlačení klávesy – nota číslo 5 a plná sila (127)
10
2.1.2 Spôsob posielania MIDI správ
V prvých verziách programu sme tlačidlá riešili cez Control Change, ale ukázalo sa to ako
veľmi nespoľahlivé. Pretože tačidlo bolo aktivované len raz a druhé zariadenie, resp.
aplikácia bežiaca na PC stále počítala s tým, že tlačidlo sme stlačili len raz, nedali sa
využiť funkcie spojené s držaním tlačidla. Preto sme začali používať Note On/Off. Keď je
tlačidlo stlačené, pošle sa Note On správa a aplikácia vie, že tlačidlo bolo stlačené. Keď
tlačidlo pustíme, pošle sa Note Off. To sprístupňuje napríklad použitie Shift tlačidla na
MIDI controlleri. Pre potenciometre a enkódery stačí použiť Control Change, keďže sa tam
hodnota mení iba jednorázovo.
11
3 Vlastná práca
Na začiatku sme si začali zháňať informácie o našom projekte na internete. Nainštalovali
sme si virtuálne MIDI rozhranie, Serial-MIDI konvertor a začali sme pracovať na
programe pre Arduino. Najprv sme si zapojili pár tlačidiel cez demultiplexor k Arduinu a
začali sme testovať MIDI komunikáciu s PC. Po dlhom skúšaní a zisťovaní informácií na
rôznych fórach sme dospeli k univerzálnej funkcii pre posielanie MIDI správ z Arduina.
void MidiTX(unsigned char StatusByte, unsigned char Note, unsigned char Val)
{
Serial.write(StatusByte);
Serial.write(Note);
Serial.write(Val);
}
Táto funkcia pošle dáta cez serial reprezentované ako bajty, ak by sme použili funkciu
print(), správa by nebola v správnom formáte. Prijatie správne formátovanej MIDI správy
signalizuje Serial-MIDI konvertor zablikaním indikačných svetielok na zeleno.
Ďalej sme skúšali zapojenie tlačidiel cez paralelno-sériový posuvný register, napísali sme
si vlastný kód a vyskúšali sme registre zreťaziť. Všetko fungovalo ako malo, takže sme sa
na tlačidlá rozhodli použiť registre a na potenciometre demultiplexory, nakoľko sú
analógové.
Ak sme chceli použiť enkódery, museli sme použiť hardvérové prerušenia na Arduine.
Arduino UNO ich má len 2 na pine 2 a 3. Hardvérové prerušenia sme použili kôli tomu,
aby bolo čítanie z enkóderov presné, nakoľko sa hodnoty menia veľmi rýchlo. Enkóder
generuje signál s obdlžníkovým priebehom. Keďže sme použil 2 enkódery, 1 pin
z obidvoch enkóderov sme napojil na pin prerušenia a prerušenia sme nastavili na
vzostupnú alebo zostupnú hranu.
12
Enkóder generuje takýto priebeh:
Obr. 5 – Signál generovaný enkódermi
Z obrázku je vidieť, ako enkóder generuje signál z dvoch pinov (A a B) pri točení
v rôznych smeroch. Priebehy sa dajú zameniť, ak vymeníme piny, taktiež to záleží od typu
enkódera. Prerušenie sme nastavili na vzostupnú hranu, po prerušení sa spustí nami
deklarovaná funkcia, v ktorej zistíme stav druhého pinu, ak je na obidvoch pinoch rovnaký
potenciál, znamená to, že otáčame enkóderom proti smeru hodinových ručičiek, ak nemajú
rovnaký potenciál, znamená to opak. Poďľa toho vieme zistiť, kedy sme enkóderom otočili
a vieme poslať MIDI správu, ak sa enkóder otáča proti smeru hod. ručičiek, posielame
Control Change s hodnotou 0, ak sa točí v smere hod. ručičiek, posielame Control Change
s hodnotou 127.
13
Ďalej nasledoval návrh celého zariadenia:
Obr. 6 – Návrh zariadenia
Na návrh sme použili Adobe Photoshop, pričom sme sa snažili priblížiť čo najviac finálnej
podobe zariadenia. Taktiež sme vypracovali vektorový návrh, ktorý slúžil na CNC rezanie
do vrchnej plechovej časti zariadenia, na tento návrh sme použili voľne dostupný program
Inkscape, výsledný dokument obsahuje presné rozmery na desatiny milimetra, takže
rezanie bolo presné, dokument sme exportovali tak, aby sa dal použiť v AutoCAD-e,
nakoľko to vyžadovali vo firme, kde prebiehalo rezanie.
Obr. 7 – Vektorový návrh, určený na rezanie
14
3.1 Doska plošného spoja
Neoddeliteľnou súčasťou tohto zariadenia je doska plošného spoja. Na návrh sme použili
Eagle, na plošnom spoji je vyhradené miesto pre Arduino, ktoré sa zasunie priamo na piny
na plošnom spoji. Na doske plošného spoja sú umiestnené všetky integrované obvody
spolu s obvodom pre enkódery, ktorý zabezpečuje presnejšie čítanie – RC filter. Plošný
spoj je navrhnutý tak, aby sme šetrili leptací roztok, takže tam, kde je voľné miesto sú
medené plochy, ktoré sú zároveň spojené so zemou.
Obr. 8 – Doska plošného spoja
Na obrázku je znázornená doska plošného spoja. Bola navrhovaná obojstranne, na obrázku
su znázornené len spodné cesty, cesty ktoré nie sú znázornené sú pospájané prepojkami na
spodnej strane plošného spoja. K týmto cestám patrí napájanie integrovaných obvodov,
výstup z posuvných registrov a cesta pre jeden adresovací pin demultiplexorov.
Hodnoty rezistrov pri tlačidlách nie sú podstatné, rezistory slúžia iba na pripojenie tlačidiel
na zem, takže pri stlačení tlačidná nenastane skrat, pretože medzi pinom a zemou je
rezistor.
15
Obr. 9 – Logická schéma zapojenia
16
3.2 Program pre Arduino
Program sme rozdelili do viacerých súborov pre prehľadnosť programu - napísali sme si
hlavičkové súbory pre jednotlivé triedy. Máme vytvorené triedy pre tlačidlá
a potencimetre. Program pozostáva z 3 súborov – mixer.cpp, button.h a pot.h.
Súbor mixer.cpp je hlavný súbor programu pre Arduino, stará sa o vytvorenie všetkých
objektov, nastavenia pinov, prerušení a je v ňon hlavná slučka programu, ktorá sa opakuje
až do odpojenia napájania Arduina.
Na začiatku sa spustí funkcia void setup(), v nej sa vytvoria všety objekty a priradia sa im
parametre, ako napr. ID objektu, piny, alebo spôsob akým budú pracovať. Taktiež sa tu
zapína sériová komunikácia. Baud rate sme volili väčší ako pre MIDI(31250), kôli rezerve.
Serial-MIDI konvertor bežiaci na PC sa už o správny prenos informácií do virtuálneho
MIDI rozhrania postará. Po skončení tejto funkcie nasleduje funkcia void loop(), ktorá sa
už stará o celý chod zariadenia, kontroluje zmeny na ovládacích prvkoch zariadenia, volá
jednotlivé metódy daných objektov a čo je hlavné - posiela MIDI správy po sériovej linke.
3.2.1 Triedy
Triedy sú napísané v 2 súboroch – button.h pre tlačidlá a pot.h pre potenciometre.
Trieda pre tlačidlá obsahuje 1 metódu boolean changed(), ktorá vyhodnocuje, či bolo
tlačidlo stlačené, resp. či sa zmenila jeho hodnota (napätie na pine), mení hodnotu
stavového bajtu a hodnoty, ktorá sa má poslať. Vracia hodnotu typu boolean, na základe
ktorej vie algoritmus v hlavnej slučke či má/nemá poslať MIDI správu. Pri tejto triede si
vieme špecifikovať, ako sa tlačidlo bude správať – či bude mať funkcionaltu držania
tlačidla (Note ON/Note OFF pri stlačení a pustení), alebo sa budú posielať iba Control
Change správy pri stlačení tlačidla.
Trieda pre potenciometre má tiež 1 metódu – boolean changed(), funguje rovnako ako pri
predošlej triede, tzn. že kontroluje zmenu hodnoty potenciometra a na základe toho mení
objektu jeho hodnotu, podľa toho, či je potenciometer lineárny alebo logaritmický – dá sa
to špecifikovať pri vytváraní objektu. Logaritmické potenciometre prepočítavame na
lineárne, avšak nie je to veľmi spoľahlivé, pretože hodnoty sa často veľmi rýchlo menia
v rôznych odchylkách, čo spôsobuje posielanie zbytočných MIDI správ, preto sa snažíme
používať iba lineárne potenciometre. Túto funkcionalitu sme ale v triede ponechali pre
každý prípad.
Celý zdrojový kód: viď Príloha A
17
4 Praktická časť práce
4.1 Funkčné modely, technické zariadenia a iné súčasti práce
4.1.1 Plošný spoj
Na výrobu plošného spoja sme použili metódu nažehľovania. Na laserovej tlačiarni sa
vytlačí návrh plošného spoja na mastný papier (vieme ho nájsť v niektorých časopisoch),
tento návrh sa potom nažehlí klasickou žehličkou na medenú dosku plošného spoja. Potom
sa dá celá doska vymočiť vo vode a neskôr pod tečúcou vodou zmyjeme papier z dosky,
pričom na doske ostanú nažehlené časti tvorené tonerom. Takto pripravená doska sa dá
vyleptať v roztoku na leptanie plošných spojov. Výsledkom je doska plošného spoja
pripravená na pájkovanie, takže sme osadili súčiastky a všetko napájkovali – piny pre
Arduino, pätice pre integrované obvody, rezistory a pätice pre piny súčiastok. RC filter pre
enkódery sme sa nekoniec nerozholi použiť, pretože s čítaním hodnôt z enkóderov nebol
žiadny problém.
Obr. 10 – Plošný spoj, už s osadeným Arduinom UNO
4.1.2 Konštrukcia
Pri výrobe sme začali vrchnou plechovou časťou, bola nám dodaná už nafarbená, avšak
farba zabraňovala vloženiu sčiastok, nakoľko diery boli vyrezané presne. Preto sme
odstránili farbu z otvorov. Potom sme osadili všetky súčiastky a upevnili ich. Tlačidlá sa
upevnili sami pomocou plastových vystupujúcich častí, potenciometre a enkódery sme
upevnili pomocou matíc dodaných s nimi. Potom sme pospájali všetky súčiastky káblom –
1 pin tlačidiel na +5V, potenciometre spojené tiež s +5V a zemou.
18
Obr. 11 - Vrchný plech s osadenými súčiastkami
Ďalej nasledovala výroba drevenej konštrukcie. Bočná drevená konštrukcia je vyrobená zo
štyroch kusov drevenej lišty, kt. na rohoch pospájaná samoreznými šrúbami. Na zadnej
strane je vyrezaný otvore pre USB kábel Arduina. Plošný spoj je upevnený na doske, ktorá
tvorí spodnú časť zariadenia.
Neskôr sme osadili čiapočky na potenciometre a vrchnú plechovú časť sme osadili do
drevenej konštrukcie, potom sme mohli začať spájať jednotlivé súčiastky s plošným
spojom. Na to sme použili prevažne vodiče z UTP kábla, ktoré sme napájkovali na piny po
štyroch. Piny sa potom zasunuli do pätíc v plošnom spoji.
19
Obr. 12 – Zapájanie do plošného spoja
20
5 Výsledky
Výsledkom tohto projektu je MIDI controller.
Obr. 13 – Finálna podoba zariadenia
21
6 Závery práce
Vyhotovili sme MIDI controller. Teraz ho stačí iba pripojiť k PC, zapnúť Serial-MIDI
konvertor a svoju obľúbenú hudobnú aplikáciu podporujúcu MIDI.
Všetky naše ciele boli splnené. MIDI Controller je funkčný a pripravený na použitie. Toto
zariadenie je možné použiť na rôznych hudobných akciách, ale hlavne aj pre vlastnú
potrebu.
Touto prácou sme dokázali, že aj drahšie komerčné zariadenia sa dajú pomerne ľahko
nahradiť vlastnými alternatívami.
22
Zhrnutie
Vytvorili sme MIDI Controller, zariadenie na ovládanie hudobného softvéru na PC
pomocou MIDI. Ako materiál sme použili kovový plech a drevo. Do plechu sú vyrezané
diery pre súčiastky – tlačidlá, potenciometre, enkódery, tie sú pripojené do plošného spoja,
na ktorom je osadené Arduino UNO. Arduino posiela po sériovej linke MIDI správy do
PC, kde sa o ich prevod postará Serial-MIDI konvertor, ktorý ich posiela do virtuálneho
MIDI rozhrania. Ovládacími prvkami tohto zariadenia vieme ovládať nami vybraný
softvér, ktorý podporuje MIDI komunikáciu – v našom prípade softvér na mixovanie
hudby.
23
Prílohy
Zoznam príloh:
Príloha A: Zdrojový kód programu
Príloha A: Zdrojový kód programu
//------------------------------------------------------------------------------- //mixer.cpp -- Matej Semančík, IV.S, SPŠE-PO //------------------------------------------------------------------------------- #include <math.h> #include "button.h" #include "pot.h" // Definicia tlacidiel int numButtons = 53; Button *buttons[53]; // Definicia potenciometrov int numPots = 8; Pot *pots[8]; // Enkodery piny int Enc1_A = 2; //Interrupt int Enc1_B = 4; int Enc2_A = 3; //Interrput int Enc2_B = 5; //Enkodery prerusenia void ENC1_CHANGE() { if(digitalRead(Enc1_A) == digitalRead(Enc1_B)) { MidiTX(176, 126, 0); } else { MidiTX(176, 126, 127); } } void ENC2_CHANGE() { if(digitalRead(Enc2_A) == digitalRead(Enc2_B)) { MidiTX(176, 127, 0); } else { MidiTX(176, 127, 127); } } //74HC165 posuvny register #define CLOCK 9 #define LOAD 10 #define DATA 11 //4051 (de)mux piny int A = 8; int B = 7; int C = 6; int DMX1_IN = A0; int DMX2_IN = A1; int DMX3_IN = A2; int DMX4_IN = A3; // Funkcia na posielanie MIDI sprav void MidiTX(unsigned char StatusByte, unsigned char Note, unsigned char Val) { Serial.write(StatusByte); Serial.write(Note); Serial.write(Val); }
// Obsluha multiplexora /* Nastavi jednotlive bitove vahy pinov pre vstupnu hodnotu 'ch', napr. pri ch=3 -> pin2 = 0, pin1=1, pin0=1 */ void multiplex(int ch, int pin0, int pin1, int pin2) { digitalWrite(pin0, bitRead(ch, 0)); digitalWrite(pin1, bitRead(ch, 1)); digitalWrite(pin2, bitRead(ch, 2)); } void setup() { Serial.begin(57600); // Enkodery pinMode(Enc1_A, INPUT); pinMode(Enc1_B, INPUT); pinMode(Enc2_A, INPUT); pinMode(Enc2_B, INPUT); digitalWrite(Enc1_A, HIGH); digitalWrite(Enc1_B, HIGH); digitalWrite(Enc2_A, HIGH); digitalWrite(Enc2_B, HIGH); attachInterrupt(0, ENC1_CHANGE, RISING); attachInterrupt(1, ENC2_CHANGE, RISING); // Posuvny register pinMode(CLOCK, OUTPUT); pinMode(LOAD, OUTPUT); pinMode(DATA, INPUT); digitalWrite(LOAD, HIGH); // Adresovacie piny pre multiplexor pinMode(A, OUTPUT); pinMode(B, OUTPUT); pinMode(C, OUTPUT); //Potenciometre for(int i=0; i<numPots; i++) { if(i < 8) { //pin, id, je linearny, multiplex, DEMUX 1 pots[i] = new Pot(DMX1_IN, i, LINEAR, i); } else if (i < 16) { pots[i] = new Pot(DMX2_IN, i, LINEAR, i-8); // DEMUX 2 } else if (i < 24) { pots[i] = new Pot(DMX3_IN, i, LINEAR, i-16); // DEMUX 3 } else if (i < 32) { pots[i] = new Pot(DMX4_IN, i, LINEAR, i-24); // DEMUX 4 } } //Tlacidla for(int i=0; i<numButtons; i++) { buttons[i] = new Button(i, HOLD); //id, toggle/hold } }
void loop() { //Potenciometre for(int i=0; i<numPots; i++) { multiplex(pots[i]->multiplex, C, B, A); if(pots[i]->changed()) { MidiTX(176, pots[i]->id, pots[i]->val); } } //Tlacidla - register digitalWrite(LOAD, LOW); digitalWrite(LOAD, HIGH); for(int i=0; i<numButtons; i++) { digitalWrite(CLOCK, HIGH); digitalWrite(CLOCK, LOW); buttons[i] -> val = digitalRead(DATA); if(buttons[i]->changed()) { MidiTX(buttons[i]->statusmsg, buttons[i]->id, buttons[i]->val*127); } } digitalWrite(CLOCK, HIGH); // -------------------------------------------- delay(5); /*Delay, zabranuje velmi rychlemu posielaniu MIDI sprav, niekedy to zahlcuje virtualne MIDI rozhranie, hlavne pri rychlych zmenach potenciometrov */ } //------------------------------------------------------------------------------- //button.h -- Matej Semančík, IV.S, SPŠE-PO //------------------------------------------------------------------------------- #ifndef Button_H #define Button_H #include "Arduino.h" #define TOGGLE 1 #define HOLD 0 #define NOTEON 144 #define NOTEOFF 128 #define CTRLCHANGE 176 class Button { public: int val, lastVal, id, statusmsg; boolean ena, toggleable; Button(int _id, boolean _toggleable); boolean changed(); }; Button::Button(int _id, boolean _toggleable) { id = _id; toggleable = _toggleable; statusmsg = 176;
ena = true; } boolean Button::changed() { if(toggleable) { if(ena == true && val == 1) { ena = false; return true; } else { ena = !val; return false; } } else if(!toggleable) { if(lastVal == val) { return false; } else if(val == 1 && ena == true) { ena = false; statusmsg = 144; return true; } else if(val == 0 && ena == false) { ena = true; statusmsg = 128; return true; } lastVal = val; } } #endif //------------------------------------------------------------------------------- //pot.h -- Matej Semančík, IV.S, SPŠE-PO //------------------------------------------------------------------------------- #ifndef Pot_H #define Pot_H #include "Arduino.h" #include <math.h> #define LOGARITHMIC 1 #define LINEAR 0 class Pot { public: unsigned long int val, lastVal; float valF; int pin, id, multiplex; boolean isLog; Pot(int _pin, int _id, boolean _isLog, int _multiplex); boolean changed(); }; Pot::Pot(int _pin, int _id, boolean _isLog, int _multiplex)
{ pin = _pin; id = _id; multiplex = _multiplex; isLog = _isLog; pinMode(pin, INPUT); } boolean Pot::changed() { if(!isLog) { val = analogRead(pin)/8; } else { valF = analogRead(pin)/128.0; val = pow(2, valF)/2; } if(val != lastVal) { lastVal = val; return true; } else return false; } #endif