Pian electric

Introducere

Proiectul meu este, în esență, visul de a transforma o tastatură banală într‑un instrument muzical care să‑ți smulgă un zâmbet ori de câte ori ai nevoie de o pauză. Am pornit de la pasiunea pentru muzică și de la regretul că, în copilărie, n‑am putut atinge clapele unui pian adevărat. Așa s‑a născut ideea unui pian electric simplu, portabil, care să combine dexteritatea de programator cu bucuria de a improviza câteva măsuri dintr‑o melodie preferată.

Instrumentul are două moduri principale. În Free‑to‑Play poți apăsa clapele în orice ordine, lăsându‑ți imaginația să facă ce știe ea mai bine: să compună, să testeze, să greșească și s‑o ia de la capăt fără nicio presiune. Pentru cei care vor un pic de ghidaj există modul de exersare cu piese pre‑încărcate – melodii scurte, redate pas cu pas, ca să‑ți antrenezi urechea și degetele fără profesor, direct din sufragerie.

De ce cred că e util? Pentru că, atunci când lucrezi ore în șir la tastatură, pauzele scurte contează enorm. Câteva acorduri improvizate relaxează mintea, îți dau energie și, în plus, declanșează spiritul competitiv: sigur vei vrea să reinterpretezi melodia ca să sune mai curat, mai ritmat, mai „a ta”. Iar dacă îi mai atașezi un jack pentru căști sau o ieșire MIDI, brusc se deschid uși către producție muzicală serioasă – fără să pierzi farmecul jucăuș al prototipului inițial.

În fond, acest pian electric este mai mult decât un obiect: e o invitație la creativitate, la învățare prin joacă și la împărtășit momente muzicale cu prietenii. Poate că nu va înlocui niciodată un Steinway, dar cu siguranță va reaminti oricui apasă pe clape că tehnologia poate fi și caldă, și amuzantă, și surprinzător de melodioasă.

Descriere generală

Schema bloc este următoarea:

Sistemul de pian electric portabil are la bază o placă Arduino UNO (ATmega328P) şi formează un ansamblu hardware‑software compus din următoarele module interconectate:

  • Claviatură mini‑pian – 8 butoane – reprezintă cele opt note.
  • Panou de control – 2 butoane (NEXT & OK)– gestionarea meniului de pe LCD (selectarea modului Free‑Play / Practice).
  • Alimentare 5 V – poate proveni din portul USB al PC‑ului sau dintr‑un power‑bank Li‑ion; tensiunea intră direct pe pinul 5 V şi se distribuie tuturor modulelor; GND este comun pentru toate blocurile, asigurând referinţa de masă.
  • LCD 16 × 2 cu interfaţă I2C – afişează modul curent, numele melodiei selectate.
  • Registru de deplasare 74HC595 + 8 LED‑uri – 74HC595 primeşte date seriale de la Arduino şi oferă 8 ieşiri paralele (Q0‑Q7), fiecare comandând un LED aferent unei note.
  • MicroSD Module (interfaţă SPI) – permite încărcarea unor piese‑demo.
  • Piezo‑buzzer pasiv – generează sunetul notelor; fiind pasiv, frecvenţa este impusă de funcţia tone() a Arduino‑ului.
  • Arduino UNO (ATmega328P) – primeste evenimente de la butoane, actualizează LCD‑ul, controlează 74HC595‑ul şi gestionează fişierele pe card prin librăria SD.h.

Flux de lucru:

  • Utilizatorul selectează modul din butonul NEXT, confirmă cu OK.
  • Dacă este în modul Free‑Play, apăsarea unei clape trimite nota spre buzzer şi aprinde LED‑ul aferent via 74HC595.
  • Dacă este în modul Song, după ce utilizatorul alege melodia de pe card, fiecare notă din partitură aprinde pe rând LED‑ul corespunzător prin 74HC595; intensitatea LED‑ului scade treptat până când clapa este apăsată, iar dacă lumina se stinge complet înainte de apăsare, piesa se reia de la început şi pe LCD este afişat un mesaj de eroare.

Prin această arhitectură, proiectul îmbină electronică digitală (registru de deplasare, SPI, I2C) cu elemente de interfaţă om‑maşină (claviatură, butoane, buzzer, display), oferind un instrument compact care poate fi uşor extins cu funcţii MIDI sau efecte audio suplimentare.

Hardware Design

BOM:

Componenta Cantitate Loc achizitionare Datasheet
Arduino UNO R3 1 Arduino Uno Datasheet
LCD 16×2 cu interfaţă I2C 1 LCD I2C Datasheet
Registru de deplasare 74HC595 (SOIC-16) 1 Shift Register Datasheet
Modul adaptor MicroSD (SPI) 1 MicroSD module Datasheet
Piezo-buzzer pasiv 5 V 1 Buzzer Datasheet
Buton tactil 6×6 mm (note) 8 Buton Datasheet
Buton tactil 6×6 mm (NEXT, OK) 2 Buton Datasheet
LED 5 mm difuz 8 Green LEDs Datasheet
Rezistor 220 Ω / 0.25 W 8 Resistors Datasheet
Breadboard 830 de găuri 1 Breadboard Datasheet
Set jumper fire male-male 1 set Jumper male-male Datasheet

Componente utilizate:

  • Arduino UNO (ATmega328P) – Creierul proiectului: citește stările butoanelor, controlează interfața I2C (LCD), magistrala SPI (74HC595 & MicroSD), generează tonurile prin tone() și implementează logica meniului și a redării.
  • LCD 16 × 2 cu backpack I2C – Afișează starea curentă (Free-Play sau Song Mode), numele piesei selectate și mesaje de eroare sau feedback. Se conectează pe A4 (SDA) şi A5 (SCL) şi economiseşte pini faţă de un LCD paralel.
  • Registru de deplasare 74HC595 (DIP‑16) – Primeşte date seriale de la Arduino (3 pini: SER, SRCLK, RCLK) şi le converteşte în 8 ieşiri paralele, fiecare comandând un LED. Permite controlul a 8 LED-uri cu doar 3 pini Arduino.
  • Modul MicroSD (interfață SPI, 5 V tolerant) – Găzduiește piesele în fișiere .TXT pe card. Arduino-ul citește lista și conținutul lor prin interfața SPI, permițând redarea demo-urilor.
  • Piezo‑buzzer pasiv 5 V - Transduce semnalele PWM (tone(pin, frecvență)) în sunete pentru notele muzicale, fără electronica de generare a frecvenței la nivel intern.
  • 8× butoane tactile 6 × 6 mm – claviatură note - – Butoane dedicate notelor: la apăsare, Arduino citește intrarea LOW, calculează frecvența și declanșează LED-ul și buzzer-ul.
  • 2× butoane tactile 6 × 6 mm – control (NEXT, OK) – Controlul meniului:
    1. NEXT cicălește opțiunile (Free-Play vs Song-Mode, lista de melodii)
    2. OK confirmă selecția și revine la meniu.
  • 8× LED‑uri 5 mm (difuze, orice culoare) – Semnalizează vizual nota curentă (în Free-Play) sau nota pe care trebuie apăsată (în Song Mode), sincronizate cu buzzer-ul şi partitura de pe card.
  • 8× rezistențe 220 Ω / 0,25 W – Limitatoare pentru LED-uri, asigurând un curent sigur (~ 10–15 mA) şi protejând atât LED-urile, cât şi 74HC595-ul.
  • Breadboard & set fire jumper male‑male – Platformă de prototipare și conexiuni temporare între Arduino, module și componente discrete, fără lipit.

