Il progetto è un esempio di un PLL (Phase-Locked Loop) implementato in C++. Un PLL è un circuito elettronico che può essere usato per sincronizzare un'onda a una frequenza di riferimento. Questo esempio utilizza un PLL semplice per mostrare come le varie componenti di un PLL lavorano insieme, visualizzando il risultato tramite GNUplot.
Il file principale del progetto è clean_pll_loop.cpp
. In questo file viene utilizzata la libreria gnuplot-iostream.h
per creare e aggiornare i grafici dinamicamente. Le componenti principali del PLL sono il rivelatore di fase, il filtro del loop e l'oscillatore controllato in tensione.
- Generazione del Segnale di Input: Viene creato un segnale coseno con una frequenza definita.
- Rivelatore di Fase: Calcola la differenza di fase tra il segnale di input e il segnale sinusoidale generato.
- Filtro del Loop: Applica un filtro proporzionale-integrativo per regolare l'uscita del PLL.
- Aggiornamento della Fase e dei Segnali: Aggiorna le stime di fase e i segnali sinusoidali e cosenoidi basati sulla fase stimata.
- Visualizzazione con GNUplot: Mostra in tempo reale i segnali generati e il segnale di input utilizzando GNUplot.
Il codice è stato testato principalmente su Linux (ZorinOS). Potrebbero esserci delle differenze nell'esecuzione su Windows o altri sistemi operativi.
-
Installare la libreria Boost: Necessaria per eseguire il codice. Su Linux, puoi installarla con il comando:
sudo apt install libboost-all-dev
Su Windows, scarica la libreria direttamente dal sito ufficiale di Boost.
-
Clonare il repository:
git clone https://github.com/italspazio-com/pll-to-cpp.git
-
Compilare il codice: Per eseguire direttamente il programma e vedere il grafico, usa:
./main
Per apportare modifiche al codice e poi compilarlo, usa:
g++ clean_pll_loop.cpp -o main -lboost_iostreams -lboost_system -lboost_filesystem
Il codice seguente è responsabile per l'aggiornamento dinamico del grafico tramite GNUplot:
cout << "Press Ctrl-C to quit (closing gnuplot window doesn't quit)." << endl;
// Invia i dati a gnuplot
gp << "plot '-' binary" << gp.binFmt1d(cos_out, "array") << "with lines lw 5 title 'cos_out', "
<< "'-' binary" << gp.binFmt1d(input_signal, "array") << "with lines lw 5 title 'input_signal'\n";
gp.sendBinary1d(cos_out);
gp.sendBinary1d(input_signal);
// Pulisce e aggiorna il grafico
gp.flush();
mysleep(50);
-
Comando di Plotting:
gp << "plot '-' binary" << gp.binFmt1d(cos_out, "array") << "with lines lw 5 title 'cos_out', " << "'-' binary" << gp.binFmt1d(input_signal, "array") << "with lines lw 5 title 'input_signal'\n";
gp << "plot '-' binary"
: Questo comando dice a GNUplot di aspettarsi dati in formato binario.gp.binFmt1d(cos_out, "array")
: Specifica che i dati per il grafico sono forniti come un array in formato binario. Ilcos_out
è il vettore contenente i dati del segnale coseno."with lines lw 5 title 'cos_out'"
: Indica che il segnalecos_out
deve essere tracciato con una linea di larghezza 5 e con il titolo 'cos_out'.- Analogamente,
gp.binFmt1d(input_signal, "array")
e"with lines lw 5 title 'input_signal'"
indicano che ancheinput_signal
deve essere tracciato come un array con una linea di larghezza 5 e il titolo 'input_signal'.
-
Invio dei Dati:
gp.sendBinary1d(cos_out); gp.sendBinary1d(input_signal);
gp.sendBinary1d(cos_out)
: Invia i dati del segnale coseno a GNUplot in formato binario.gp.sendBinary1d(input_signal)
: Invia i dati del segnale di input a GNUplot in formato binario.
-
Aggiornamento del Grafico:
gp.flush(); mysleep(50);
gp.flush()
: Forza GNUplot a visualizzare immediatamente i dati inviati e aggiornare il grafico.mysleep(50)
: Pausa l'esecuzione per 50 millisecondi per rallentare l'aggiornamento del grafico e renderlo visivamente fluido.