Come scrivere una libreria per Arduino

Scrivere una libreria per Arduino

Chi ha già provato a scrivere uno sketch per Arduino sa che lo sviluppo per questo tipo di piattaforma è relativamente semplice, grazie a un linguaggio intuitivo, un ambiente di sviluppo integrato, e numerosi esempi già pronti per l’uso. Se a questo punto volessimo condividere il codice che abbiamo sviluppato con dei nostri amici o con degli appassionati sparsi in giro per il mondo, il passo da seguire è quello di preparare una libreria. Vediamo come.

Come esempio, creeremo una libreria molto semplice. Del resto, quello che ci interessa maggiormente ora è apprendere i passi da seguire per la creazione di una nuova libreria; questi passi potranno poi essere applicati anche al caso di librerie per applicazioni maggiormente complesse.

Quali sono i principali vantaggi che derivano dall’utilizzo di una libreria? I vantaggi offerti da una libreria possono essere sintetizzati nel modo seguente:

  • semplifica l’utilizzo e l’organizzazione del codice. Infatti, una libreria ben scritta e testata, mette a disposizione dell’utilizzare delle funzioni pronte per l’uso: l’utente non deve preoccuparsi di come una particolare funzione è stata implementata, è sufficiente sapere come deve essere utilizzata
  • migliora la leggibilità del codice: il codice dell’applicazione si snellisce ed è più semplice da comprendere
  • decentralizza la logica: lo sketch può infatti focalizzarsi su uno specifico processing, trascurando (o meglio “nascondendo”) gli aspetti implementativi gestiti all’interno della libreria. Si usa spesso dire che una libreria deve specificare cosa, quando, e dove, ma non come
  • permette di mantenere aggiornato il codice: se una stessa libreria viene utilizzata da più utenti, quando viene rilasciato un aggiornamento (in seguito ad esempio a del bug-fixing, oppure a seguito dell’aggiunta di nuove funzionalità), la stessa libreria può essere importata dagli utenti, che potranno così disporre immediatamente della nuova versione (con minime o addirittura senza alcuna modifica al proprio codice)

Supponiamo ora di voler scrivere una libreria che permetta di controllare lo stato di un led collegato a una uscita di Arduino. Possiamo pensare alle seguenti funzioni da includere nella nostra libreria:

  • initialize: è la funzione di inizializzazione, quindi verrà chiamata una sola volta allo startup del sistema. Riceve come parametro il numero del segnale (pin) della scheda Arduino che si intende utilizzare per comandare il led. Il codice di questa procedura provvederà automaticamente a configurare questo pin come pin di uscita. Non è previsto alcun valore di ritorno dalla funzione. Il suo prototipo sarà perciò di questo tipo:
    void initialize (byte pinLed);
  • on: forza l’accensione del led. Non è richiesto alcun parametro e non esiste valore di ritorno. Il suo prototipo sarà perciò il seguente:
    void on(void);
  • off: forza lo spegnimento del led. Non è richiesto alcun parametro e non esiste valore di ritorno. Il suo prototipo sarà perciò il seguente:
    void off(void);
  • blink: causa il lampeggio del led. Come parametro viene passato il periodo desiderato per il lampeggio. Se ad esempio si vuole ottenere un lampeggio alla frequenza di 20 Hz, occorrerà passerà come parametro il valore 50 (l’unità di misura sono i millisecondi). Per questo parametro è stata prevista una variabile di tipo unsigned short in modo tale da poter gestire periodi anche superiori a 255 millisecondi. Non è previsto alcun valore di ritorno, per cui il prototipo di questa funzione è il seguente:
    void blink (unsigned short periodMs);

Possiamo a questo punto vedere l’implementazione completa di queste funzioni; il passo successivo sarà quello di “calarle” all’interno di una libreria:

void initialize (byte pinLed)
{
  pinGlob = pinLed;
  pinMode(pinGlob, OUTPUT);
}

void on(void)
{
  digitalWrite(pinGlob, HIGH);
}

void off(void)
{
  digitalWrite(pinGlob, LOW);
}

void blink (unsigned short periodMs)
{
  on();
  delay(periodMs/2);
  off();
  delay(periodMs/2);
}

Abbiamo a questo punto visto una possibile implementazione per le funzioni che vogliamo includere nella nostra libreria. Prima di procedere, è però utile spendere qualche parola sulla convenzione adottata nel mondo Arduino per scegliere i nomi delle funzioni e delle variabili. Questa convenzione, che seguiremo nella scrittura della nostra libreria, prevede che i nomi della libreria siano in UppercaseUppercase (MaiuscoloMaiuscolo), mentre quelli delle funzioni in lowercaseUppercase (minuscoloMaiuscolo). Ciò significa che la nostra libreria dovrà avere un nome tutto maiuscolo (scegliamo ad esempio il nome LEDLIB), mentre i nomi delle funzioni e delle variabili saranno tutti in minuscolo, con maiuscolo solo la prima lettera di ogni parola (eccetto la prima parola, che è tutta in minuscolo). Nel mondo Arduino, le librerie corrispondono a delle classi (si segue la stessa sintassi del C++), cioè a dei particolari tipi di strutture. Ogni classe si suddivide poi in due file:

  • un file header (estensione .h), contenente la dichiarazione della classe, oltre alla definizione di eventuali tipi e costanti. Nel nostro caso, questo file si chiamerà LEDLIB.h
  • un file con il codice sorgente (estensione .cpp), contenente l’implementazione della classe, cioè il codice relativo a tutte le sue funzioni (esportate o locali). Le funzioni esportate da una classe corrispondono a quelle esportate dalla libreria, e vengono anche chiamate metodi. Nel nostro caso, il file sorgente della libreria si chiamerà LEDLIB.cpp

