This shows you the differences between two versions of the page.
pm:prj2025:eradu:iosif.stan [2025/05/21 17:29] iosif.stan |
pm:prj2025:eradu:iosif.stan [2025/05/30 03:44] (current) iosif.stan |
||
---|---|---|---|
Line 1: | Line 1: | ||
====== Laser Microphone ====== | ====== Laser Microphone ====== | ||
===== Introducere ===== | ===== Introducere ===== | ||
- | |||
Microfon laser : | Microfon laser : | ||
- | * Proiectul constă într-un sistem de spionaj acustic bazat pe un microfon laser, care captează vibrațiile sunetelor reflectate de pe suprafețe (ex: geamuri) folosind două fotodiode și două lasere. Semnalul este amplificat și poate fi ascultat în timp real printr-o ieșire jack pentru căști. În paralel, un microcontroler ESP32 procesează cele două semnale pentru a reduce zgomotul și a extrage o versiune mai clară a sunetului captat. | + | * Proiectul constă într-un sistem de spionaj acustic bazat pe un microfon laser, care captează vibrațiile sunetelor reflectate de pe suprafețe (ex: geamuri) folosind două fotodiode și două lasere. Semnalul este amplificat și În paralel, un microcontroler ESP32 procesează cele două semnale pentru a reduce zgomotul și a extrage o versiune mai clară a sunetului captat. |
- | * Scopul proiectului este explorarea principiilor fizice și electronice din spatele microfoniei laser, dar și aplicarea unor tehnici de prelucrare a semnalului (digital signal processing) pe un microcontroler embedded, în vederea obținerii unui sistem de ascultare pasivă cu performanță ridicată. | + | * Scopul proiectului este explorarea principiilor fizice și electronice din spatele microfoniei laser, dar și aplicarea unor tehnici de prelucrare a semnalului (digital signal processing) pe un microcontroler embedded, în vederea obținerii unui sistem de ascultare pasivă. |
* Ideea a pornit din curiozitatea față de modul în care pot fi captate sunetele de la distanță, fără contact direct, folosind doar lumina. Am vrut să reproducem și să îmbunătățim principiul din spatele microfonului laser folosit în securitate și spionaj, integrând și un modul de procesare digitală pentru a filtra zgomotul ambiental. | * Ideea a pornit din curiozitatea față de modul în care pot fi captate sunetele de la distanță, fără contact direct, folosind doar lumina. Am vrut să reproducem și să îmbunătățim principiul din spatele microfonului laser folosit în securitate și spionaj, integrând și un modul de procesare digitală pentru a filtra zgomotul ambiental. | ||
* Proiectul este util pentru că oferă un exemplu aplicat de combinație între fizică, electronică analogică și procesare digitală a semnalului, fiind valoros atât educativ cât și tehnic. Pentru noi, reprezintă o provocare complexă care ne ajută să ne dezvoltăm abilitățile în embedded systems, filtrare digitală, și hardware design. Pentru alții, poate fi o unealtă de supraveghere pasivă sau un punct de plecare pentru cercetare în domeniul captării acustice non-invazive. | * Proiectul este util pentru că oferă un exemplu aplicat de combinație între fizică, electronică analogică și procesare digitală a semnalului, fiind valoros atât educativ cât și tehnic. Pentru noi, reprezintă o provocare complexă care ne ajută să ne dezvoltăm abilitățile în embedded systems, filtrare digitală, și hardware design. Pentru alții, poate fi o unealtă de supraveghere pasivă sau un punct de plecare pentru cercetare în domeniul captării acustice non-invazive. | ||
Line 21: | Line 20: | ||
Listă de piese: | Listă de piese: | ||
- | ESP32 DevKit (cu Wi-Fi și capacitate de procesare DSP) | ||
- | 2x Laser pointer roșu (clasă II sau III, alimentare 3–5V) | + | ESP32 DevKit1 |
- | 2x Fotodiodă (ex: BPW34 sau similar) | + | 2x Laser pointer roșu (alimentare 3–5V) |
- | 2x Amplificator operațional (MAX7804) | + | 2x Fotodiodă (opt101) |
- | + | ||
- | Priză jack stereo de 3.5mm (pentru ieșire audio) | + | |
Breadboard și fire de conexiune | Breadboard și fire de conexiune | ||
Sursă de alimentare stabilizată 5V | Sursă de alimentare stabilizată 5V | ||
+ | |||
+ | 3x led clasic (rosu , galben , verde) | ||
+ | |||
+ | 3x rezistente 220ohmi | ||
{{:pm:prj2025:eradu:IOSIF2.png?600|}}. | {{:pm:prj2025:eradu:IOSIF2.png?600|}}. | ||
Line 59: | Line 59: | ||
===== Algoritmi și structuri implementate: ===== | ===== Algoritmi și structuri implementate: ===== | ||
- | Citirea a două canale analogice conectate la ieșirile a două module OPT101 | + | Algoritmi și structuri: |
- | Filtrare software: | + | Citire simultană a două canale analogice (OPT101) |
- | moving average (medie glisantă) | + | Filtrare software: medie glisantă și mediană pe N eșantioane |
- | mediana pe N eșantioane | + | Reducere zgomot prin diferență: semnal final = semnal1 − semnal2 (pentru semnale în opoziție de fază) |
- | Reducere zgomot prin comparație diferențială: | + | Transmisie date prin UART sau Wi-Fi către laptop |
- | dacă semnalele sunt în opoziție de fază (unul e zgomot de fond, altul e reflexie utilă) | + | Funcționare: |
- | semnal final = semnal1 - semnal2 | + | setup(): |
- | Transmisie UART / Wi-Fi la laptop pentru analiză sau redare | + | Inițializează ADC (rezoluție 12 biți) |
- | -> setup() | + | Configurează pinii pentru OPT101 (GPIO34, GPIO35) |
- | inițializează ADC-urile (analogReadResolution(12)) | + | |
- | configurează pinii OPT101 (analogRead(GPIO34) și analogRead(GPIO35)) | + | Inițializează comunicația Serial/Wi-Fi |
- | inițializează comunicarea (USB Serial sau Wi-Fi) | + | loop(): |
- | -> loop() | + | Citește ambele canale periodic |
- | citește periodic ambele canale | + | |
- | adaugă valorile într-un buffer circular | + | Stochează valorile în buffer circular |
- | aplică un filtru ( | + | Aplică filtrul și calculează diferența |
- | calculează diferența dintre canale | + | Trimite rezultatul prin Serial/Wi-Fi |
- | + | ||
- | trimite rezultatul prin Serial/WiFi | + | |
===== COD SURSA : ===== | ===== COD SURSA : ===== | ||
- | <note tip> | + | CONST N_SAMPLES = 10 |
- | #define OPT1_PIN 34 | + | |
- | #define OPT2_PIN 35 | + | |
- | #define SELECT_GPIO 13 | + | |
- | #define N_SAMPLES 10 | + | BUFFER1 = array de 10 elemente, inițializate cu 0 |
- | float buffer1[N_SAMPLES] = {0}; | + | BUFFER2 = array de 10 elemente, inițializate cu 0 |
- | float buffer2[N_SAMPLES] = {0}; | + | |
- | int idx = 0; | + | |
- | void setup() { | + | IDX = 0 |
- | Serial.begin(115200); // UART - Laborator 1 | + | |
- | analogReadResolution(12); // ADC - Laborator 4 | + | |
- | pinMode(SELECT_GPIO, INPUT_PULLUP); // GPIO - Laborator 0 | + | FUNCȚIE setup: |
- | } | + | initializează comunicarea serială |
+ | setează rezoluția ADC la 12 biți | ||
+ | configurează pinul SELECT_GPIO ca intrare cu rezistență pull-up internă (dacă mai trebuie pentru alt scop) | ||
- | float average(float* buf) { | + | FUNCȚIE average(buffer): |
- | float sum = 0; | + | sumă = 0 |
- | for (int i = 0; i < N_SAMPLES; i++) sum += buf[i]; | + | pentru fiecare valoare din buffer: |
- | return sum / N_SAMPLES; | + | sumă = sumă + valoare |
- | } | + | returnează sumă împărțit la N_SAMPLES |
- | void loop() { | + | FUNCȚIE loop: |
- | bool useOpt1 = digitalRead(SELECT_GPIO); | + | citește valoarea analogică de pe pinul OPT1_PIN |
+ | salvează valoarea în BUFFER1[IDX] | ||
- | if (useOpt1) { | + | citește valoarea analogică de pe pinul OPT2_PIN |
- | buffer1[idx] = analogRead(OPT1_PIN); | + | salvează valoarea în BUFFER2[IDX] |
- | float avg = average(buffer1); | + | |
- | Serial.print("CH1: "); | + | |
- | Serial.println(avg); | + | |
- | } else { | + | |
- | buffer2[idx] = analogRead(OPT2_PIN); | + | |
- | float avg = average(buffer2); | + | |
- | Serial.print("CH2: "); | + | |
- | Serial.println(avg); | + | |
- | } | + | |
- | idx = (idx + 1) % N_SAMPLES; | + | calculează media1 = average(BUFFER1) |
- | delay(10); | + | calculează media2 = average(BUFFER2) |
- | } | + | |
- | </note> | + | calculează semnal_filtrat = media1 - media2 // exemplu de calcul pentru atenuarea zgomotului |
+ | |||
+ | afișează "Media senzor 1:" + media1 | ||
+ | afișează "Media senzor 2:" + media2 | ||
+ | afișează "Semnal filtrat:" + semnal_filtrat | ||
+ | |||
+ | IDX = (IDX + 1) modulo N_SAMPLES | ||
+ | |||
+ | așteaptă 10 milisecunde | ||
===== Script Receiver Python : ===== | ===== Script Receiver Python : ===== | ||
- | <note tip> | ||
- | import serial | ||
- | import time | ||
- | from collections import deque | ||
- | import matplotlib.pyplot as plt | ||
- | import matplotlib.animation as animation | ||
- | # Configurație port serial (modifică după caz) | + | DEFINE SERIAL_PORT = 'COM3' |
- | SERIAL_PORT = 'COM3' # sau '/dev/ttyUSB0' pe Linux | + | DEFINE BAUD_RATE = 115200 |
- | BAUD_RATE = 115200 | + | DEFINE BUFFER_SIZE = 100 |
- | # Inițializează buffer pentru grafic | + | INITIALIZE data_buffer ca coadă cu maxim BUFFER_SIZE elemente, toate inițializate cu 0 |
- | BUFFER_SIZE = 100 | + | |
- | data_buffer = deque([0]*BUFFER_SIZE, maxlen=BUFFER_SIZE) | + | |
- | # Inițializează graficul | + | INITIALIZE grafic cu axele setate astfel: |
- | fig, ax = plt.subplots() | + | axa verticală: 0 până la 4095 (rezoluție ADC 12 biți) |
- | line, = ax.plot([], [], lw=2) | + | axa orizontală: 0 până la BUFFER_SIZE |
- | ax.set_ylim(0, 4095) # ADC pe 12 biți | + | titlu: "Semnal de la ESP32" |
- | ax.set_xlim(0, BUFFER_SIZE) | + | etichete: "Valoare ADC" pe verticală, "Timp (ultimele N puncte)" pe orizontală |
- | ax.set_title("Semnal de la ESP32") | + | |
- | ax.set_ylabel("Valoare ADC") | + | |
- | ax.set_xlabel("Timp (ultimele N puncte)") | + | |
- | def update_plot(frame): | + | DESCHIDE portul serial pe SERIAL_PORT cu BAUD_RATE și timeout de 1 secundă |
- | global ser | + | AȘTEAPTĂ 2 secunde (pentru a permite ESP32 să pornească) |
- | try: | + | |
- | line_raw = ser.readline().decode().strip() | + | |
- | if line_raw.startswith("CH"): | + | |
- | val = float(line_raw.split(":")[1]) | + | |
- | data_buffer.append(val) | + | |
- | line.set_data(range(len(data_buffer)), list(data_buffer)) | + | |
- | except: | + | |
- | pass | + | |
- | return line, | + | |
- | # Deschide conexiunea serială | + | FUNCȚIE update_plot(frame): |
- | ser = serial.Serial(SERIAL_PORT, BAUD_RATE, timeout=1) | + | încearcă să citească un rând din portul serial |
- | time.sleep(2) # Așteaptă pornirea ESP-ului | + | dacă rândul începe cu "CH": |
+ | extrage valoarea numerică după ":" | ||
+ | adaugă valoarea în data_buffer (se șterge cel mai vechi dacă s-a depășit dimensiunea) | ||
+ | actualizează datele graficului cu valorile din data_buffer | ||
+ | ignoră orice eroare la citirea sau conversia datelor | ||
+ | returnează linia graficului actualizată | ||
- | # Pornește animația | + | PORNEȘTE animația graficului care apelează update_plot la fiecare 50 ms |
- | ani = animation.FuncAnimation(fig, update_plot, interval=50) | + | |
- | plt.tight_layout() | + | |
- | plt.show() | + | |
- | # Închide portul serial când se termină | + | CÂND fereastra graficului se închide: |
- | ser.close() | + | ÎNCHIDE portul serial |
- | </note> | + | |
===== Rezultate Obţinute ===== | ===== Rezultate Obţinute ===== | ||
- | <note tip> | + | Din pacate , deoarece fotodioda alesa de mine are un amplificator integrat (care este facut pentru semnale lente si mari ~ stingi aprinzi lumina) |
- | Care au fost rezultatele obţinute în urma realizării proiectului vostru. | + | nu am putut sa conectez aceasta dioda la amplificatorul MAX9814 , astfel ea nu a fost capabila sa capteze vibratiile mici alea geamului supus unor |
- | </note> | + | sunete . Dispozitivul poate insa capta miscari mai mari ale geamului insa nu la nivel de sunet . |
===== Concluzii ===== | ===== Concluzii ===== | ||
- | ===== Download ===== | + | Pentru a obtine rezultatul dorit ar trebui sa obtin o fotodioda separata si sa o leg la un MAX9814 , desi chiar si in acest caz nu sunt sigur daca |
+ | un esp32 are puterea de procesare pentru a genera un fisier audio. | ||
- | <note warning> | + | Insa a fost distractiv sa lucrez la acest proiect si am invatat multe despre programarea microprocesoarelor si despre cum functioneza semnalele analog , digitale si audio. |
- | O arhivă (sau mai multe dacă este cazul) cu fişierele obţinute în urma realizării proiectului: surse, scheme, etc. Un fişier README, un ChangeLog, un script de compilare şi copiere automată pe uC crează întotdeauna o impresie bună ;-). | + | |
- | Fişierele se încarcă pe wiki folosind facilitatea **Add Images or other files**. Namespace-ul în care se încarcă fişierele este de tipul **:pm:prj20??:c?** sau **:pm:prj20??:c?:nume_student** (dacă este cazul). **Exemplu:** Dumitru Alin, 331CC -> **:pm:prj2009:cc:dumitru_alin**. | + | Overall , proiectul functioneaza mai mult ca un senzor de miscare (ar putea fii folosit drept deschizator automat de usi sau de bariere) sau ca detector de cutremur sau batai in usa. Nu chiar ceea ce imi doream dar pe acolo . |
- | </note> | + | |
- | ===== Jurnal ===== | + | ===== Download ===== |
- | not finished yet | + | https://github.com/iosif-stan/pm |
===== Bibliografie/Resurse ===== | ===== Bibliografie/Resurse ===== | ||
- | not finished yet | + | Data sheet esp32 devkit 1 : |
+ | https://roboeq.ir/files/id/4034/name/ESP32%20MODULE.pdf/ | ||
+ | |||
+ | Inspiratie : | ||
+ | https://www.youtube.com/watch?v=EiVi8AjG4OY&t=173s | ||
+ | |||
+ | Opt 101 data sheet : | ||
+ | https://www.ti.com/lit/ds/symlink/opt101.pdf | ||
- | <html><a class="media mediafile mf_pdf" href="?do=export_pdf">Export to PDF</a></html> |