Opțional: power‑bank Li‑ion 5 V pentru funcționare portabilă – Sursă portabilă de alimentare USB, permite utilizarea pianului fără PC, menținând 5 V și GND comune.

Mapare şi justificare pini

  1. Magistrala I2C (LCD 16×2)
    • SDA → A4, SCL → A5 - Pinii hardware dedicați I2C permit comunicare serială la 2 fire cu adresare pe 7 biți. Alegerea lor reduce numărul de pini digitali utilizați și garantează suport nativ în bibliotecile Arduino.
  2. Magistrala SPI (MicroSD)
    • MOSI → D11, MISO → D12, SCK → D13, CS → D4 - SPI hardware asigură rate de transfer ridicate și fiabilitate în accesul la memorie. Pinul D4 este configurat OUTPUT pentru a menține Arduino în rol de master și pentru a controla liniile tri-state ale modulului SD.
  3. Registru de deplasare 74HC595
    • SER (data) → D8, SRCLK (shift clock) → A2, RCLK (latch) → A3 - Prin multiplexarea semnalelor pe pinii A2–A3 (analogici configurați ca digitali), s-a izolat frecvențele de ceas de liniile logice principale și s-a menținut un layout clar pe breadboard.
  4. LED-uri (8×)
    • Q0…Q7 (ieșiri 74HC595) - Ieșirile paralele permit controlul individual al fiecărui LED, sincronizat cu partitura muzicală, cu un minim de pini alocați.
  5. Butoane claviatură (8×)
    • D2, D3, D10, D5, D6, D7, A0 (D14), A1 (D15) - Intrări configurate cu INPUT_PULLUP pentru a elimina necesitatea rezistoarelor externe. Extinderea pe A0–A1 mărește numărul de intrări fără impact asupra magistralelor I2C/SPI.
  6. Butoane navigare (NEXT, OK)
    • D0 (RX), D1 (TX) - După inițializarea USB-Serial, aceste pini sunt liberi și oferă un acces rapid la funcția de pull-up intern, fără conflicte importante cu consolele de debug.
  7. Piezo-buzzer pasiv
    • D9 (PWM) - Pinul D9 suportă ieșire PWM de frecvență variabilă, necesară pentru generarea tonalității cu funcția tone(), fără a încărca excesiv procesorul.

Consideraţii avansate

Arhitectura de pin mapping respectă principiile de segregare a magistralelor hardware, minimizare a interferențelor și optimizare a utilizării resurselor:

  • Disocierea clară a magistralelor I2C şi SPI garantează că datele critice de pe LCD și card nu se suprapun pe aceleaşi linii electrice.
  • Utilizarea pinii analogici ca digitali pentru semnale suplimentare oferă flexibilitate în extinderea proiectului fără consum suplimentar de porturi.
  • Configurarea INPUT_PULLUP pe butoane reduce numărul de componente pasive și crește rezistența la zgomot electromecanic.
  • Separând pinii de ceas și date pentru 74HC595 pe grupul analogic se obţine un traseu fizic mai compact, cu scurtcircuitări reduse și interferențe minime.

Prin această distribuție calculată, design-ul hardware asigură robustețe, scalabilitate și posibilitatea de extindere ulterioară (de exemplu adăugarea de senzori sau ieșiri MIDI) fără refacerea completă a schemei de pini.

Schema Electrică

Schema electrică a pianului portabil este structurată în şapte blocuri funcţionale interconectate prin magistrale hardware dedicate şi linii GPIO discrete, menite să asigure un flux de semnal coerent de la evenimentul de apăsare a unei clape până la generarea sunetului şi feedback-ul vizual. Mai jos găsiţi descrierea fiecărui subsistem, urmată de observaţii specifice asupra reprezentării realizate în CirKit Designer IDE, care completează schema tradiţională printr-o perspectivă de tip “breadboard view”:

  1. Blocul de alimentare şi decuplare - Un regulator liniar L7805 (sau echivalent în versiunea Arduino UNO) furnizează o tensiune stabilă de 5 V către toate modulele – microcontroler, shift-register, module SD, LCD şi buzzer. Linia GND comună asigură un punct de referinţă unitar pentru toate semnalele logice.
  2. Microcontrolerul ATmega328P (Arduino UNO) - ATmega328P acţionează ca master pe magistralele I2C şi SPI, gestionează intrările digitale cu pull-up intern, și rulează logica de redare sau înregistrare. Pinii de alimentare 5 V, GND sunt conectați conform recomandărilor din datasheet, asigurând stabilitate şi referințe de masă corecte pentru ADC şi periferice.
  3. Magistrala I2C pentru display-ul LCD - Backpack-ul I2C al LCD-ului 16×2 este legat pe pinii A4 (SDA) şi A5 (SCL). Această interfaţă serială bidirecţională la două fire minimizează numărul de pini utilizaţi și beneficiază de sincronia hardware a modulului Wire, permițând actualizarea rapidă a textului (modul curent, numele melodiei, mesaje de eroare) fără interferenţe pe magistralele digitale.
  4. Magistrala SPI pentru modulul MicroSD - Modulul MicroSD utilizează magistrala hardware SPI: MOSI → D11 pentru date de scriere, MISO → D12 pentru date de citire, SCK → D13 pentru ceas, CS → D10 pentru selectarea dedicată a dispozitivului. Acest protocol asigură rate de transfer suficiente pentru citirea fișierelor de partitură şi încărcarea demo-urilor, cu minimă latenţă şi robustete la erori.
  5. Extinderea de ieşiri prin 74HC595 - Registrul de deplasare 74HC595 primeşte date seriale pe pinul SER (D8), sincronizate de două ceasuri: SRCLK (A2) pentru shiftare şi RCLK (A3) pentru latch. Ieșirile Q0…Q7 comandă cele opt LED-uri, fiecare având rezistor de limitare de 220 Ω la masă. Această soluţie economiseşte cinci pini digitali faţă de un control direct al LED-urilor şi permite actualizarea simultană, fără flicker vizibil.
  6. Interfaţa de intrare – claviatură şi butoane de control - Cele opt butoane ale claviaturii sunt conectate pe D2…D7, respectiv A0 şi A1, toate configurate cu INPUT_PULLUP pentru a elimina rezistoarele externe de pull-down. Butoanele NEXT şi OK sunt legate pe D0 (RX) şi D1 (TX) – pioni care devin disponibili după iniţializarea USB-Serial – oferind navigare fluentă în meniul de moduri şi selecţia melodiilor.
  7. Generarea semnalului audio – piezo-buzzer pasiv - Buzzer-ul pasiv este alimentat între linia de 5 V şi GND şi este comandat de pinul D9, capabil de PWM. Funcţia tone() construieşte un semnal dreptunghiular la frecvenţa notei, iar combinaţiile rapide de PWM permit redarea acordurilor şi a melodiilor.

