This is an old revision of the document!


Secțiunea 1 - Semnale în domeniul frecvență

Semnale și sisteme de bază

La curs am discutat despre semnale de bază și sisteme. În continuare vom face câteva exerciții legate de aceste noțiuni.

Exercițiul 1

[2p]

Pentru a transmite simboluri (ex: litere din alfabet) modemurile folosesc diferite frecvențe și mai multe niveluri de amplitudine. O transmisie se face într-o perioadă de timp T (interval de transmisie) și poate conține o suprapunere de mai multe semnale, e.g. suma a două semnale de amplitudini și frecvențe diferite:

$x(t) = A_{1} \cdot sin(2\cdot \pi\cdot f_{1}\cdot t) + A_{2} \cdot sin(2\cdot \pi\cdot f_{2}\cdot t)$

  1. Care este cel mai mic interval de transmisie care are sens să fie folosit, dacă $f_1 = 1600$ Hz și $f_2 = 1800$ Hz? Cu alte cuvinte, cât ar trebui să fie $T$ astfel încât semnalul să aibă un număr întreg de cicluri? [1p]
  2. Afişaţi semnalul produs de modem pe parcursul a trei intervale de transmisie. Pentru primul interval de transmisie puteți folosi $A_1 = 0$ și $A_2 = 1$, pentru al doilea interval $A_1 = 1$ și $A_2 = 1$, iar pentru al treilea interval $A_1 = 1$ și $A_2 = 0$. Aşa cum am învăţat în laboratorul trecut adăugaţi titlu şi etichete plot-ului. [1p]

Ar trebui să obțineți ceva similar:

Pentru $\pi$ puteți folosi comanda np.pi din biblioteca numpy. Pentru concatenare puteți folosi np.concatenate sau np.hstack

Afișați grafic semnalul ca în laboratorul 1 folosind biblioteca matplotlib.

După ce ați făcut plot-ul puteți pune un titlu figurii folosind și etichete axelor X și Y.

Exerciţiul 2

[2.5p]

La curs am văzut că putem descompune semnalele într-o sumă de mai multe semnale de bază (ramp, step etc.). Pentru acest exerciţiu veţi încerca să folosiţi semnalele 'step' şi 'ramp' pentru a crea semnalul reprezentat cu negru în acest slide: building_signals.pdf

Pentru a face asta în Python va trebui să lucrăm cu semnale discrete, nu continue (vom discuta despre acest aspect în cursurile viitoare). În loc să lucrăm cu semnale reprezentate în intervalul [0,1] ca în slide vom folosi semnale ce se întind peste 100 de puncte.

Puteţi folosi următoarea funcţie pentru a crea un semnal 'ramp' peste N puncte:

ramp.py
import numpy as np
 
 
def ramp(N):
    y = np.zeros(N, dtype=int)
    for t in range(0, N):
        y[t] = t
    return y

Pentru a apela funcția 'ramp' din ramp.py într-un alt fișier .py (care se află în același director) puteți folosi următorul cod:

ex2.py
from ramp import ramp

Task-ul vostru este să creaţi un semnal combinat, ca cel din slide, dar folosind secvenţe discrete, cu o formulă ca cea de mai jos:

$s(i) = r(i) - r(i-T) - T \cdot u(i-T)$

unde $i$ este un index de la 0 la N (în loc de un număr real de la 0 la 1), $T$ este întârzierea, $s$ este semnalul rezultat, $r$ este semnalul 'ramp' (eventual întârziat cu $T$) și $u$ este semnalul 'unit step' (întârziat aici cu $T$).

  • $r(i-T)$ este doar o notaţie care marchează faptul că folosim un semnal 'ramp' întârziat cu $T$. Nu trebuie să apelaţi funcţia ramp cu argumentul $(i-T)$ pentru că nu va funcţiona. Va trebui să întârziaţi semnalul 'de mână' ca mai jos.
  • Folosim factorul $T$ în faţa lui $u(i-T)$ pentru că este amplitudinea la care $r(i)$ a ajuns până în acel moment şi vrem să avem semnalul final la 0.