Il listato relativo al file LEDLIB.h sarà perciò il seguente:

#ifndef LEDLIB_H
#define LEDLIB_H

#include "Arduino.h"

class LEDLIB
{
   private:
      byte pinGlob;  // pin utilizzato per pilotare il LED

   public:
      void initialize (byte pinLed);
      void on(void);
      void off(void);
      void blink (unsigned short periodMs);
};

#endif

E’ importante notare come tutte le funzioni della libreria siano “public”, quindi visibili all’esterno, e quindi richiamabili da un’applicazione. E’ invece dichiarata come “private” la variabile pinGlob in quanto questa è locale alla classe e non deve essere visibile al suo esterno. Questo è invece il codice relativo all’implementazione della classe (LIBLED.cpp):

/*
  LEDLIB.cpp - Libreria di esempio per gestire
  l'accensione, lo spegnimento, e il lampeggio
  di un LED.
*/

#include "LEDLIB.h"  // dichiarazione della classe

/* funzione di inizializzazione */
void LEDLIB::initialize (byte pinLed)
{
  pinGlob = pinLed;
  pinMode(pinGlob, OUTPUT);
}

/* funzione di accensione del led */
void LEDLIB::on(void)
{
  digitalWrite(pinGlob, HIGH);
}

/* funzione di spegnimento del led */
void LEDLIB::off(void)
{
  digitalWrite(pinGlob, LOW);
}

/* funzione di lampeggio del led */
void LEDLIB::blink (unsigned short periodMs)
{
  on();
  delay(periodMs/2);
  off();
  delay(periodMs/2);
}

Siamo ora a buon punto, dobbiamo ancora vedere come “installare” la libreria (non preoccupatevi, è un’operazione molto semplice), e scrivere un piccolo esempio di utilizzo della stessa. I passi da seguire sono i seguenti:

  1. create un nuova cartella “LIBLED” nella sottocartella “libraries” del vostro ambiente di sviluppo per Arduino
  2. copiate i file LIBLED.h e LIBLED.cpp nella nuova cartella LEDLIB
  3. lanciate l’ambiente di sviluppo Arduino e selezionate l’opzione Sketch->Import Library dal menu principale: magia! Se avete eseguito correttamente i passi precedenti, sarà visibile nell’elenco la nuova libreria LEDLIB. Non selezionate comunque l’opzione di importazione della libreria, questa serve solo per includere l’header della libreria stessa nello sketch corrente

Il codice dell’esempio è il seguente:

#include <LEDLIB.h>

LEDLIB led;

void setup()
{
  led.initialize(13);
}

void loop()
{
  led.blink(1000);
}

La creazione di almeno un file di esempio è molto importante per due motivi:

  1. permette di testare la libreria: questa infatti non viene compilata fino al momento in cui è inclusa da un’applicazione
  2. la “filosofia” di Arduino prevede di allegare sempre, insieme alla libreria, almeno un file di esempio. Se provate infatti a guardare nella cartella “libraries” della vostra installazione Arduino, potrete trovare la sottocartella “examples” in corrispondenza di ogni libreria presente (ad esempio per la libreria EEPROM)

Se avete provato a caricare l’esempio di cui sopra, avrete potuto notare come l’ambiente di sviluppo di Arduino non abbia riconosciuto nessuno dei nuovi nomi introdotti (la classe e i suoi metodi). Ciò è normale, bisogna infatti “istruire” Arduino su quali sono questi nuovi simboli, in modo tale che l’IDE possa applicare ad essi l’appropriata colorazione. Per fare questo è sufficiente creare un file chiamato “keywords.txt” che andrà copiato nella stessa cartella in cui sono presenti i file della libreria. Nel nostro caso, il contenuto del file sarà il seguente:

#######################################
# Syntax Coloring Map For LEDLIB
#######################################

LEDLIB	KEYWORD1

initialize	KEYWORD2
on	KEYWORD2
off	KEYWORD2
blink	KEYWORD2

Vengono in pratica elencati i nuovi simboli e il tipo di colorazione da applicare agli stessi (per separare il nome del simbolo e il tipo di keyword, occorre utilizzare un singolo carattere TAB). Questo è l’ultimo passo necessario alla creazione di una libreria. Potete a questo punto distribuire a chi interessato le librerie da voi stessi create: sarà sufficiente, per praticità, comprimere tutti i file della cartella relativa alla libreria e rilasciare il file compresso.

Arduino è disponibile da Farnell

4 Comments

  1. slovati 25 luglio 2012
  2. slovati 31 luglio 2012
  3. slovati 25 marzo 2012
  4. slovati 3 aprile 2012

Leave a Reply