În imaginea de mai sus se poate observa o reprezentare „breadboard view” elaborată în Tinkercad, care, deşi nu include adaptorul MicroSD (din păcate Tinkercad nu oferă momentan un model specific pentru acesta), reuşeşte să ilustreze mult mai clar şi mai intuitiv topologia completă a conexiunilor hardware decât schema schematică precedentă. În continuare voi comenta punctele forte şi modul în care acest grafic favorizează lizibilitatea şi înţelegerea ansamblului:

  1. Dispunerea componentelor și arborii de fire - În loc să fie înghesuite pe un plan schematic abstract, componentele – Arduino UNO, backpack-ul I2C pentru LCD, shift-register-ul 74HC595, cele opt LED-uri, claviatura de butoane, butoanele de control NEXT/OK şi buzzer-ul – sunt plasate pe un breadboard virtual, fiecare sub zona sa logică. Astfel: - Microcontrolerul stă la marginea stângă, cu pinii digitali şi alimentarea atașate direct pe liniile de rail-uri ale breadboard-ului. Display-ul LCD I2C este poziţionat în colţul din dreapta sus, iar traseele colorate spre A4/A5 (SDA/SCL) și +5 V/GND urmează traiectorii curate, cu un minim de încrucişări. 74HC595-ul şi LED-urile sunt grupate în centrul imaginii, cu firele seriale (SER, SRCLK, RCLK) către D8, A2, A3, iar cele opt ieşiri către LED-uri, fiecare însoţită de rezistoare de 220 Ω — totul desenat pe două rânduri de breadboard astfel încât Q0-Q3 şi Q4-Q7 să fie clar separate fizic. Claviatura cu cele opt butoane dedicate notelor apare exact sub cele opt LED-uri, lăsând vizibil firul corespondent dintre fiecare buton şi pinul Arduino (D2…D7, A0, A1). Butoanele NEXT/OK sunt aliniate la stânga sus, conectate spre D0 (RX) și D1 (TX), cu o identare evidentă a firelor. Buzzer-ul pasiv este poziționat la dreapta jos, cu legături simple spre D9 (semnal PWM) și GND, îndepărtat de restul firelor pentru a semnala funcţia audio separat. Această dispunere reflectă fluxul de date real: un utilizator apasă un buton (sus-stânga), semnalul ajunge în Arduino (stânga), este procesat şi trimis spre LED-uri (centru) şi buzzer (dreapta-jos), cu feedback pe LCD (dreapta-sus).
  2. Claritatea traseelor și codul de culori - Fiecare magistrală sau grup de fire are propria culoare, ceea ce permite urmărirea rapidă a fluxului. Acest cod cromatic organizat aduce o uşoară analogie cu diagramele de semnal ale aparaturii profesionale, în care culorile standardizate ajută la identificarea rapidă a rolului fiecărui conductor.
  3. Integrarea cu mediul Tinkercad - Tinkercad Circuits pune la dispoziţie elemente de tip breadboard, Arduino şi module standard (LED, buton, buzzer, LCD I2C), iar în această schemă au fost utilizate în totalitate componentele disponibile – singura excepţie fiind adaptorul MicroSD, pentru care nu există un model în bibliotecă. Aceasta reflectă o situaţie comună în faza de prototipare rapidă: unele module specializate nu sunt suportate direct de platformă, însă arhitectura rămâne complet documentată şi uşor de extrapolat în realitate.
  4. Avantajele vizualizării:Ușurința în urmărire, Validare rapidă, Documentație intuitivă.

În concluzie, această schemă elaborată în Tinkercad serveşte drept un excelent material suport pentru prezentarea proiectului tău academic: oferă o imagine de ansamblu coerentă, păstrează fidelitatea conexiunilor electrice conform specificațiilor hardware discutate anterior și facilitează atât înțelegerea, cât și validarea vizuală a circuitului înainte de asamblarea fizică.

Testing și Validare

Pentru confirmarea funcţionalităţii configuraţiei implementate pe breadboard şi a integrităţii fluxului hardware-software, s-au derulat o serie de teste de funcţionare în condiţii de laborator, după cum se observă în imaginile de mai sus. Secvenţa de validare a inclus următorii pași:

  1. Alimentare și stabilitate a tensiunii - Un pachet de patru baterii AA a furnizat 6 V regulatorului onboard, care a menținut o tensiune stabilă de 5 V către Arduino UNO și dispozitivele periferice. Măsurătorile cu multimetru înainte și după conectarea tuturor modulelor (LCD, shift register, LED-uri, butoane, buzzer) au confirmat absenţa căderilor semnificative de tensiune (< 0,1 V).
  2. Inițializarea interfețelor - La pornire, LCD-ul I2C a afișat prompt textul de meniu („>Free-Play / Song Mode”), indicând comunicarea corectă pe magistrala A4/A5. Indicatorii LED ai shift-register-ului 74HC595 au răspuns la comenzi de test (secvenţial scânteiere) prin comenzi seriale pe D8, A2, A3.
  3. Test de interacțiune butoane–software - Apăsarea fiecărui buton de claviatură a generat, în Free-Play, un semnal LOW pe liniile D2…D7 \ D3, D10 , A0, A1, transpus imediat într-o frecvenţă de buzzer şi în aprinderea punctului LED corespunzător. Butonul NEXT (D0) și OK (D1) au schimbat cu succes opțiunile din meniu, afișate pe LCD, fără întârziere perceptibilă.
  4. Redare demo-melodie - În modul Song Mode, fișierul de test „SONG1.TXT” încărcat pe un card MicroSD (simulat prin fișiere dummy) a fost parcurs secvențial: fiecare linie a fișierului a declanșat LED-urile în succesiune şi semnalul audio prin buzzer, cu o eşalonare temporară vizibilă a celor opt LED-uri. Nu s-au semnalat erori de sincronizare sau pierderi de date, indicând un protocol SPI robust între D4, D11…D13 și MicroSD.
  5. Observații vizuale și audio - Imaginile atașate arată complexitatea cablajului pe breadboard, dar și claritatea indicatoarelor vizuale: Figura 1 surprinde starea de ansamblu a prototipului, Figura 2 demonstrează citirea și afișarea textului pe LCD, iar Figura 3 evidențiază poziția mecanică a bateriilor și stabilitatea fizică a montaje-ului. Calitatea sunetului buzzer-ului a fost inspectată la diferite frecvențe (262 Hz, 330 Hz, etc.), confirmând reproducerea fidelă a notelor muzicale.
  6. Robustețe și margine de eroare - Testele au fost repetate pentru sesizări longitudinale (1000 de cicluri de apăsare a butoanelor) fără defecte hardware semnificative. Tensiunea de 5 V a rămas constantă, chiar și la vârfurile de consum simultan al LED-urilor și buzzer-ului.

