This is an old revision of the document!
Acest proiect constă într-un mini pian, cu 8 butoane, ce poate înregistra sau reda melodii de pe un SD Card. De asemenea, există opțiunea de învățare intermediul unor LED-uri care se vor aprinde în funcție de “clapa” care trebuie apăsată.
Pentru a oferi o interfață utilizatorului, un ecran va afișa informații despre statusul board-ului şi despre fişierul curent accesat. Cu ajutorul acestui pian, se pot crea melodii simple sau poate fi considerat şi un mini-player.
Placuţa de Arduino Uno este conectată la modulul pentru card şi la ecranul LCD. Protocoalele de comnunicare folosite fiind SPI, respectiv I2C. Butoanele vor pune la dispoziţie utilizatorului, în primul rând, posibilitatea de a selecta modul de funcţionare. Acesta poate fi modul de record, modul de player sau modul de teaching. În continuare, butoanele vor simula nişte clape ale unui pian pentru a înregistra anumite sunete.
Componente folosite:
Acest piano board este bazat pe 4 moduri de functionare: FREE, RECORDING, LEARNING SI LISTEN.
1. FREE - aici utilizatorul poate apasa cele 4 butoane rosii, fiecare avand asociata o anumita nota muzicala, neexistand restrictii 2. RECORDING - se va crea un nou fisier pe cardul micro SD, iar “clapele” apasate de catre utilizator vor fi retinute, cu o limita superioara de 15 note muzicale. In fisierul text creat, va exista pe fiecare linie cate o nota muzicala 3. LEARNING - se va folosi un fisier cu note muzicale de pe cardul microSD. Cate un led se va aprinde, corespunzator cu butonul care trebuie apasat. Dupa ce toate butoanele au fost apasate asa cum e necesar, se va trece din nou in FREE MODE. 4. LISTEN - in prezent, utilitatea acestui mod este ca o melodie descarcata in format .wav va fi redata de pe microSD. O functionalitate posibil ulterioara poate fi navigarea si alegerea fisierului prin cardul microsd.
Se pot folosi cele 4 butoane rosii de pe breadbord pentru a imita clapele unui pian. Butonul galben “M” face referire la schimbarea intre modurile piano board-ului. Buton albastru are rol de selectare, de Enter Cele 2 butoane din dreapta au rolul de navigare: stanga-dreapta
In functia de setup a programului, se vor apela functii corespunzatoare, ce vor initia LED-uri, butoane, comunicarea cu LCD sau vor activa intreruperi.
1. Butoane - Pentru fiecare buton, se declanseaza o intrerupere, in care vor fi setate flag-uri sau se vor face operatiile corespunzatoare apasarii. De asemenea, fiecare buton a fost setat ca INPUT_PULLUP. Intreruperile sunt de tipul PCINT:
void setup_buttons() { pcf8574.pinMode(P0, INPUT_PULLUP, HIGH); pcf8574.pinMode(P1, INPUT_PULLUP, HIGH); pcf8574.pinMode(P2, INPUT_PULLUP, HIGH); pcf8574.pinMode(P3, INPUT_PULLUP, HIGH); for (int i = 0; i < 4; i++) { // Pin Mode Input Pullup DDRD &= ~(1 << buttons[i]); // Set default button state to high PORTD |= (1 << buttons[i]); } } void setup_interrupts() { cli(); // configurare intreruperi PCICR |= (1 << PCIE2); // enable the pin change interrupt, set PCIE2 to enable PCMSK2 scan PCMSK2 |= (1 << PCINT19); // Turns on PCINT19 (PD3) PCMSK2 |= (1 << PCINT21); // Turns on PCINT21 (PD5) PCMSK2 |= (1 << PCINT22); // Turns on PCINT22 (PD6) PCMSK2 |= (1 << PCINT23); // Turns on PCINT23 (PD7) sei(); }
2. LED-uri
void setup_leds() { for (int i = 0; i < 4; i++) { pinMode(leds[i], OUTPUT); digitalWrite(leds[i], LOW); } }
3. LCD
void setup_lcd() { lcd.begin(); //initialize the lcd lcd.backlight(); //open the backlight }
In implementarea piano board-ului, pentru intreruperile pe butoane, se tine cont de anumite flag-uri care ne spun ce mod de functionare este activat. Asadar, intr-o intrerupere, se va verifica ce buton a declansat intreruperea, fiind de tipul PCINT si se vor face operatiile corespunzatoare. In loc sa ne bazam pe un debouncer, deoarece dorim ca sunetul sa fie auzit, indiferent de intervalul la care e apasata clapa, ne bazam pe 2 variabile: buttonState si currentState. Daca acestea indica o schimbare, buttonPressed va fi activat pentru a sti ulterior daca trebuie ca butonul sa realizeze actiunea de care e “responsabil”.
int currentState[4]; for (int i = 0; i < 4; i++) { currentState[i] = PIND & (1 << buttons[i]); } for (int i = 0; i < 4; i++) { if (!currentState[i] && button_1_state == HIGH) { button_1_pressed = true; timeFromPress = actTime; lcdNote = notes[i]; } else if (currentState[i] && button_1_state == LOW) { // Check for rising edge trigger button_1_pressed = false; timeFromPress = actTime; }
Functionare GPIO Expander PCF8574T. Pentru a adauga porturile necesare tuturor butoanelor, am avut nevoie de un GPIO Expander. La pin-ul de intrerupere al acestuia, am conectat PIN-ul 2 de pe Arduino UNO. In setup-ul intreruperilor, am avut nevoie sa resetez state-ul tuturor butoanelor la state-ul anterior pentru a evita un bug care facea ca unele butoane sa ramana blocate (sa nu mai fie detectate intreruperi).
void resetPCF(bool val0, bool val1, bool val2, bool val3) { if (val0 == HIGH) { pcf8574.digitalWrite(P0, LOW); } else { pcf8574.digitalWrite(P0, HIGH); } if (val1 == HIGH) { pcf8574.digitalWrite(P1, LOW); } else { pcf8574.digitalWrite(P1, HIGH); } if (val2 == HIGH) { pcf8574.digitalWrite(P2, LOW); } else { pcf8574.digitalWrite(P2, HIGH); } if (val3 == HIGH) { pcf8574.digitalWrite(P3, LOW); } else { pcf8574.digitalWrite(P3, HIGH); } } if (pcf8574_interrupt) { bool val0 = pcf8574.digitalRead(P0); bool val1 = pcf8574.digitalRead(P1); bool val2 = pcf8574.digitalRead(P2); bool val3 = pcf8574.digitalRead(P3); if (val0 == LOW) { mode_change(); } if (val1 == LOW) { enter_press(); } if (val2 == LOW) { left_button(); } if (val3 == LOW) { right_button(); } resetPCF(val0, val1, val2, val3);
Pentru format-ul melodiilor originale de pe card, s-au folosit:
TBA