This shows you the differences between two versions of the page.
pm:prj2025:ccristi:agavrilut [2025/05/25 22:34] agavrilut [Decizii și detalii de implementare] |
pm:prj2025:ccristi:agavrilut [2025/05/28 02:34] (current) agavrilut [Aplicația MiniSynth Recorder] |
||
---|---|---|---|
Line 41: | Line 41: | ||
* Apăsarea celor 8 butoane pentru a reda note muzicale, folosind buzzer-ul pasiv | * Apăsarea celor 8 butoane pentru a reda note muzicale, folosind buzzer-ul pasiv | ||
* Ajustarea frecvenței notelor prin rotirea potențiometrului | * Ajustarea frecvenței notelor prin rotirea potențiometrului | ||
- | * În poziția minimă a potențiometrului, sunt redate notele din gama C4-C5, iar prin rotirea acestuia spre dreapta, frecvențele cresc gradual | + | * În poziția minimă a potențiometrului, sunt redate notele din gama C4-C5, iar prin rotirea acestuia spre dreapta, frecvențele cresc gradual, până la C5-C6 |
2. **//Modul record//** | 2. **//Modul record//** | ||
Line 112: | Line 112: | ||
| Buzzer | D10 | PB2 (OC1B) | Ieșire PWM pe Timer1 | | | Buzzer | D10 | PB2 (OC1B) | Ieșire PWM pe Timer1 | | ||
| HC-05 STATE | D13 | PB5 | Indică starea conexiunii Bluetooth | | | HC-05 STATE | D13 | PB5 | Indică starea conexiunii Bluetooth | | ||
- | | HC-05 RXD | TX0 | PD1 | Comunicare UART (USART0), Arduino->HC-05, conectat prin divizor de tensiune (2kΩ și 1kΩ) | | + | | HC-05 RXD | TX0 | PD1 | Comunicare UART (USART0), Arduino->HC-05, conectat prin divizor de tensiune (2kΩ și 1kΩ), pentru că pinul RXD funcționează la 3.3V | |
| HC-05 TXD | RX0 | PD0 | Comunicare UART (USART0), HC-05->Arduino | | | HC-05 TXD | RX0 | PD0 | Comunicare UART (USART0), HC-05->Arduino | | ||
==== Imagini ==== | ==== Imagini ==== | ||
+ | |||
+ | {{:pm:prj2025:ccristi:whatsapp_image_2025-05-28_at_00.50.06_ffb0866b.jpg?nolink&600|}} | ||
Inițial am conectat pinii RX și TX de pe HC-05 la D11 și D12, în ideea de a folosi SoftwareSerial. Ulterior i-am mutat pe TX1 și RX0 și am renunțat complet la bibliotecile Arduino. | Inițial am conectat pinii RX și TX de pe HC-05 la D11 și D12, în ideea de a folosi SoftwareSerial. Ulterior i-am mutat pe TX1 și RX0 și am renunțat complet la bibliotecile Arduino. | ||
Line 138: | Line 140: | ||
**''main.cpp''** | **''main.cpp''** | ||
- | Fișierul principal conține funcția ''setup()'' și bucla ''while(1)'', în care sunt apelate funcțiile de actualizare: | + | Fișierul principal conține funcția ''setup()'' și bucla ''while(1)'', în care sunt apelate funcțiile de actualizare |
- | * ''update_bt_state()'' – verifică dacă modulul HC-05 este conectat, controlează LED-ul albastru și dezactivează modul record în caz de deconectare | + | * ''update_bt_state()'': verifică dacă modulul HC-05 este conectat, controlează LED-ul albastru și dezactivează modul record în caz de deconectare |
- | * ''update_notes()'' – detectează apăsarea butoanelor, aplică pitch shift în funcție de potențiometru, redă nota pe buzzer și trimite mesaje seriale dacă înregistrarea e activă | + | * ''update_notes()'': detectează apăsarea butoanelor, aplică pitch shift în funcție de potențiometru, redă nota pe buzzer și trimite mesaje seriale dacă înregistrarea e activă |
- | * ''update_rec_mode()'' – comută între modurile normal și record la apăsarea butonului de înregistrare, controlează LED-ul roșu și trimite serial mesaje de control | + | * ''update_rec_mode()'': comută între modurile normal și record la apăsarea butonului de înregistrare, controlează LED-ul roșu și trimite serial mesaje de control |
**''io_utils.h''** | **''io_utils.h''** | ||
- | Funcții pentru configurarea pinilor, folosind structura ''IOPin'', care conține toate registrele asociate unui pin: | + | Funcții pentru configurarea pinilor, folosind structura ''IOPin'', care conține toate registrele asociate unui pin |
- | * ''conf_input(IOPin)'' – setează pinul ca intrare | + | * ''conf_input(IOPin)'': setează pinul ca intrare |
- | * ''conf_input_pullup(IOPin)'' – configurare ca intrare cu rezistor de pull-up activ | + | * ''conf_input_pullup(IOPin)'': configurare ca intrare cu rezistor de pull-up activ |
- | * ''conf_output(IOPin)'' – setează pinul ca ieșire | + | * ''conf_output(IOPin)'': setează pinul ca ieșire |
- | * ''read_pin(IOPin)'' – returnează starea pinului | + | * ''read_pin(IOPin)'': returnează starea pinului |
- | * ''set_pin_high(IOPin)'' / ''set_pin_low(IOPin)'' – controlează nivelul logic pe pin | + | * ''set_pin_high(IOPin)''/''set_pin_low(IOPin)'': controlează nivelul logic pe pin |
**''buzzer.h''** | **''buzzer.h''** | ||
- | Controlul buzzer-ului prin PWM, folosind Timer1: | + | Controlul buzzer-ului prin PWM, folosind Timer1 |
- | * ''buzzer_init()'' – configurează Timer1 în modul Fast PWM, cu top în ICR1 și ieșire pe pinul OC1B (PB2) | + | * ''buzzer_init()'': configurează Timer1 în modul Fast PWM, cu top în ICR1 și ieșire pe pinul OC1B (PB2) |
- | * ''play_note(frequency)'' – calculează valoarea pentru ICR1 în funcție de frecvența dată, activează pinul OC1B și configurează semnalul PWM | + | * ''play_note(frequency)'': calculează valoarea pentru ICR1 în funcție de frecvența dată, activează pinul OC1B și configurează semnalul PWM |
- | * ''stop_note()'' – dezactivează PWM, setează pinul pe LOW și apoi pe input pentru a opri complet sunetul | + | * ''stop_note()'': dezactivează PWM, setează pinul pe LOW și apoi pe input pentru a opri complet sunetul |
**''adc_pot.h''** | **''adc_pot.h''** | ||
- | Citirea valorii de la potențiometru prin ADC0: | + | Citirea valorii de la potențiometru prin ADC0 |
- | * ''adc_init()'' – inițializează perifericul ADC | + | * ''adc_init()'': inițializează perifericul ADC |
- | * ''read_pot_value()'' – returnează valoarea potențiometrului mapată în intervalul 0.0–12.0, folosită pentru calculul pitch shift | + | * ''read_pot_value()'': returnează valoarea potențiometrului mapată în intervalul 0.0–12.0, folosită pentru calculul pitch shift |
**''timer.h''** | **''timer.h''** | ||
- | Folosește Timer0 pentru funcții asemănătoare cu Arduino: | + | Folosește Timer0 pentru funcții asemănătoare cu Arduino |
- | * ''timer0_init()'' – configurează Timer0 în mod CTC, cu întrerupere pe compare match A | + | * ''timer0_init()'': configurează Timer0 în mod CTC, cu întrerupere pe compare match A |
- | * ''_millis()'' – returnează timpul scurs în milisecunde, folosit pentru debounce și timestamp-uri | + | * ''_millis()'': returnează timpul scurs în milisecunde, folosit pentru debounce și timestamp-uri |
- | * ''_delay(ms)'' – întârziere software folosind ''_millis()'' | + | * ''_delay(ms)'': întârziere software folosind ''_millis()'' |
**''usart.h''** | **''usart.h''** | ||
- | Comunicare serială cu modulul HC-05: | + | Comunicare serială cu modulul HC-05 |
- | * ''usart0_init(ubrr)'' – inițializează USART0 cu baud 9600, format 8N1 | + | * ''usart0_init(ubrr)'': inițializează USART0 cu baud 9600, format 8N1 |
- | * ''usart0_print(str)'' – transmite un șir de caractere prin USART, folosește ''usart0_transmit(character)'', pentru a trasmite câte un caracter | + | * ''usart0_print(str)'': transmite un șir de caractere prin USART, folosește ''usart0_transmit(character)'', pentru a trasmite câte un caracter |
==== Decizii și detalii de implementare ==== | ==== Decizii și detalii de implementare ==== | ||
Line 215: | Line 217: | ||
Structura grupează bitul asociat unui pin cu adresele registrelor sale, făcând codul mai lizibil și mai ușor de scris. | Structura grupează bitul asociat unui pin cu adresele registrelor sale, făcând codul mai lizibil și mai ușor de scris. | ||
- | Câmpurile sunt declarate ca ''volatile'', asigurând că velorile registrelor sun scrise și citite exact în momentul în care sunt accesate în cod. | + | Câmpurile sunt declarate ca ''volatile'', asigurând că valorile registrelor sunt scrise și citite exact în momentul în care sunt accesate în cod. |
Line 285: | Line 287: | ||
Permite conectarea la dispozitiv prin port serial și înregistrarea notelor transmise în timp real. | Permite conectarea la dispozitiv prin port serial și înregistrarea notelor transmise în timp real. | ||
+ | |||
+ | {{:pm:prj2025:ccristi:screenshot_2025-05-28_005653.png?nolink&500|}} | ||
* **Port name** – câmp text pentru introducerea portului serial (ex: ''COM11'', ''/dev/ttyUSB0'') | * **Port name** – câmp text pentru introducerea portului serial (ex: ''COM11'', ''/dev/ttyUSB0'') | ||
Line 292: | Line 296: | ||
* **Start Recording/Stop Recording** – pornește sau oprește înregistrarea | * **Start Recording/Stop Recording** – pornește sau oprește înregistrarea | ||
* Înregistrarea se oprește automat și la primirea mesajului ''RECORD_OFF'' de la dispozitiv | * Înregistrarea se oprește automat și la primirea mesajului ''RECORD_OFF'' de la dispozitiv | ||
- | * După oprirea înregistrării, aplicația procesează datele și le salvează într-un fișier ''.mid'' | + | * După oprirea înregistrării, aplicația procesează datele și le salvează într-un fișier ''.mid'', în folderul ''recordings'' |
**2. View Recordings** | **2. View Recordings** | ||
Afișează toate melodiile înregistrate și permite redarea sau ștergerea acestora. | Afișează toate melodiile înregistrate și permite redarea sau ștergerea acestora. | ||
+ | |||
+ | {{:pm:prj2025:ccristi:screenshot_2025-05-28_005720.png?nolink&500|}} | ||
* **Listă de înregistrări** – scrollable, afișează toate fișierele MIDI salvate | * **Listă de înregistrări** – scrollable, afișează toate fișierele MIDI salvate | ||
Line 303: | Line 309: | ||
* **Play/Stop** – redă melodia selectată sau oprește redarea | * **Play/Stop** – redă melodia selectată sau oprește redarea | ||
* **Delete** – șterge fișierul selectat | * **Delete** – șterge fișierul selectat | ||
+ | |||
+ | |||
+ | ==== Testare ==== | ||
+ | |||
+ | Am testat funcționalitățile incremental, pe măsură ce le-am implementat, prin observarea comportamentului așteptat sau prin afișarea valorilor prin serial monitor, unde era necesar. | ||
+ | * Apăsare butoane - afișarea frecvenței corespunzătoare | ||
+ | * Debounce - se afișează un singur mesaj la fiecare apăsare | ||
+ | * Buzzer - redarea corectă a frecvențelor | ||
+ | * Pitch shift - afișarea valorii citite de la potențiometru, apoi afișarea frecvențelor ajustate și redarea acestora | ||
+ | * am verificat că frecvențele calculate corespund cu tabelul de frecvențe ale notelor (de exemplu, la poziția maximă, am verificat că frecvențele corespund gamei C5-C6) | ||
+ | * Activare/dezactivare mod record - testat vizual (LED) și prin verificarea mesajelor trimise | ||
+ | * Comunicația Bluetooth - testată inițial cu un script care doar citește și afișează mesajele în terminal, ulterior cu aplicația implementată | ||
+ | * am testat apoi cazurile speciale: se încearcă înregistrarea fără conexiune, se întrerupe conexiunea în timpul înregistrării | ||
+ | * Aplicația Python - am implementat și testat pe rând conectarea, citirea mesajelor (prin afișare în terminal), crearea fișierelor MIDI (testate prin redare cu un player și prin analiza notelor într-un software dedicat), redarea înregistrărilor | ||
+ | * am testat cazurile speciale, ex: note fără ''note_off'', actualizarea interfeței la oprirea înregistrării de către dispozitiv (prin ''RECORD_OFF'') etc. | ||
===== Rezultate Obţinute ===== | ===== Rezultate Obţinute ===== | ||
- | <note tip> | + | [[https://youtu.be/qJW-3LLUZFE|Demo]]: |
- | Care au fost rezultatele obţinute în urma realizării proiectului vostru. | + | |
- | </note> | + | |
+ | <HTML><iframe width="560" height="315" src="//www.youtube.com/embed/qJW-3LLUZFE" frameborder="0" allowfullscreen></iframe></HTML> | ||
+ | |||
+ | {{:pm:prj2025:ccristi:whatsapp_image_2025-05-28_at_00.50.06_043a05d0.jpg?nolink&500|}} | ||
+ | |||
+ | {{:pm:prj2025:ccristi:whatsapp_image_2025-05-28_at_00.50.06_72c42e1a.jpg?nolink&500|}} | ||
===== Concluzii ===== | ===== Concluzii ===== | ||
+ | |||
+ | Proiectul m-a ajutat să înțeleg mai bine conceptele studiate în cadrul laboratoarelor, prin aplicarea practică a noțiunilor de GPIO, UART, PWM, ADC și timere. | ||
+ | |||
+ | În plus, proiectul mi-a oferit ocazia să învăț noțiuni noi despre formatul MIDI și modul în care se procesează digital muzica, de la conversia frecvențelor în note până la generarea și redarea fișierelor MIDI. | ||
+ | |||
+ | |||
===== Download ===== | ===== Download ===== | ||
- | Firmware: {{:pm:prj2025:ccristi:mini-synth-firmware.zip|}} | + | Cod microcontroller: {{:pm:prj2025:ccristi:mini-synth-firmware.zip|}} |
Recorder Python: {{:pm:prj2025:ccristi:mini-synth-recorder.zip|}} | Recorder Python: {{:pm:prj2025:ccristi:mini-synth-recorder.zip|}} | ||
Line 326: | Line 356: | ||
Resurse hardware: | Resurse hardware: | ||
- | * [[https://ww1.microchip.com/downloads/en/DeviceDoc/Atmel-7810-Automotive-Microcontrollers-ATmega328P_Datasheet.pdf|Datasheet Atmega328P]] | + | * Datasheet ATmega328P: [[https://ww1.microchip.com/downloads/en/DeviceDoc/Atmel-7810-Automotive-Microcontrollers-ATmega328P_Datasheet.pdf|Microchip]] |
- | * [[https://upload.wikimedia.org/wikipedia/commons/thumb/e/e4/Arduino-nano-pinout.png/1200px-Arduino-nano-pinout.png?20190717220831|Pinout Arduino Nano]] | + | * Pinout Arduino Nano: [[https://upload.wikimedia.org/wikipedia/commons/thumb/e/e4/Arduino-nano-pinout.png/1200px-Arduino-nano-pinout.png|Wikipedia]] |
+ | * Detalii funcționare HC-05 [[https://lastminuteengineers.com/hc05-bluetooth-arduino-tutorial/|Last Minute Engineers]] | ||
+ | |||
+ | Resurse software: | ||
+ | * Exemplu software debounce: [[https://digilent.com/reference/learn/microprocessor/tutorials/debouncing-via-software/start?srsltid=AfmBOopGY96OA4t9osU41cufoSORA-XfGQRbBblO_Mly4EVyrVYBwlT9|Digilent Reference]] | ||
+ | * Exemplu structură pin: [[https://www.avrfreaks.net/s/topic/a5C3l000000UZAwEAO/t149008?comment=P-1421885|AVR Freaks]] | ||
+ | * Frecvențe note muzicale: [[https://mixbutton.com/music-tools/frequency-and-pitch/music-note-to-frequency-chart|MixButton]] | ||
+ | * Formulă pitch shift: [[https://www.diva-portal.org/smash/get/diva2:1381398/FULLTEXT01.pdf|DiVA portal]] | ||
+ | |||
+ | |||
+ | Resurse aplicație Python: | ||
+ | |||
+ | * Documentație Mido: [[https://mido.readthedocs.io/en/stable/files/midi.html|mido.readthedocs.io]] | ||
+ | * Documentație pySerial: [[https://pyserial.readthedocs.io/en/latest/pyserial.html|pyserial.readthedocs.io]] | ||
+ | * Documentație Pygame GUI: [[https://pygame-gui.readthedocs.io/en/latest/index.html|pygame-gui.readthedocs.io]] | ||
+ | * Exemple Pygame GUI: [[https://github.com/MyreMylar/pygame_gui_examples|pygame_gui_examples (GitHub)]] | ||