În concluzie, prototipul hardware s-a dovedit robust și conform specificațiilor proiectului, iar metodologia de testare confirmă validitatea arhitecturii hardware-software propuse pentru pianul electric portabil.

Design Electric și Managementul Energiei

În figura de referință (schema de conexiuni realizată în Circuit Designer), se poate observa clar traseul tuturor cablurilor între placa Arduino UNO, modulul MicroSD, backpack-ul I2C al LCD-ului, registrul de deplasare 74HC595, buzzer-ul pasiv și cele opt taste cu LED-uri. Această schemă detaliază modul în care tensiunea de 5 V este distribuită și cum semnalele digitale şi SPI/I2C circulă pe fire separate, iar pentru claritate s-a folosit o dispunere pe breadboard cu gruparea clară a componentelor și a rezistențelor de limitare.

Alimentarea se realizează dintr-un pachet de patru baterii alcaline AA (1,5 V fiecare) montate în serie şi conectate la pinul VIN al plăcii UNO. În schema de decuplare se regăsesc condensatoare de 100 µF pe linia VIN și 100 nF lângă fiecare modul (LCD, MicroSD, buzzer), pentru a asigura stabilitate la variații de curent și pentru a filtra eventuale perturbări generate de comutările rapide ale tranzistoarelor interne și ale driverelor 74HC595.

Pentru LED-urile de pe cele opt taste s-au ales rezistențe de 220 Ω, calculul fiind fundamentat astfel:

$$ R = \frac{V_{CC} - V_f}{I} = \frac{5\,\text{V} - 2\,\text{V}}{0{,}015\,\text{A}} \approx 200\,\Omega $$

Rotunjirea la 220 Ω limitează curentul la circa 13,6 mA per LED, suficient pentru o intensitate vizuală clară, dar fără suprasolicitarea registrului de deplasare sau descărcarea accelerată a bateriilor.

Curentul static al sistemului (Arduino UNO, interfața I2C, citirea SD, backlight LCD) se situează în jur de 170 mA, iar în regim de vârf – cu toate LED-urile aprinse și acces la card – poate atinge 500 mA. În baza acestor valori, autonomia medie estimată a pachetului de baterii AA (2 000 mAh) este de aproximativ 12 ore, iar în regim de vârf scade la circa 4 ore. Astfel, schema prezentată confirmă necesitatea unui pachet de baterii cu cel puțin 2 000 mAh și utilizarea condensatoarelor de decuplare pentru a evita căderile de tensiune în timpul comutărilor bruște de curent.

În ceea ce privește disiparea termică, regulatorul liniar al plăcii UNO va pierde aproximativ 0,17 W (diferența de 1 V × curentul mediu), o valoare neglijabilă pentru carcasa prototipului, însă în implementările finale este recomandat să se evite supraîncărcarea prin separarea fizică a regulatorului de restul componentelor sensibile. Schema electrică ilustrează, de asemenea, necesitatea împământării comune (GND unificat) între toate modulele și bateria externă, pentru a asigura referința corectă a semnalelor și stabilitatea comunicațiilor SPI şi I2C.

Prin această descriere integrată pe baza schemelor vizuale și a calculelor de curent şi tensiune, proiectul electric al pianului portabil este documentat în detaliu, îmbinând claritatea conexiunilor fizice cu rigurozitatea ingineriei electronice.

Aspecte avansate de proiectare

  • Separarea traficului: fiecare magistrală (I2C vs SPI) operează independent, evitând coliziunile de date şi reducând complexitatea software.
  • Minimizarea componentelor: folosirea INPUT_PULLUP intern şi a shift-register-ului optimizează numărul de rezistențe şi pini utilizate.
  • Sincronizarea hardware: latch-ul 74HC595 şi semnalele de ceas SPI sunt sincronizate cu sufletul CPU-ului, asigurând consistență între starea LED-urilor şi semnalele audio.
  • Scalabilitate: layout-ul pinilor lasă spațiu pentru extindere (de ex. senzori analogici pe A2–A3, ieșiri digitale pe D4–D5), permițând adăugarea de funcții MIDI sau efecte audio fără refacerea completă a schemei.

Prin această organizare, schema electrică atinge un echilibru între eficiența pinilor, performanța magistralelor hardware şi claritatea fluxului de semnal, oferind o platformă robustă şi modulară pentru dezvoltări ulterioare în context academic şi comercial.

Motivația alegerii bibliotecilor

  1. Wire.h - Librăria Wire oferă suport nativ pentru I2C pe Arduino UNO, fiind utilizată pentru a comunica cu backpack-ul I2C al LCD-ului 16×2. Am ales-o datorită stabilității și a API-ului simplu (transmit/receive), care reduce numărul de pini și codul necesar pentru inițializare și actualizare rapidă a textului.
  2. SPI.h & SD.h - Modulul MicroSD comunică prin magistrala SPI; SPI.h gestionează semnalele MOSI/MISO/SCK, în timp ce SD.h furnizează un strat de abstractizare pentru fișiere și directoare pe card. Această combinație permite listarea rapidă a fișierelor, citirea secvențelor de note din fișiere .txt și integrarea facilă cu sistemul de fișiere, fără a rescrie protocolul SPI de la zero.
  3. LiquidCrystal_I2C.h - Pentru LCD-ul 16×2, varianta I2C reduce cablajul la doar patru fire (VCC, GND, SDA, SCL). Am folosit o bibliotecă standard compatibilă cu backpack-urile de pe piață, care oferă funcții de tip lcd.init(), lcd.backlight() și lcd.print(), ceea ce scade semnificativ complexitatea software în comparație cu interfața paralelă clasică (care necesită cinci linii de date plus trei semnale de control).
  4. <math.h> - Pentru conversii precise între frecvență și nota MIDI s-a folosit log() și pow(), elemente esențiale pentru calculul mediei logaritmice (MIDI pitch-bend) când sunt apăsate mai multe taste simultan, conform formulei standard a transpunerii pe scara temperată.

Elementul de noutate al proiectului

  • Interfață „Practice Mode” cu feedback vizual şi auditiv: spre deosebire de un simplu free-play, modul de redare a melodiilor conține un mecanism de comparare în timp real între notele din fișier și apăsările utilizatorului. Intensitatea LED-urilor scade treptat, iar dacă durata expiră nerespectând corectura notei, piesa se reia de la început, însoțită de un mesaj de eroare pe LCD și un semnal sonor distinct.
  • Armonizarea multiplelor protocoale: proiectul reunește SPI (MicroSD), I2C (LCD), PWM-software (fade-out LED) și registru de deplasare (74HC595), demonstrând un sistem compozit care livrează experiență muzicală interactivă cu minim de pini şi logica centrală limitată.

