wxWidgets

leggi il paragrafo: modello del canale.

Banda passante di un filtro.

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:

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();
  } 
}

Esercizi.

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.