Pentru asta ar trebui să:

  1. creaţi un semnal 'unit step' numit ustep.py, care practic întoarce o secvenţă de N valori de 1 [0.5p]
  2. să setaţi numărul de puncte la $N = 200$ şi delay-ul la $T = 100$
  3. să creaţi cele 3 semnale (care urmează să fie combinate) folosind 'ramp' şi 'ustep' cu $N$ şi $T$ de mai sus. [1p]
    • Creați secvența de input ca un șir cu elemente de la 1 la N cu pasul 1
    • Creați semnalul rampă, tot cu N elemente
    • Puteţi întârzia un semnal cu $T$ în felul următor (o posibilă soluție):
       s_delayed = np.pad(s[:N - T], (T, 0)) 

      Documentație np.pad. Mai puteți concatena zerouri folosind np.concatenate, np.hstack, etc.

  4. combinaţi cele 3 semnale
  5. afişaţi toate cele 4 semnale (cele 3 individuale şi combinaţia lor) [1p]
    • folosiţi culori diferite (eventual grosimi de linie diferite) pentru fiecare semnal şi afişaţi legenda pentru a diferenţia semnalele.

Consultați documentația Matplotlib Documentație matplotlib.pyplot, pentru a afișa semnalele cu stiluri, culori sau grosimi diferite.

Pentru a afişa mai multe semnale în aceeaşi figură cu ajutorul comenzii $plot$ puteţi folosi după toate plot-urile:

 plt.show() 

Ar trebui să obțineţi ceva similar imaginii de mai jos:

Exerciţiul 3

[2p]

La curs am văzut că datorită egalității lui Euler putem scrie o exponenţială complexă ca o sumă de sin şi cos:

$e^{j\cdot t} = \cos(t) + j\cdot \sin(t)$

De asemenea:

$e^{-j \cdot t} = \cos(t) - j \cdot \sin(t)$

Adunând aceste 2 ecuaţii şi împărţind la 2 obţinem:

$\cos(t) = \frac{e^{j \cdot t} + e^{-j \cdot t}}{2}$

Încercaţi să arătaţi asta în Python, făcând următoarele:

  • Folosiţi secvenţa de input
     t = np.array([0, np.pi / 6, np.pi / 4, np.pi / 3, np.pi / 2]) 
  • Afişaţi exponenţiala complexă $s_1 = e^{j\cdot t}$, e.g.
    complex_exp1 = np.exp(1j * t)
    x_complex_exp1 = np.real(complex_exp1)
    y_complex_exp1 = np.imag(complex_exp1)
    plt.plot(x_complex_exp1, y_complex_exp1, 'ro')
 
  • Afişaţi exponenţiala complexă $s_2 = e^{-j \cdot t}$ cu o altă culoare
  • Calculaţi media celor 2 exponenţiale $s_s = \frac{s_1 + s_2}{2}$, i.e. cos(t)
  • Afișaţi secvenţa rezultată în planul complex folosind np.real(ss) ca valori x şi np.imag(ss) ca valori y
  • Verificaţi dacă s1, s2 şi ss arată cum v-aţi fi aşteptat!
  • Opțional, calculați și afișați și sin(t)

Pentru numărul imaginar j, în Python se folosește notația 1j.

Folosiți codul următor pentru a desena un cerc trigonometric, peste care veți reprezenta valorile calculate mai sus

import numpy as np
import matplotlib.pyplot as plt
 
tt = np.arange(0, 2 * np.pi, 0.1)
figure1 = plt.figure('Figura 1', figsize=(10, 10))
complex_tt = np.exp(1j * tt)
x = np.real(complex_tt)
y = np.imag(complex_tt)
plt.plot(x, y, 'k.')
plt.plot(0, 0, 'kx')

Exerciţiul 4

[3.5p]

Avem un sistem de feedback precum cel din imaginea următoare:

Să presupunem că folosim acest sistem pentru sistemul de pilot automat al maşinii, unde x(t) este o constantă ce reprezintă viteza dorită, iar y(t) este viteza maşinii măsurată de vitezometru. În această aplicaţie, sistemul 2 este sistemul identitate (intrare = ieşire).