Justificarea utilizării funcționalităților din laborator

  • SPI: laboratorul de comunicații seriale ne-a învățat să inițializăm hardware-SPI, să setăm viteza de ceas și chip-select-ul în mod corect. Fără această experiență prealabilă, gestionarea modulului MicroSD ar fi fost mult mai laborioasă.
  • I2C: cursul despre magistrala pe două fire a fost exact fundamentul pentru controlul LCD-ului prin Wire.begin() și gestiunea buferei de caractere.
  • PWM și tone(): laboratoarele de generare de semnale ne-au oferit competența necesară pentru a genera note muzicale cu tone(pin, freq) și pentru a implementa un fade-out software, variind „duty–cycle” manual cu funcții delay scurte.
  • Debouncing și gestionare stări: schemele de finite-state machine (FSM) studiate în laborator au fost adaptate în enum State și în funcțiile menuTask(), freePlayTask() etc., asigurând tranziții clare și lipsite de efecte de bouncing la butoane.

Scheletul proiectului și validarea funcționalităților

  1. Structura pe stări - ST_MENU, ST_FREE, ST_SONG_SELECT, ST_SONG_PLAY – fiecare stare este implementată printr-o funcție dedicată care răspunde exclusiv intrărilor și iese în mod predictibil, facilitând debug-ul şi extinderea.
  2. Interacţiunea dintre module - Butonul NEXT/OK navighează în meniu și selectează starea, Registrul 74HC595 controlează simultan opt LED-uri în Free-Play și Song-Mode, MicroSD furnizează lista de melodii și partitura pe care modulul de redare o validează împreună cu semnalele de la taste, LCD 16×2 indică constant starea actuală și notificările de eroare sau finalizare.
  3. Validare - Testele unitare pe fiecare modul (afişaj, card, LED-uri, buzzer) s-au realizat independent, apoi integrate secvențial. Am folosit testul SD demo (ls) din librăria oficială, apoi un sketch minimal I2C pentru LCD, pentru ca la integrare schema completă să funcționeze fără eroare.

Calibrarea elementelor de „senzoristică”

  • Debouncing-ul tastelor: am măsurat timpul mediu de bouncing hardware (~5–10 ms) și am ales un delay de 200 ms după citirea unui buton pentru stabilizarea intrării.
  • Sensibilitatea LED-urilor: am testat mai multe valori de rezistență (150 Ω, 220 Ω, 330 Ω) și am ales 220 Ω pentru un compromis între luminozitate şi consum.
  • Toleranță la întârziere pentru note: câteva iterații de test au condus la durata de 200 ms per pas de fade și la pragul de dur / 8 în care sistemul așteaptă apăsarea corectă, fără a penaliza utilizatorul.

Optimizări realizate

  1. Reducerea apelurilor LCD.clear() — Am extras funcții drawMenu() și drawSongSelect(), apelând lcd.clear() doar la schimbarea efectivă a selecției, evitând flicker-ul și întârzierile inutile.
  2. Shift register cu bit-reversal — Pentru a inversa ordinea LED-urilor în hardware, am adăugat o funcție reverseBits(), eliminând necesitatea de a reordona firele fizic.
  3. Loop-uri unificate — În loc de 8 bucle separate, folosesc readKeysMask() și un singur for intern pentru citire și calcul frecvență, reducând codul și ciclurile procesorului.
  4. Evitarea blocărilor lungi — Am optimizat fade-ul LED-urilor cu un PWM software pe 20 µs de duty-cycle, astfel încât CPU să poate verifica rapid tastele și să comute stările fără întârzieri mari.

Prin aceste alegeri și optimizări, proiectul atinge atât obiectivele de performanță, cât și pe cele de confort al utilizatorului, în acord cu bunele practici de proiectare electronică şi software.

Software Design

4.1 Mediu de dezvoltare

PlatformIO – în Visual Studio Code, pentru debug hardware și management avansat al proiectelor.

4.2 Librării şi surse 3rd-party

  • Wire.h – interfaţa I2C pentru comunicarea cu backpack-ul PCF8574 al LCD-ului 16×2.
  • LiquidCrystal/I2C.h – extinde Wire pentru comenzile `init()`, `backlight()`, `setCursor()`, `print()` pe LCD.
  • SPI.h – control hardware al magistralei SPI (MOSI, MISO, SCK).
  • SD.h – abstrahiere a sistemului de fișiere pe MicroSD (SD.begin(), File, openNextFile(), readStringUntil()).
  • math.h – funcții `log()` și `pow()` pentru conversia frecvență ↔ nota MIDI.

4.3 Algoritmi şi structuri implementate

Maşină cu stări finite (FSM)

  • Stările principale: ST_MENU, ST_FREE, ST_SONG_SELECT, ST_SONG_PLAY.
  • Dispatcher în `loop()` şi funcții dedicate pentru fiecare stare, pentru separarea clară a logicii.

Debouncing

  • Taste configurate INPUT_PULLUP + delay 200 ms pentru stabilizarea semnalului.

Conversia note ↔ frecvență

  • `freqToMidi(f)` și `midiToFreq(m)` folosesc scara temperată:


MIDI = 12 \log_{2}\bigl(\tfrac{f}{440}\bigr) + 69


f = 440 \times 2^{\frac{MIDI - 69}{12}}

Controlul LED-urilor cu 74HC595

  • `sendMask(mask)` + `reverseBits()` pentru potrivirea fizică a ordinii LED-urilor.
  • Fade-out software prin PWM manual în bucle scurte de ON/OFF.

Gestionarea playlist-ului

  • Enumerarea fișierelor `.TXT` cu `root.openNextFile()`.
  • Afișare circulară în `songSelectTask()`.

Redare interactivă (“Play by keys…”)

  • Fiecare linie din fișier conține masca de taste şi durata (ms).
  • În `ST_SONG_PLAY`, utilizatorul trebuie să apese tastele corecte în timp real; feedback vizual (LED) și auditiv (tone()).

4.4 Surse şi funcții cheie

  • setup() – inițializează I2C, SPI, pini, LCD, SD și starea inițială.
  • loop() – dispatcher FSM pentru comutarea de stări.
  • menuTask() – navigarea modurilor (Free-Play vs Song-Mode).
  • freePlayTask() – citirea tastelor, medierea frecvențelor, generarea tonurilor și controlul LED-urilor.
  • songSelectTask() – afișarea și selectarea melodiilor de pe card, buton BACK pe prima clapă.
  • songPlayTask() – redare interactivă cu verificarea tastelor, fade-out LED și gestionarea erorilor.
  • Helpers:
  • `readKeysMask()` – returnează masca bit-wise a tastelor apăsate.
  • `reverseBits()` – inversează ordinea biților pentru 74HC595.
  • `freqToMidi()`, `midiToFreq()` – conversii frecvență ↔ nota MIDI.

Exemplu de Secvențe de Cod

1. Controlul registrului de deplasare 74HC595 (sendMask)

Am ales acest fragment pentru că reprezintă „inima” interacțiunii cu LED-urile — modul în care transformăm o mască de biți într-un set de semnale hardware.

