Arduino e i tipi di dati

Programmando con Sketching è inevitabile utilizzare delle variabili o costanti: senza questi elementi infatti nessun programma avrebbe senso.

 

LA MEMORIA

sensore CCD

Per poter lavorare Arduino (così come anche gli altri dispositivi simili) ha bisogno di utilizzare la memoria RAM. Possiamo immaginare la memoria come un foglio elettronico: ogni cella contiene delle informazioni e e ogni cella ha un indirizzo.

VARIABILI E COSTANTI

Una prima suddivisione del tipo di informazioni è tra variabili e costanti. Il nome parla chiaro: le prime possono cambiare e le seconde rimangono fisse. Prima domanda: a che servono le costanti se poi non cambiano? Risposta: perchè hanno un “nome” dal quale comprenderne il significato.

int mlivellopwm = 20;     // valore iniziale della potenza (VARIABILE)

const int kpinventola = 1;   // contatto di output e/ventola (COSTANTE)

Perchè differenziare tra costanti e variabili? Per sicurezza: se per sbaglio durante l’esecuzione, dovessi cambiare il valore di una variabile, potrei causare dei problemi, magari attivare erroneamente un motore, con tutti i danni che ne deriverebbero. Se invece è costante, quel valore è immodificabile.

DIVERSI TIPI

Sia le variabili e sia le costanti occupano della memoria, ma a seconda del tipo ne potranno occupare di più o di meno.

Facendo un paragone con un foglio elettronico  , a volte capita di allargare una colonna perchè non è in grado di contenere l’informazione.

Ancora, sempre nel foglio elettronico, capita di definire una o più celle come area “data ora”. Questa è una similitudine con i tipi di dato: diversi tipi per poter contenere e trattare adeguatamente il dato contenuto.

ELENCO DEI TIPI

TIPO DIMENSIONE (byte) FAMIGLIA/INTERVALLO
String  2K alfanumerico
array  limitato dalla memoria  alfanumerico/numerico
bool  1 byte  logico
boolean  deprecato, uguale a bool  logico
byte 1 byte  numerico, da 0 a 255
char 1 byte  numerico, da -127 a 128
double8 8 byte  numerico
float  4 byte  numerico,  da -3.4028235E38 a 3.4028235E38
int  2 byte  numerico, da -32768 a 32767
long  4 byte  numerico, no virgola, da -2147483648 a 2147483647
short  2 byte   numerico con segno
unsigned char  1 byte  alfanumerico, da 0 a 255
unsigned int  2 byte  numerico, da  0 a 65535
unsigned long  4 byte  numerico, da 0 a 4294967295
void  0  N.D.
word  2 byte  numerico, da  0 a 65535

FALSI AMICI

Anche Sketching ha i suoi false friends (cfr. wikipedia ).

kit comando luci (voolamp)

Mi riferisco a char, il cui nome lascerebbe intendere “carattere”, ovvero simbolo dell’alfabeto.
In realtà è un byte che contiene 2^8=256 valori. Peccato però char che abbia la gestione del segno, quindi i bit restanti diventano 7, e con 7 bit possiamo “mappare” solo i primi 128 simboli del codice ASCII. Infatti 2^7=128.

 

char mvalore = 66;     // identifica "B"

char mvalore2 = -66    // valido, ma *non* e' un simbolo ASCII

COSA SCEGLIERE

Tutto dipende da cosa dovrà contenere la variabile: numeri o caratteri?

Se abbiamo del testo possiamo usare:

  • serie di caratteri, ovvero char[]
  • String

Per quanto i numeri, la scelta è abbastanza ampia, ma il più delle volte il tutto si risolve in 2 o 3 tipi:

  • int
  • float
  • double

Con questi tipi è possibile gestire la quasi totalità delle variabili (o costanti).

E GLI ALTRI?

I diversi tipi, soddisfano due esigenze:

  • occupazione di memoria
  • velocità di elaborazione/calcolo

TEST DI VELOCITÀ

Qui di seguito uno script Sketching per provare la velocità di elaborazione delle differenti variabili: int, double e float.

I risultati appariranno sulla finestra di monitor seriale. Una possibile modifica potrebbe essere la “costante” MCICLI: l’importante è non superare il valore di 32000, pena una lunga attesa.

/*
FLW - www.fablabway.com

mauro rossolato

lab49 - test velocita' calcolo variabili

uses:

when who what
----------------------------
19.05.2016 mr creates

*/

//#define MCICLI 4096
#define MCICLI 16384


int moneshot = 1;
float mfloat = 3.0;
int mint = 3;
double mdouble = 3;
unsigned long mtmstart, mtmend;


void setup()
{
  Serial.begin(9600);
  Serial.println("FLW,2018 - test velocita' calcolo variabili, v.1.0");
}


void loop() {
  int mndx;
  if (moneshot == 1) {
    //-------------------------------------
    mtmstart = micros();
    for (mndx = 0; mndx < MCICLI; mndx++) {
      mdouble =  mdouble / 2;
    }
    mtmend = micros();
    Serial.print("durata ciclo double: ");
    Serial.print(mtmend - mtmstart );
    Serial.print(" microsecondi. Valore mdouble: ");
    Serial.println(mdouble);
    //-------------------------------------
    mtmstart = micros();
    for (mndx = 0; mndx < MCICLI; mndx++) {
      mint = mint / 2;
    }
    mtmend = micros();
    Serial.print("durata ciclo int: ");
    Serial.print(mtmend - mtmstart );
    Serial.print(" microsecondi. Valore mint: ");
    Serial.println(mint);
    //-------------------------------------
    mtmstart = micros();
    for (mndx = 0; mndx < MCICLI; mndx++) {
      mfloat = mfloat / 2.0;
    }
    mtmend = micros();
    Serial.print("durata ciclo float: ");
    Serial.print(mtmend - mtmstart );
    Serial.print(" microsecondi. Valore mfloat: ");
    Serial.println(mfloat);
    //-------------------------------------
    moneshot = 0;
  }
}

con questo risultato:

FLW,2018 - test velocita' calcolo variabili, v.1.0
... microsecondi

CONCLUSIONE

In Arduino, così come in altri linguaggi esistono diversi tipi di dati. Queste differenze servono per migliorare le prestazioni oppure l’occupazione di memoria. I tipi int, float e double sono quelli “universali”.

É possibile definire dei nuovi tipi custom? Si, ma lo vedremo prossimamente.