Sorgenti per funzioni utili per la simulazione

Generazione forme d'onda

Funzioni che elaborano il valore dell'ampiezza di un segnale a forma d'onda nota in funzione del parametro tempo

//==============================================================================
//                            Forme d'onda
//==============================================================================
//------------------------------------------------------------------------------
// Onda quadra
//t:   tempo in secondi
//Per: Periodo in secondi
//Amp: Ampiezza (Valore Massimo) in Volt
//Offset: scostamento dallo 0 in volt
function Quadra(t,Per,Amp,Offset:real):real;
begin
  if frac(t/Per)>0.5 then
    result:=-Amp+Offset
  else
    result:=Amp+Offset;
end;
 

//------------------------------------------------------------------------------
// Dente di sega
//t:   tempo in secondi
//Per: Periodo in secondi
//Amp: Ampiezza (Valore Massimo) in Volt
//Offset: scostamento dallo 0 in volt
function DenteSega(t,Per,Amp,Offset:real):real;
begin
  result:=-Amp+frac(t/Per)*Amp*2;
end;
 

//------------------------------------------------------------------------------
// Onda triangolare
//t:   tempo in secondi
//Per: Periodo in secondi
//Amp: Ampiezza (Valore Massimo) in Volt
//Offset: scostamento dallo 0 in volt
function Triangolare(t,Per,Amp,Offset:real):real;
var
  f:real;
begin
  f:=frac(t/Per);
  if f>0.5 then
    result:=-Amp+(1-f)*Amp*4+Offset
  else
    result:=-Amp+f*Amp*4+Offset;
end;
 

//------------------------------------------------------------------------------
// Sinusoide
//t:   tempo in secondi
//Per: Periodo in secondi
//Amp: Ampiezza (Valore Massimo) in Volt
//Offset: scostamento dallo 0 in volt
//Fase: sfasamento in radianti
function Sinusoide(t,Per,Amp,Offset,Fase:real):real;
begin
  result:=Offset+Amp*sin(2*pi/Per*t+Fase);
end;


Grafico

Disegna grafico dei dati presenti in una Stringgrid dentro un oggetto Image.
La prima colonna rappresenta l'asse x il resto delle colonne: le grandezze nell'asse y
La prima riga viene considerata come intestazione delle grandezze rappresentate nelle colonne.
//==============================================================================
//                            Grafico
//==============================================================================
procedure TForm1.Grafico(S:TStringGrid;I:TImage);
const
  ytxtfmt='%5.2g';
  xtxtfmt='%5.2g';
  ColoreSf=clWhite;
  ColoriY:array[1..4] of TColor=(clBlue,clRed,clGreen,clFuchsia);
  MgSx =30;
  MgDx =50;
  MgSu =20;
  MgGiu=35;
  DivR =8;
  DivC =10;
  StepLeg=20;

var
  MinX,MaxX:real;
  MinY,MaxY:real;
  MinY1,MaxY1:real;
  MinY2,MaxY2:real;
  n,m,x,y:integer;
  dqy,dqx:integer;
  kx,ky:real;
  st:string;
  x1,x2,y1,y2:integer;


  procedure marker(x,y:integer);
  const
    sz=3;
  begin
    I.Canvas.Rectangle(x-sz,y-sz,x+sz,y+sz);
  end;


  function ElabMin(C:integer):real;
  var
    r:integer;
    v:real;
  begin
    with S do
    begin
      result:=StrToFloat(Cells[C,1]);
      for r:=2 to RowCount-1 do
      begin
        v:=StrToFloat(Cells[C,r]);
        if v<result then
          result:=v;
      end;
    end;
  end;

  function ElabMax(C:integer):real;
  var
    r:integer;
    v:real;
  begin
    with S do
    begin
      result:=StrToFloat(Cells[C,1]);
      for r:=2 to RowCount-1 do
      begin
        v:=StrToFloat(Cells[C,r]);
        if v>result then
          result:=v;
      end;
    end;
  end;