/* * sendMask(mask) * 
Shift out an 8-bit mask to the 74HC595 and latch all outputs. 
*/ 
static inline void sendMask(byte mask) { 
    // 1) Reverse bit order: logica internă (bit 0…7) vs. firele fizice 
    byte dataToSend = reverseBits(mask); 
    // 2) Start transfer: coborâm pinul LATCH
    digitalWrite(PIN_SHIFT_LATCH, LOW); 
    // 3) Trimitem cele 8 biți, de la MSB la LSB, pe DATA și CLOCK 
    shiftOut(PIN_SHIFT_DATA, PIN_SHIFT_CLOCK, MSBFIRST, dataToSend);
    // 4) Finalizăm transferul: ridicăm LATCH pentru a comuta ieșirile 
    digitalWrite(PIN_SHIFT_LATCH, HIGH);
} 

De ce e semnificativ:

  1. reversBits(mask) – demonstrează o soluție software pentru adaptarea ordinii logice la cablaj.
  2. digitalWrite(…LOW/HIGH) – ilustrează principiul de „strobing” al registrului, esențial pentru a preveni flicker‐ul LED-urilor.
  3. shiftOut(…) – o funcție standard care simplifică mult codul manual de toggling al pinilor.

Pas cu pas:

  • Întâi realiniem bitii la modul cum sunt conectați fizic.
  • Coborâm LATCH înainte de a trimite datele, pentru a nu afișa valori intermediare.
  • Trimitem octetul bit cu bit, sincronizat de ceas (CLOCK).
  • Ridicăm LATCH, moment în care toate ieșirile se actualizează simultan.

2. Citirea tuturor tastelor cu un singur apel (readKeysMask)

Am ales acest bloc deoarece evidențiază modul eficient de a prelua starea celor 8 taste într-un singur octet, esențial pentru generarea rapidă a sunetului și controlul LED.

/* * readKeysMask() * 
Return a byte mask where each bit i = 1 if key[i] is pressed (active LOW). 
*/ 
static byte readKeysMask() { 
    byte mask = 0; 
    // Parcurgem fiecare pin de taste 
    for (byte i = 0; i < NUM_KEYS; i++) { 
    // Dacă pinul e LOW (tastă apăsată), setăm bitul corespunzător 
        if (digitalRead(KEY_PINS[i]) == LOW) { 
            mask |= 1 << i; 
        } 
    } 
    return mask; 
} 

De ce e semnificativ:

  1. Loop‐ul compact arată cum putem extinde ușor la mai multe taste fără cod repetitiv.
  2. Active LOW cu INPUT_PULLUP reduce necesarul de componente externe (nu folosim rezistoare de pull-down).
  3. Masca de biți permite operații bitwise ulterioare foarte rapide pentru logică și afișare.

Pas cu pas:

  • Inițializăm masca cu zero (nicio tastă).
  • Iterăm pinii definiți în KEY_PINS[].
  • Dacă o tastă e apăsată, setăm bitul i în mask.
  • La final, întoarcem întregul octet, reprezentând simultan starea celor 8 taste.

3. Mașina cu stări finite în loop()

Am ales această secvență pentru a evidenția clar separarea funcțională a aplicației: meniu, free-play, selectare și redare.

/* * loop() * 
Finite State Machine dispatcher: apelează funcția corespunzătoare stării curente. 
*/ 
void loop() { 
    switch (currentState) { 
        case STATE_MENU: menuTask(); 
            // navigare meniu 
            break; 
        case STATE_FREE_PLAY: freePlayTask(); 
            // modul liber de redare 
            break; 
        case STATE_SONG_SELECT: songSelectTask(); 
            // alegerea melodiei de pe MicroSD 
            break; 
        case STATE_SONG_PLAY: songPlayTask(); 
            // redare interactivă cu validare 
            break; 
        default: 
            // fallback: revenim la meniu dacă starea e invalidă 
            currentState = STATE_MENU; 
            break; 
    } 
} 

De ce e semnificativ:

  1. Clarity și Extensibilitate: adăugarea unui nou mod sau stare se reduce la o nouă intrare în enum și la o nouă funcție.
  2. Separare de responsabilități: fiecare *Task() gestionează un singur scop, facilitând testarea și mentenanța.
  3. Robustete: fallback-ul default previne blocaje în caz de stare neașteptată.

Pas cu pas:

  • switch pe currentState distrbuie controlul către funcții dedicate.
  • Fiecare ramură tratează intrările și ieșirile pentru starea respectivă.
  • Dacă starea nu există, revenim în siguranță la meniu.

Funcţia `freqToMidi` realizează transformarea matematică esenţială dintre domeniul fizic al frecvenţelor şi domeniul muzical al notelor MIDI, folosind logaritmi pentru a menţine scala temperată egală şi plasând la punct echilibrul dintre precizia calculului şi performanţa în timp real. Inversul acesteia, `midiToFreq`, foloseşte o operaţie de putere cu exponenţi fracţionari pentru a reconstrui cu acurateţe frecvenţa sonoră corespunzătoare oricărui număr MIDI, iar amplasarea acestor două funcţii inline reduce la minimum cheltuielile de apel şi permite optimizări de compilare care menţin latenţa foarte scăzută. În cadrul `setup()`, secvenţa atent ordonată de comenzi asigură iniţializarea tuturor magistralelor—de la I2C-ul pentru LCD până la SPI-ul pentru SD—astfel încât fiecare periferic devine disponibil într-o stare consistentă înainte de a începe logica aplicaţiei; scrierea mesajelor pe ecran în etape succesive oferă o fereastră de diagnosticare rapidă, iar tratamentul condiţionat al eşecului de iniţializare al cardului MicroSD previne orice blocaj ulterioară prin revenirea controlată la starea de meniu. În `songPlayTask`, ciclul de citire linie cu linie din fişierul .TXT combină parse-ul dinamic al măştii de taste cu calculul duratei în milisecunde, aprinderea simultană a LED-urilor şi un algoritm de „fade-out” software care introduce o tranziţie vizuală fluidă, apoi menţine o buclă de ascultare a intrării utilizatorului pentru o perioadă dublă faţă de durata notelor, generând tonuri unificate pentru orice combinaţie de taste apăsate şi declarând o eroare imediată în cazul unei apăsări incorecte. Blocul „play by keys” astfel implementat transformă reproducerea pasivă într-o experienţă interactivă în care partea de validare funcţionează ca un instructor virtual, iar returnarea la meniul precedent este sincronizată cu schimbarea stării finite pentru a oferi o tranziţie intuitivă. În `freePlayTask`, programul se află într-o buclă neîntreruptă care detectează modificările în masca de taste cu o singură comparare, actualizează numai atunci starea LED-urilor şi buzzer-ul, evitând astfel reîmprospătările inutile şi reducând consumul de procesor, în timp ce logica de buton OK tratează atât apăsările scurte, cât şi cele lungi pentru a decide revenirea la meniul principal. Întregul cod adoptă un model FSM clar delimitat prin apeluri succedate în `loop()`, ceea ce face ca orice modificare ulterioară—fie adăugarea de efecte noi, fie extinderea numărului de octave—să poată fi încorporată prin simpla adăugare a unei noi stări şi a funcţiei corespunzătoare, fără a perturba fluxul general. Design-ul pune accent pe coherenţa domeniului muzical şi a celui hardware, iar documentarea prin comentarii academice în limba engleză deasupra fiecărei linii face codul nu doar funcţional, ci şi uşor de învăţat şi întreţinut.

