Arduino · 12 settembre 2013 0

Ottimizzare gli sketch

Quando parliamo di ottimizzare gli sketch, non ci riferiamo solo allo scrivere bene il codice ma anche ad usare determinati strumenti, al fine di ottimizzare le risorse del microcontrollore. Ad esempio, come abbiamo tante volte detto, la memoria dell’Atmega328P delle nostre schede Arduino è scarsa, ed usarla bene permette di risparmiarne molta.

Partiamo dall’analisi dello sketch “Blink” allegato all’IDE…

E’ senz’altro lo sketch più famoso. Eccolo (senza i commenti iniziali):

int led = 13;

// the setup routine runs once when you press reset:
void setup() {                
    // initialize the digital pin as an output.
    pinMode(led, OUTPUT);     
}

// the loop routine runs over and over again forever:
void loop() {
    digitalWrite(led, HIGH);   // turn the LED on (HIGH is the voltage level)
    delay(1000);               // wait for a second
    digitalWrite(led, LOW);    // turn the LED off by making the voltage LOW
    delay(1000);               // wait for a second
}

Funziona e fa il suo lavoro. Occupazione? 1.072 byte di Flash. Non molti, direte voi. Troppi, considerando le poche cose che fa!

Il problema sono le funzioni predefinite del core di Arduino, pinMode e digitalWrite. Esse aiutano la scrittura semplificata del codice nascondendo all’utente diverse cose che devono essere fatte. Ad esempio, pinMode deve convertire il numero di pin passato nel corrispondente piedino fisico del microcontrollore. digitalWrite, poi, non solo esegue questa conversione, ma controlla anche se il pin in questione è un pin dotato di funzionalità PWM e, in caso affermativo, disattiva il segnale PWM del pin, a prescindere dal fatto che esso sia oppure no presente.

Tutti questi controlli si traducono in istruzioni da compilare e salvare nella Flash. Se ora noi manipoliamo direttamente le porte logiche del microcontrollore, il nostro sketch “Blink” può diventare molto più snello:

int led = 13;

// the setup routine runs once when you press reset:
void setup() {                
    // initialize the digital pin as an output.
    //pinMode(led, OUTPUT);     
    DDRB |= (1<<5); 
}

// the loop routine runs over and over again forever:
void loop() {
    //digitalWrite(led, HIGH);   // turn the LED on (HIGH is the voltage level)
    PORTB |= (1<<5);
    delay(1000);               // wait for a second
    //digitalWrite(led, LOW);    // turn the LED off by making the voltage LOW
    PORTB &= ~(1<<5);
    delay(1000);               // wait for a second
}

Compilato, occupa 654 byte di Flash, ben 418 byte in meno! Un risparmio del 39% dato dal fatto che su 5 istruzioni contenute nel programma, 3 riguardavano la manipolazione delle porte. Se andiamo ad ottimizzare un programma più grande, il guadagno non sarà di sicuro di questa entità ma potremo senz’altro limare qualche centinaio di byte che, su sketch con dimensioni prossime al limite della Flash del 328P, possono fare la differenza.

Ultima nota sullo sketch. Nel “Blink” originale si nota l’uso del tipo “int” per la variabile led. Se ciò non è un errore sintattico, è comunque da deprecare perché porta a sprecare RAM. Al suo posto consiglio l’uso del tipo “byte”, che consuma 1 byte di RAM contro i 2 del tipo “int”.