begin
  //Cancella grafico
  I.Canvas.Brush.Color:=ColoreSf;
  I.Canvas.Pen.Style:=psSolid;
  I.Canvas.Pen.Color:=ClBlack;
  I.Canvas.Rectangle(0,0,I.Width,I.Height);
  //Elabora massimi e minini
  MinX :=ElabMin(0);
  MaxX :=ElabMax(0);
  MinY :=ElabMin(1);
  MaxY :=ElabMax(1);
  for n:=2 to S.ColCount-1 do
  begin
    MinY1:=ElabMin(n);
    if MinY>MinY1 then
      MinY:=MinY1;
    MaxY1:=ElabMax(n);
    if MaxY<MaxY1 then
      MaxY:=MaxY1
  end;
  //Disegna Reticolo
  dqy:= (I.Height-MgSu-MgGiu) div DivR;
  dqx:= (I.Width -MgSx-MgDx)  div DivC;
  ky:=dqy*DivR/(MaxY-MinY);
  kx:=dqx*DivC/(MaxX-MinX);
  I.Canvas.Pen.Style:=psDot;
  I.Canvas.Pen.Color:=ClGray;
  //Righe
  for n:=0 to DivR do
  begin
    with I.Canvas do
    begin
      MoveTo(MgSx,I.Height-MgGiu-(n*dqy));
      LineTo(MgSx+(DivC*dqx),I.Height-MgGiu-(n*dqy));
      st:=Format(ytxtfmt,[MinY+(MaxY-MinY)*n/DivR]);
      TextOut(MgSx-TextWidth(st)-2,I.Height-MgGiu-(n*dqy)-TextHeight(st) div 2-2,st);
    end;
  end;
  //Colonne
  for n:=0 to DivC do
  begin
    with I.Canvas do
    begin
      MoveTo(MgSx+(n*dqx),I.Height-MgGiu);
      LineTo(MgSx+(n*dqx),I.Height-MgGiu-(DivR*dqy));
      st:=Format(ytxtfmt,[MinX+(MaxX-MinX)*n/DivC]);
      TextOut(MgSx+(n*dqx)-TextWidth(st) div 2,I.Height-MgGiu+4,st);
    end;
  end;
  //Asse X
  I.Canvas.TextOut(MgSx+(I.Width-MgSx-MgDx) div 2-I.Canvas.TextWidth(S.Cells[0,0]) div 2,
                   I.Height-I.Canvas.TextHeight(S.Cells[0,0])-2,
                   S.Cells[0,0]);
  //Legenda
  y:=MgSu+(I.Height-MgSu-MgGiu) div 2 - (S.ColCount-1) * StepLeg div 2;
  x:=I.Width-MgDx+5;
  I.Canvas.Pen.Style:=psSolid;
  for n:=1 to S.ColCount-1 do
  begin
    with  I.Canvas do
    begin
      Pen.Color:=clBlack;
      TextOut(x,y+(n-1)*StepLeg,S.Cells[n,0]);
      Pen.Color:=ColoriY[n];
      MoveTo(x,y+(n-1)*StepLeg+TextHeight(S.Cells[n,0])+2);
      LineTo(x+TextWidth(S.Cells[n,0]),y+(n-1)*StepLeg+TextHeight(S.Cells[n,0])+2);
    end;
  end;
  I.Canvas.Pen.Color:=clBlack;
  //Grafica
  with  I.Canvas do
  begin
    for n:=2 to S.RowCount-1 do
    begin
      for m:=1 to S.ColCount-1 do
      begin
        Pen.Color:=ColoriY[m];
        x1:=MgSx+round((StrToFloat(S.Cells[0,n-1])-MinX)*kx);
        y1:=I.Height-MgGiu-round((StrToFloat(S.Cells[m,n-1])-MinY)*ky);
        x2:=MgSx+round((StrToFloat(S.Cells[0,n])-MinX)*kx);
        y2:=I.Height-MgGiu-round((StrToFloat(S.Cells[m,n])-MinY)*ky);
        if n=2 then
          marker(x1,y1);
        marker(x2,y2);
        MoveTo(x1,y1);
        LineTo(x2,y2);
      end;
    end;
  end;
end;