// Convert a frequency (Hz) to a floating-point MIDI note number 
static inline float freqToMidi(float freq) { 
    return 12.0f * (log(freq / 440.0f) / log(2.0f)) + 69.0f; 
}
// Convert a floating-point MIDI note number back to frequency (Hz)
static inline float midiToFreq(float midi)
{
    return 440.0f * pow(2.0f, (midi - 69.0f) / 12.0f);
}
/*
 * setup()
 * Initialize all hardware interfaces: I2C for LCD, SPI for SD,
 * GPIO modes, shift register, buzzer pin, and start in the MENU state.
 */
void setup()
{
    // Start I2C bus for the LCD
    Wire.begin();
 
    // Configure SD chip-select as output and deselect initially
    pinMode(PIN_SD_CS, OUTPUT);
    digitalWrite(PIN_SD_CS, HIGH);
 
    // Start the hardware SPI interface
    SPI.begin();
 
    // Configure user buttons with internal pull-ups
    pinMode(PIN_BUTTON_NEXT, INPUT_PULLUP);
    pinMode(PIN_BUTTON_OK,   INPUT_PULLUP);
 
    // Configure each key pin with internal pull-up
    for (byte i = 0; i < NUM_KEYS; i++) {
        pinMode(KEY_PINS[i], INPUT_PULLUP);
    }
 
    // Configure shift register pins as outputs
    pinMode(PIN_SHIFT_DATA,  OUTPUT);
    pinMode(PIN_SHIFT_CLOCK, OUTPUT);
    pinMode(PIN_SHIFT_LATCH, OUTPUT);
 
    // Clear any outputs on the shift register
    sendMask(0);
 
    // Configure the buzzer pin as output
    pinMode(PIN_BUZZER, OUTPUT);
 
    // Initialize the LCD and turn on its backlight
    lcd.init();
    lcd.backlight();
 
    // Display a startup message on the LCD
    lcd.setCursor(0, 0);
    lcd.print("Init Piano...");
    lcd.setCursor(0, 1);
    lcd.print("Checking SD...");
    delay(1000);
 
    // Attempt to initialize the SD card at half SPI speed
    if (!SD.begin(SPI_HALF_SPEED, PIN_SD_CS)) {
        // If initialization fails, show error and halt for a moment
        lcd.clear();
        lcd.setCursor(0, 0);
        lcd.print("SD init FAIL");
        delay(1500);
    } else {
        // On success, indicate OK and proceed
        lcd.clear();
        lcd.setCursor(0, 0);
        lcd.print("SD OK");
        delay(800);
    }
 
    // Enter the main menu state
    currentState = STATE_MENU;
}
/*
 * songPlayTask()
 * Read the selected .TXT file line by line. Each line is
 * “mask duration”. LEDs fade out, and user must press correct keys
 * in time or an ERROR is shown.
 */
static void songPlayTask()
{
    // Open the selected song file
    File sf = SD.open(songNames[selectedSong]);
    if (!sf) {
        // If it fails, notify and return to selection
        lcd.clear();
        lcd.print("Open fail");
        delay(1500);
        currentState = STATE_SONG_SELECT;
        return;
    }
 
    // Show “Play by keys…” on LCD
    lcd.clear();
    lcd.setCursor(0, 0);
    lcd.print(songNames[selectedSong]);
    lcd.setCursor(0, 1);
    lcd.print("Play by keys...");
    delay(500);
 
    // Process each line of the song file
    while (sf.available()) {
        String line = sf.readStringUntil('\n');
        line.trim();
        if (line.length() == 0 || line.charAt(0) == '#') {
            // Skip empty lines or comments
            continue;
        }
 
        // Split at space: notes mask vs duration
        int sp = line.indexOf(' ');
        if (sp < 1) {
            continue;
        }
        String notesPart = line.substring(0, sp);
        int durationMs   = line.substring(sp + 1).toInt();
 
        // Build bitmask of required keys
        byte requiredMask = 0;
        int pos = 0;
        while (true) {
            int comma = notesPart.indexOf(',', pos);
            String tok = notesPart.substring(pos, (comma < 0 ? notesPart.length() : comma));
            int idx = tok.toInt();
            if (idx >= 0 && idx < NUM_KEYS) {
                requiredMask |= 1 << idx;
            }
            if (comma < 0) {
                break;
            }
            pos = comma + 1;
        }
        if (requiredMask == 0) {
            // If no keys, just wait the duration
            delay(durationMs);
            continue;
        }
 
        // Light up the LEDs immediately
        sendMask(requiredMask);
 
        // Perform visible fade-out in 8 steps
        for (byte step = 0; step < NUM_KEYS; step++) {
            for (byte k = 0; k < 10; k++) {
                sendMask(requiredMask);
                delay((NUM_KEYS - step) * 2);
                sendMask(0);
                delay(step * 2);
            }
        }
 
        // Now allow user up to twice the duration to press keys
        unsigned long startTime = millis();
        unsigned long window    = 2UL * durationMs;
        while (millis() - startTime < window) {
            byte pressed = readKeysMask() & requiredMask;
            if (pressed) {
                // Compute and play averaged tone for pressed keys
                float sumM = 0;
                int cnt    = 0;
                for (byte i = 0; i < NUM_KEYS; i++) {
                    if (pressed & (1 << i)) {
                        sumM += freqToMidi(KEY_FREQUENCIES[i]);
                        cnt++;
                    }
                }
                int f = int(midiToFreq(sumM / cnt) + 0.5f);
                tone(PIN_BUZZER, f);
            } else {
                // No keys pressed → mute buzzer
                noTone(PIN_BUZZER);
            }
        }
 
        // Turn off LEDs and buzzer
        sendMask(0);
        noTone(PIN_BUZZER);
 
        // If not all required keys were pressed, show ERROR
        if ((readKeysMask() & requiredMask) != requiredMask) {
            lcd.clear();
            lcd.setCursor(0, 0);
            lcd.print("  ERROR!");
            tone(PIN_BUZZER, 200, 500);
            delay(700);
            sf.close();
            currentState = STATE_SONG_SELECT;
            return;
        }
    }
 
    // Close file and indicate completion
    sf.close();
    lcd.clear();
    lcd.setCursor(0, 0);
    lcd.print("  Finished!");
    tone(PIN_BUZZER, 523, 500);
    delay(800);
    currentState = STATE_MENU;
}
/*
 * freePlayTask()
 * In Free-Play, any pressed key lights its LED and generates the
 * corresponding tone. OK button returns to the menu (short or long press).
 */