Să construim acest sistem având în vedere următoarele constrângeri:

  • viteza initială a maşinii este 7
  • valoarea iniţială a secvenţei de feedback (output-ul lui S2), f, este 0
  • valoarea iniţială pentru secvenţa de diferenţă, e, este 0
  • valoarea de input a sistemului de pilot automat, x, este o secvenţă de tipul [60, 60, …, 60]
  • primul sistem, S1, cunoaște viteza curentă y(i) şi primește ca parametru diferenţa e(i). Bazându-se pe acestea, actualizează viteza curentă după cum urmează:
    • Dacă e(i) > 10, atunci y(i+1) = y(i) + 5
    • altfel dacă e(i) > 0, atunci y(i+1) = y(i) + 1
    • altfel dacă e(i) == 0, atunci y(i+1) = y(i)

Construiţi sistemul S1 ca o funcţie cu 2 parametrii (viteza_curentă, e), care afişează următoarea viteză curentă ca mai sus. În Python puteţi folosi o instrucţiune for pentru asta:

N = 20;
y = np.zeros(N, dtype=int)
y[0] = 7;
for i in range(0, N - 1):
  ...
  y[i+1] = S1(y[i], e[i])
end

Rulaţi sistemul de N = 20 ori şi afişaţi outputul sistemului.

Semnale în domeniul frecvență

Materiale ajutătoare:

  1. Secțiunile 4.2 (Exercițiul 1), 4.5 (Exercițiul 2), 4.6 (Exercițiul 3)

Exercițiul 1 - seria Fourier

[5p]

În acest exercițiu vom începe să lucrăm cu seria Fourier, unul dintre cele mai importante instrumente în procesarea digitală a semnalelor. Va trebui să vă familiarizați cu acesta.

Orice semnal periodic de perioada $T$ se poate descompune într-o sumă de semnale de bază. Această descompunere poartă numele de seria Fourier și ne arată cum se descompune orice semnal periodic într-o sumă de sinusoide:

\begin{equation} s(t) = \sum_{k=-\infty}^{\infty}{c_{k}e^{j\frac{2 \pi kt}{T}}} \end{equation}

Având un semnal dat $s(t)$ putem calcula coeficienții Fourier după formula: \begin{equation} c_k = \frac{1}{T} \int_{t=0 }^{T}{s(t)e^{-j\frac{2 \pi kt}{T}}}dt \end{equation}

Folosind formula precedentă, un semnal dreptunghiular, de amplitudine “A” pe intervalul $[0, \frac{T}{2}]$ și de amplitudine ”-A” pe intervalul $[\frac{T}{2}, T]$ are coeficienții Fourier daţi de formula următoare:

\begin{equation} c_{k} = \left\lbrace \begin{array}{} \frac{2}{j \pi k}A \qquad k \quad impar \\0 \qquad \quad k \quad par \end{array} \right. \end{equation}

Semnalele reale au următoarea proprietate: coeficienții Fourier negativi sunt conjugații complecși ai celor pozitivi $c_{-k} = c_{k}^*$. Puteți verifica pentru semnalul nostru dreptunghiular. De asemenea, semnalele pare s(-t) = s(t), au coeficienții complet reali, obținând $c_{−k}=c_{k}$, iar semnalele impare s(-t) = -s(t), au coeficienții complet imaginari, obținând $c_{−k}=−c_{k}$.

În acest exerciţiu va trebui să încercaţi să reconstruiţi semnalul dreptunghiular folosind un număr limitat de coeficienți pentru a vedea diferenţa dintre semnalul original și cel reconstruit.

