Free Pascal

Free Pascal su Raspberry Pi: GPIO, eventi e misure a ultrasuoni

calendar_today personTeam EGSOFT schedule5 min di lettura
info

Disclaimer: le informazioni pubblicate in questa sezione hanno finalità di pura divulgazione tecnica. EG Software S.r.l. non si assume alcuna responsabilità per un utilizzo improprio dei contenuti, né per eventuali danni diretti o indiretti derivanti dalla loro applicazione, e non garantisce l'aggiornamento, l'accuratezza o la completezza delle informazioni riportate. Prima di utilizzare in produzione codice o procedure qui descritte, verificane sempre l'adeguatezza al proprio contesto.

Free Pascal ha una caratteristica che lo distingue nettamente da Delphi nell'ambito embedded: il compilatore supporta nativamente la cross-compilazione verso architetture ARM, il che lo rende adatto a progetti su Raspberry Pi anche senza installare un IDE completo sulla scheda. Da un PC Windows o Linux si può compilare un binario ARM da eseguire poi via SSH o SFTP sul dispositivo. Vediamo un caso pratico: controllo di un LED tramite pulsante e misura di una distanza con un sensore a ultrasuoni.

Cross-compilare per Raspberry Pi

Il flag principale da conoscere è -P per la piattaforma di destinazione (ad esempio -Parm per ARM a 32 bit) e -T per il sistema operativo target (-Tlinux). In Lazarus questi parametri si impostano nelle opzioni di progetto, sezione "Target CPU family / OS", senza dover richiamare il compilatore da riga di comando ogni volta. Il codice applicativo resta lo stesso: cambia solo la libreria che effettivamente parla con i pin fisici, tipicamente un binding a sysfs o a libgpiod.

GPIO digitale: uscite e ingressi

Una volta impostata la modalità di un pin (input/output) le operazioni di base sono semplici: scrittura digitale su un'uscita e lettura su un ingresso. Ecco un esempio, ripulito, di controllo di un LED bicolore in funzione dello stato di un pulsante:

program GPIOLedControl;

{$mode objfpc}{$H+}

uses
  Classes, SysUtils, CThreads, RPiGPIO; // unit di binding GPIO, non inclusa in FPC

const
  BtnPin = 11;
  GreenPin = 12;
  RedPin = 13;

procedure AggiornaLed(statoPulsante: integer);
begin
  if statoPulsante = 0 then
  begin
    RPiGPIO.DigitalWrite(RedPin, HIGH);
    RPiGPIO.DigitalWrite(GreenPin, LOW);
  end
  else
  begin
    RPiGPIO.DigitalWrite(RedPin, LOW);
    RPiGPIO.DigitalWrite(GreenPin, HIGH);
  end;
end;

procedure Setup;
begin
  RPiGPIO.SetMode(BOARD);
  RPiGPIO.PinMode(GreenPin, OUTPUT);
  RPiGPIO.PinMode(RedPin, OUTPUT);
  RPiGPIO.PinMode(BtnPin, INPUT);
  RPiGPIO.PullUpDn(BtnPin, PUD_UP);
end;

Eventi asincroni sui pin: niente polling continuo

Invece di interrogare il pin in un ciclo stretto — che consuma CPU inutilmente — molte librerie GPIO per Raspberry Pi offrono un meccanismo a interrupt: si registra una callback che viene invocata dal sistema solo quando il segnale cambia stato, con un tempo di debounce configurabile.

procedure OnPulsanteCambiato(pin: integer);
begin
  AggiornaLed(RPiGPIO.DigitalRead(pin));
end;

// Registra la callback su fronte di salita e discesa, con 200 ms di debounce
RPiGPIO.AddEventDetect(BtnPin, BOTH, @OnPulsanteCambiato, 200);

Misurare tempi con precisione: il sensore a ultrasuoni

Un sensore a ultrasuoni tipo HC-SR04 calcola la distanza misurando il tempo che l'eco impiega a tornare dopo un impulso sul pin trigger. In Free Pascal questo si traduce in un'attesa attiva sui due pin e in un calcolo basato su DateUtils:

function MisuraDistanza: Double;
var
  inizio, fine: TDateTime;
begin
  GPIO.Output(TRIG, 0);
  Sleep(1);
  GPIO.Output(TRIG, 1);
  Sleep(1);
  GPIO.Output(TRIG, 0);

  while GPIO.Input(ECHO) = 0 do ; // attesa inizio eco
  inizio := Now;

  while GPIO.Input(ECHO) = 1 do ; // attesa fine eco
  fine := Now;

  // Velocità del suono ~340 m/s, tempo diviso 2 (andata e ritorno)
  Result := MilliSecondsBetween(fine, inizio) / 1000 * 340 / 2 * 100;
end;

Va detto che la risoluzione dei timer di sistema su cui si basa Now non è pensata per misure a livello di microsecondi: per progetti reali conviene appoggiarsi a funzioni di timing più fini offerte dalla libreria GPIO scelta, oppure a un timer hardware dedicato. Il codice qui sopra va bene per capire il principio, meno per un uso in produzione dove serva precisione millimetrica.

Altri articoli su Free Pascal grid_viewTutte le tematiche
Scrivici su WhatsApp