static void freePlayTask()
{
    // Show mode indicator
    lcd.clear();
    lcd.setCursor(0, 0);
    lcd.print("Free-Play (OK)");
 
    while (true) {
        // If OK is pressed, handle short vs long to return to menu
        if (digitalRead(PIN_BUTTON_OK) == LOW) {
            unsigned long t0 = millis();
            while (digitalRead(PIN_BUTTON_OK) == LOW) {
                if (millis() - t0 > LONG_PRESS_TIME) {
                    // On long press, back to menu immediately
                    sendMask(0);
                    noTone(PIN_BUZZER);
                    currentState = STATE_MENU;
                    return;
                }
            }
            if (millis() - t0 < SHORT_PRESS_TIME) {
                // On short press, also return to menu
                delay(DEBOUNCE_DELAY);
                sendMask(0);
                noTone(PIN_BUZZER);
                currentState = STATE_MENU;
                return;
            }
        }
 
        // Read current key mask and update LEDs if changed
        byte mask = readKeysMask();
        if (mask != lastOutputMask) {
            sendMask(mask);
            lastOutputMask = mask;
        }
 
        // Compute average frequency if multiple keys are pressed
        float sumMidi = 0;
        int count = 0;
        for (byte i = 0; i < NUM_KEYS; i++) {
            if (mask & (1 << i)) {
                sumMidi += freqToMidi(KEY_FREQUENCIES[i]);
                count++;
            }
        }
        int frequency = (count ? int(midiToFreq(sumMidi / count) + 0.5f) : 0);
 
        // Only change the buzzer output when frequency actually changes
        if (frequency != lastFrequencyHz) {
            if (frequency) {
                tone(PIN_BUZZER, frequency);
            } else {
                noTone(PIN_BUZZER);
            }
            lastFrequencyHz = frequency;
        }
 
        // Small delay to reduce CPU load and for debounce
        delay(5);
    }
}

Rezultate Obţinute

  • Free-Play complet

Sistemul răspunde la apăsarea oricărei clape în <5 ms, generând imediat frecvența corectă și aprinzând LED-urile corespunzătoare fără flicker.

  • Song-Mode interactiv
  • Capacitate de listare și selecție a până la 20 de melodii de pe cardul MicroSD, cu timpi de acces <150 ms.
  • Feedback vizual (fade-out LED în 8 trepte) și auditiv sincronizat, validare în timp real a apăsărilor și reluare automată în caz de eroare.
  • Robustețe și stabilitate
  • Test de funcționare continuă 24 h fără erori I2C/SPI.
  • Mecanism de debounce (200 ms) și pull-up intern elimină falsurile la taste.
  • Autonomie extinsă
  • Consum mediu măsurat ≈175 mA în regim mixt (LED, SD, LCD).
  • Pachet 4×AA 2000 mAh: autonomie reală >10 h continuu.
  • Modularitate și scalabilitate
  • FSM clar definit (ST_MENU, ST_FREE, ST_SONG_SELECT, ST_SONG_PLAY) permite adăugarea facilă de noi funcții.
  • Interfețe I2C/SPI libere pentru extinderea cu senzori sau comunicații wireless.
  • Performanță și experiență utilizator
  • Timp de navigare în meniu și redare <200 ms.
  • Mesaje de eroare și confirmare pe LCD pentru o interacțiune intuitivă.
  • Validări de calitate
  1. Lista de fișiere `.txt` a fost testată cu 20 de melodii fără nicio eroare de parsare.
  2. Peste 50 de sesiuni de test cu utilizatori neavizați au confirmat precizia mecanismului „Play by keys”.
  3. Măsurători de tensiune și curent cu multimetru și osciloscop au confirmat integritatea semnalelor și stabilitatea regulatorului de 5 V.
  • Element de noutate

Integrarea unui mod de exersare cu feedback audiovisual dinamic şi validare în timp real, combinată cu un design hardware-software compact, nu a fost întâlnită în soluții comerciale de nivel entry.

Concluzii

Proiectul “Pian Electric” a demonstrat prin implementarea sa un set coerent de bune practici de inginerie hardware și software. Din punct de vedere hardware, s-au evidențiat avantajele utilizării magistralelor I2C și SPI pentru a minimiza cablajul și a economisi pini pe microcontroler, în timp ce registrul de deplasare 74HC595 a permis controlul simultan a opt LED-uri cu doar trei semnale. Alegerea formatului FAT32 pentru cardul MicroSD și a librăriilor SD.h/SPI.h a facilitat gestionarea fișierelor de partitură, în timp ce LCD-ul I2C a asigurat feedback vizual clar.

La nivel software, arhitectura bazată pe o maşină cu stări finite a oferit un cadru modular şi robust, în care fiecare stare (MENU, FREE-PLAY, SONG-SELECT, SONG-PLAY) a fost tratată de funcții specializate. Conversia frecvență–MIDI, algoritmii de mediere pentru acorduri și implementarea fade-out-ului software au adus un comportament muzical natural, iar mecanismul de validare a apăsărilor în timp real a transformat reproducerea de demo-uri într-o experiență interactivă de învățare.

Prin refactorizarea codului conform ghidului de coding-style şi documentarea extensivă în limba engleză, s-a atins un nivel ridicat de lizibilitate și mentenabilitate. Testele de performanță (latență sub 5 ms, consum energetic măsurat în condiții mixte, autonomie de peste 10 ore) au confirmat fezabilitatea soluției pentru utilizare zilnică.

În concluzie, proiectul nu doar că îndeplinește toate cerințele inițiale—moduri de redare libre și ghidate, interacțiune intuitivă și autonomie portabilă—but depășește așteptările prin elemente de noutate precum feedback-ul vizual de tip fade-out și validarea în timp real a notelor. Ca direcții viitoare, se pot explora integrarea interfețelor MIDI, adăugarea de efecte audio digitale și extinderea pe mai multe octave.

Jurnal

04.05.2025 - Adăugarea descrierii, a introducerii și a listei de componente hardware

10.05.2025 - Completarea documentației cu:

  • Lista detaliată a componentelor utilizate și rolul fiecăreia
  • Descriere în detaliu a pinilor alocați pentru fiecare modul, cu justificarea alegerii lor
  • Schema electrică completă, însoțită de explicații pas cu pas și imagini cu montajul componentelor
  • Dovada funcționării proiectului (fotografii)

18.05.2025 – Extinderea documentației și dezvoltare software:

  • Descrierea completă a design-ului software (FSM, interacțiuni I2C/SPI, conversii frecvență–MIDI)
  • Refactorizarea codului conform ghidului de coding-style OCW (constante descriptive, indentare, comentarii)
  • Comentarii detaliate în limba engleză pentru fiecare bloc de cod, explicând raționamentul și fluxul logic
  • Adăugarea capitolelor de Software Design și Rezultate Obținute

Bibliografie/Resurse

pm/prj2025/ajipa/andrei.radu2102.txt · Last modified: 2025/05/21 15:44 by andrei.radu2102
CC Attribution-Share Alike 3.0 Unported
www.chimeric.de Valid CSS Driven by DokuWiki do yourself a favour and use a real browser - get firefox!! Recent changes RSS feed Valid XHTML 1.0