Nel seguente esempio si suppone di sollecitare il circuito con un segnale Onda Quadra e di rappresentare il grafico del segnale in uscita dal filtro. Si usa un componente wxSpinButton per variare il periodo dell'onda quadra.
Avviare un nuovo progetto wxDev-C++ basato su wxWidgets Frame. Salvarlo con il nome: CircuitoRC.
Sul frame collocare:
una barra dei menu,
un componente wxSpinButton, posizionandolo nella parte superiore del frame.
un componente wxStaticText, accanto al wxSpinButton.
Creare i due menu: File, contenente il comando "Esci", e Disegna, contenente il comando "Diagramma".
Alla proprietà Label del componente wxStaticText assegnare il valore 0.
Aggiungere una nuova unità al progetto, salvarla con nome Funzione.h.
class Funzione { private: double Periodo, Frequenza, Omega; public: Funzione(double T); double f(double t); double w(); void cambiaT(double T); double leggiT(); };
Aggiungere una nuova unità al progetto, salvarla con nome Funzione.cpp.
#include "Funzione.h" #include <math.h> // ------- Il costruttore ----------- // riceve un double ed inizializza i campi bembro. Funzione::Funzione(double T) { Periodo = T; Frequenza = 1/T; Omega = 6.28/T; } // -------- ONDA QUADRA -------- // riceve un double che confronta con il // semiperiodo, per restituire il valore del segnale double Funzione::f(double t) { int NrPer; if (t > Periodo) { NrPer = (int) (t/Periodo); t = t - (double) (NrPer*Periodo); } if (t <= Periodo/2) return -10.0; else return 10.0; } // funzioni di accesso ai campi membro. // leggi Omega double Funzione::w() { return Omega; } // modifica il periodo. void Funzione::cambiaT(double T) { Periodo = T; Frequenza = 1/T; Omega = 6.28/T; } // leggi il periodo. double Funzione::leggiT() { return Periodo; }
Aggiungere una nuova unità al progetto, salvarla con nome circuitoRC.h.
class circuitoRC { private: double R, C; double dt, tau; public: circuitoRC(double, double); double leggiTau(){return tau;} double leggidt(){return dt;} };
Aggiungere una nuova unità al progetto, salvarla con nome circuitoRC.cpp.
#include "circuitoRC.h" // --------- il costruttore ------------------- // riceve come parametri i valori della resistenza e della capacità // con questi valori calcola la costante di tempo e calcola l'ampiezza di // un intervallo di durata 1/100 della costante di tempo. circuitoRC::circuitoRC(double Ohm, double Farad) { R = Ohm; C = Farad; tau = R*C; dt = tau/100; }
I metodi della classe Frame devono poter accedere alla classe Funzione, per questa ragione creare un riferimento ad un oggetto di classe Funzione tra i campi membro della classe CircuitoRCFr.h
Nel file CircuitoRCFrm.h cercare l'intestazione della classe ed inserire una sezione public con la dichiarazione del riferimento all'oggetto di classe Funzione:
class CircuitoRCFrm : public wxFrame { public: Funzione *F; private: DECLARE_EVENT_TABLE();
In questo modo si è creato un puntatore ad un oggetto Funzione. Per creare l'oggetto a cui punta F aprire il file CircuitoRCApp.cpp. Osservare che viene creato un oggetto frame. Subito dopo creare l'oggetto Funzione ed assegnare ad F il puntatore a questa istanza:
bool CircuitoRCFrmApp::OnInit() { CircuitoRCFrm* frame = new CircuitoRCFrm(NULL); frame->F = new Funzione(0.00002); SetTopWindow(frame);
Nel File CircuiRCApp.cpp aggiungere la linea:
#include "Funzione.h"
Nel file CircuitoRCFrm.cpp inserire le due linee:
#include "circuitoRC.h" #include "Funzione.h"
Selezionare il componente wxSpinButton. Nella scheda Eventi associare un gestore all'evento onUp:
void CircuitoRCFrm::WxSpinButton1Up(wxSpinEvent& event) { // insert your code here wxString str = WxStaticText1->GetLabel(); // converte la stringa in double double n = wxAtof(str); n = F->leggiT(); if (n<100) n+=0.00005; else return; F->cambiaT(n); // dopo l'incremento converte il double in stringa str = wxString::Format(wxT("%f"), n); WxStaticText1->SetLabel(str); }
Il gestore di evento legge il valore della label (nella scheda Proprietà fissare a 0 il valore della proprietà Label), lo converte in un double, legge il periodo, e se è minore di 100 lo incrementa e lo aggiorna nell'istanza di F.
Nella scheda Eventi del wxSpinButton associare un gestore all'evento onDown:
void CircuitoRCFrm::WxSpinButton1Down(wxSpinEvent& event) { // insert your code here wxString str = WxStaticText1->GetLabel(); // converte la stringa in double double n = wxAtof(str); n = F->leggiT(); if (n>0) n-=0.00005; else return; F->cambiaT(n); // dopo l'incremento converte il double in stringa str = wxString::Format(wxT("%f"), n); WxStaticText1->SetLabel(str); }
Disegnare la griglia su cui verrà rappresentato il grafico. La funzione riceve il parametro dc per disegnare sul device context.
void griglia(wxClientDC &dc) { dc.Clear(); wxPen pen(*wxCYAN, 1, wxDOT); // penna rossa - spessore 1 - tratteggiata dc.SetPen(pen); for (int x=0; x<340; x+=10) dc.DrawLine(x,40,x,280); for (int y=40; y<280; y+=10) dc.DrawLine(0,y,380,y); }
Selezionare la barra dei menu. Nella scheda Proprietà clic sulla riga Edit Menu Items. Espandere il menu Disegna e aggiungere un gestore di evento associato alla voce di menu "Diagramma". Aprire il file CircuitoRCFrm.cpp e completareil gestore di evento:
void CircuitoRCFrm::Mnudiagramma1006Click(wxCommandEvent& event) { // insert your code here wxClientDC dc(this); wxPen pen(*wxRED, 1); // penna rossa - spessore 1 dc.SetPen(pen); griglia(dc); int YAscisse, XOrdinate, AsseOrdinate, X, Y, y; double scalaX, scalaY, t, Vu, derivata, dVu, tMax; circuitoRC *C; C = new circuitoRC(10.0, 0.00002); tMax = C->leggiTau()*25; scalaX=300.0/(tMax); scalaY=200.0/25.0; Vu=0.0; derivata=(F->f(0)-Vu)/C->leggiTau(); YAscisse=150; AsseOrdinate=150; XOrdinate=200; dc.DrawLine(0,YAscisse,400,YAscisse); dc.DrawLine(AsseOrdinate, 240,AsseOrdinate,0); for (t=0.0; t<=tMax; t+=C->leggidt()){ X = (int) (scalaX*t); y = (int) (F->f(t)*scalaY)+YAscisse; dc.SetPen(*wxBLACK); dc.DrawPoint(X,y); dc.SetPen(*wxRED); y=(int)(scalaY*Vu+YAscisse); dc.DrawPoint(X,y); dVu = derivata*C->leggidt(); Vu = Vu + dVu; derivata=(F->f(t)-Vu)/C->leggiTau(); } }
Modificare il segnale dato in ingresso al filtro in un segnale sinusoidale e, se necessario, tarare la griglia per inviduare la banda passante del filtro.