Principalii paşi pentru asta sunt:

  1. Creaţi semnalul original. Utilizaţi, de exemplu $T = 100$ şi $A = 3$ şi generaţi un semnal cu amplitudinea $3$ peste primele 50 de eşantioane şi $-3$ peste ultimele 50. Reprezentaţi grafic semnalul ca funcţie de timp. Ajustaţi limita verticală a plot-ului în range-ul $[-A-1, A+1]$ pentru a putea vedea mai bine graficul. [1p]
  2. Calculaţi coeficienţii Fourier $c_{k}$ pentru $k = [-k_{max}, k_{max}]$. De exemplu pentru $k_{max} = 3$, avem $k = {-3,-2,-1,0,1,2,3}$. Reprezentaţi grafic coeficienţii $c_k$ şi observaţi simetria lor în jurul lui $k = 0$. Pentru a îi reprezenta va trebui să folosiţi funcţia plt.stem. De asemenea, va trebui să reprezentaţi doar magnitudinea, adică valoarea absolută a coeficienților. [1p]
  3. Reconstruiţi semnalul doar cu ajutorul acestor coeficienţi, folosind formula: $s(t) = \sum_{k=-\infty}^{\infty}{c_{k}e^{j\frac{2 \pi kt}{T}}}$. [1p]
  4. Reprezentaţi grafic noul semnal reconstruit și comparați-l cu originalul. [1p]
  5. Folosiţi diferite valori pentru $k_{max}$ (de exemplu, 1, 5, 11, 49) și observaţi diferenţa. Vedeţi cum folosirea din ce în ce a mai multor coeficienţi ne permite să reconstruim mai bine semnalul original. [1p]

Graficele voastre trebuie să arate similar cu acestea:

Exercițiul 2 - aproximare de semnale

[5p]

Orice semnal este format dintr-o sumă de o infinitate de sinusoide complexe. Ce se întâmplă dacă facem suma doar peste un număr finit de astfel de termeni, ignorând termenii de ordin superior? În acest caz vom forma un semnal care aproximează semnalul original, iar aproximarea este cu atât mai bună cu cât folosim mai mulți termeni.

În acest exercițiu vom vedea cât de bine este aproximat un semnal, prin observarea erorii $\epsilon_{N}$ dintre semnalul original $s(t)$ și aproximarea $s_{N}(t)$ folosind doar termeni de ordin $\le N$ din seria Fourier (termenii corespunzători $k \in \{-N, \ldots, N\} $ )

Vom calcula rădăcina pătratică medie (eng. root mean square - RMS) a semnalului de eroare $\epsilon_{N}$ dat de:

\begin{equation} \epsilon_{N}(t) = s(t) - s_{N}(t), \end{equation}

Aproximarea $s_{N}(t)$ este dată de primii termeni din Seria Fourier. \begin{equation} s_N(t) = \sum_{k=-N}^N c_k e^\frac{j 2 \pi k t}{T} \end{equation}

iar RMS-ul lui $\epsilon_N$ este dat de: \begin{equation} \text{rms}(\epsilon_N) = \sqrt{\sum_{k=-\infty}^{-{N-1}} |c_k|^2 + \sum_{k=N+1}^\infty |c_k|^2} = \sqrt{2\cdot \sum_{k=N+1}^\infty |c_k|^2} \end{equation}

Task-ul vostru este să determinați valoarea lui N astfel încât $\text{rms}(\epsilon_N)$ este aproape 0 și după aceea să vedeți că într-adevăr semnalul reconstruit aproximează bine semnalul original.

O să folosim din nou semnalul dreptunghiular, de amplitudine 'A' în intervalul [0, T/2] și '-A' în intervalul [T/2, T] care are coeficienții Fourier dați de formula:

\begin{equation} c_{k} = \left\lbrace \begin{array}{} \frac{2}{j \pi k}A \qquad k \quad impar \\0 \qquad \quad k \quad par \end{array} \right. \end{equation}

Pentru asta ar trebui să urmăriți următorii pași:

  1. Creați semnalul original. Folosiți, de exemplu T=100 și A=1 pentru a genera semnalul cu valoarea 1 în primele 50 de eșantioane și -1 în ultimele 50. Reprezentaţi grafic semnalul ca funcţie de timp [1p].
  2. Calculați coeficienții Fourier $c_{k}$ pentru $k=[0:500]$. Plotați amplitudinile $|c_k|^2$ ca funcție de $k$, folosind stem și abs. [1p]
  3. Calculați $\text{rms}(\epsilon_{N})$ pentru fiecare $N \in \{1, \ldots, 500\}$. Vedeți explicația de mai jos pentru a putea calcula RMS folosind Teorema lui Parseval. Plotați (cu plot, semilogy și loglog) valoarea rms pentru $N \in \{1, \ldots, 500\}$.[1p]
  4. Determinați cel mai mic $N$ astfel încât $\text{rms}(\epsilon_{N}) < 0.05$ și reconstruiți semnalul original folosind acest număr de coeficienți. Trebuie să folosiți atât coeficienții pozitivi cât și negativi pentru a reconstrui semnalul. Reconstruiţi semnalul doar cu ajutorul acestor coeficienţi, folosind formula: $s_N(t) = \sum_{k=-N}^{N}{c_{k}e^{j\frac{2 \pi kt}{T}}}$. Reprezentați grafic semnalul reconstruit și comparați-l cu semnalul inițial. [2p]

Pentru a calcula RMS al erorii trebuie să calculăm suma pentru toți coeficienții $c_k$ cu $|k|> k_0 $, adică o infinitate de termeni. Putem încerca doar să aproximăm această sumă, sau ne putem folosi de unele proprietăți ale seriei Fourier pentru a o calcula exact. Mai precis, vom folosi Teorema lui Parseval prin care putem calcula puterea unui semnal în două feluri, în domeniul timp, integrând semnalul la pătrat peste o perioadă sau în frecvență calculând suma pătratelor modulului ale fiecărui coeficient:

\begin{equation} \frac{1}{T}\int_0^T{s^2(t)dt} = \sum_{-\infty}^{\infty}{|c_k|^2} \end{equation}

Folosind cele descrise mai sus puteți calcula exact RMS-ul erorii:

  1. calculați puterea totală calculând integrala din teorema lui Parseval pentru semnalul dreptunghiular.
  2. scădeți pătratele termenilor de la $c_k, k \in \{-N...N\}$ obținând suma termenilor necesari pentru calcularea RMS.

\begin{equation} \text{rms}(\epsilon_{N-1}) = \sqrt{2\cdot \sum_{k=N}^\infty |c_k|^2} = \sqrt{\sum_{k=-\infty}^\infty |c_k|^2 - \sum_{k=-N+1}^{N-1} |c_k|^2} = \sqrt{\sum_{k=-\infty}^\infty |c_k|^2 - (2 \cdot \sum_{k=1}^N |c_k|^2 + |c_0|^2)} \end{equation}

Exercițiul 3 - BONUS - comunicație digitală

[1p]

Pentru a transmite 2 biți simultan putem folosi două frecvențe diferite (f1, f2) pentru a coda o valoare de 2 biți:

  1. '00': folosim un semnal egal cu 0 (nicio frecvență)
  2. '01': folosim o sinusoidă ce conține doar prima frecvență ($\sin(2\pi f_1 t)$)
  3. '10': folosim o sinusoidă ce conține doar a doua frecvență ($\sin(2\pi f_2 t)$)
  4. '11': folosim ambele frecvențe $f_1$ și $f_2$

Task-ul vostru e să creați o secvență random de 10 valori între 0 și 3 (pentru a folosi toate valorile de mai sus) și apoi să o codificați folosind 2 sinusoide așa cum este descris mai sus. Pentru asta ar trebui să:

  1. selectați frecvențele $f_1$ și $f_2$ astfel încât ele să folosească aceeași frecvență fundamentală (de ex.: $f_1 = 1 \cdot f_t$, $f_2 = 2 \cdot f_t$, iar $f_t = 1$);
  2. plotați semnalul rezultat folosind perioada ($1/f_t$) pentru fiecare valoare transmisă;
  3. verificați că semnalul rezultat codează secvența voastră random;
ps/labs_python/02-04.1790454738.txt.gz · Last modified: 2026/09/26 23:32 by darius.necula
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