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.

Arance, limoni e bergamotti in …3D!

 

Pian piano la stagione degli agrumi si sta compiendo. Tra poco infatti la primavera riavvierà il ciclo della Natura e così avremo le fiuriture e poi i frutti e poi…in tavola.

Non conosco il valore alimentre di un succo di frutta d’agrumi, quello che è certo è che ci vuole uno spremiagrumi. Una volta erano di vetro, ma oggi possiamo realizzarlo direttamente noi! Vediamo come progettarlo, in due puntate, con l’aiuto della mathart.

SINUSOIDE

A ben vedere, la parte centrale di uno uno spremiagrumi è una sinusoide: inizia a 90° e termina a 360.

Quindi partiamo da uno sviluppo di serie sinusoidale e par farlo useremo un foglio elettronico.

 

 

FOGLIO ELETTRONICO E SINUSOIDE

Apriamo Calc (Openoffice ad esempio…) ed inseriamo la prima riga:

il 50 e il 5. Poi creeremo la serie dei gradi nella colonna A. Per farlo basta scrivere 1,2, 3 e poi trascinare la “cross” fino alla 360^ riga:

poi, da 360 continueremo a ritroso e cioè da 360 a 90.

quindi in B2 la formula:

=SEN(RADIANTI(A2))

e in C2 questa: =B2*$A$1

infine in D2:

=CONCATENA("[";A2;",";SOSTITUISCI(C2;",";".");"],")

estendiamo queste formule per tuttii 360 gradi (Control-C e control-V), ed avremo qualcosa di simile:

Quella che ci servirà sara l’ultima colonna, la D.

ROTATE_EXTRUDE

Ora passiamo ad OpenSCAD.

In OpenSCAD useremo la funzione rotate_extrude() con segmentazione a 6 (o 7 per la Cabala!).

Questa funzione ci permette di passare dal mondo 2D a quello 3D. Ricordate Flatland. Io sì, mi ricordo di Abbott (il reverendo) e di Martin Gardner che su Scientific American curava la rubrica di matematica. Altri tempi…

Apriamo il nostro file di OpenSCAD così:

module mspicchi() {
rotate_extrude($fn=6)
scale ([1,2,1])
translate ([-90,0,0])polygon( points=[

quindi aggiungiamo il contenuto delle celle da 90 a 360 gradi, colonna D:

e chiudiamo con

]);
}

poi duplichiamo la funzione precedente:

module mspicchi_sub() {
rotate_extrude($fn=6)
scale ([1,2,1])
translate ([-90,0,0])polygon( points=[

ed inseriremo le celle da 360 a 90 (serie discendente), quindi chiuderemo con:

]);
}

infine la chiamata del “main”:

scale ([0.2,0.2,0.2])mspicchi();
difference() {
translate ([0,0,-40]) cylinder (h=40,r=60);
scale ([0.2,0.2,0.2]) mspicchi_sub();
  }

ed ecco il risultato:

COSA MANCA?

Beh, manca lo scarico per il liquido, ma questo lo vedremo nella seconda parte. Chi intanto volesse sperimentare con i file del foglio elettronico ed OpenSCAD può richiederli via email a fablabway@gmail.com

 

 

 

Come stampare in 3D una sfera

Se vogliamo stampare una sfera cava, magari una palla di Natale  per il nostro albero (siamo in anticipo…), faremo certamente contenti i nostri piccoli, ma una insidia si nasconde…

ESEMPIO IN OPENSCAD

Per il disegno possiamo utilizzare il nostro CAD preferito: in questo esempio userò OpenScad. Per semplicità dividerò la sfera in due parti (che potrò successivamente incollare):

difference() {
sphere (r=30,$fn=100);
    sphere (r=29,$fn=100);
    translate ([-30,-30,-30]) 
        cube([100,100,30]);
}

il risultato sarà:

sfera_cava

e fin qui tutto semplice, quindi salviamo l’STL e prima di passare al CAM facciamo qualche considerazione.

 

EQUAZIONE GONIOMETRICA

Come noto l’equazione goniometrica del cerchio è

r²=y²+x²

ora siamo molto vicini al problema: dobbiamo risolvere…

L’ULTIMO SALTO

Nel titolo del paragrafo nulla di struggente o poetico, l’ultimo salto è quello che l’estrusore dovrebbe eseguire per completare l’ultimo strato della calotta sferica. Infatti, come noto, la stampa 3D FDM/FFF procede per strati successivi.

sfera_geom2

Facciamo qualche calcolo.

Supponiamo che il raggio della sfera sia di 40mm e che il dZ=0.25mm. Di conseguenza gli strati di stampa 3D saranno:

strati = r / dZ = 40 / 0.25 = 160

Sull’asse Z di stampa, che corrisponde al disegno a Y, l’altezza dell’ultimo strato sarà ovviamente:

y[strati-1] = r - dZ = 40 - 0.25 = 39.75

e volendo calcolare la posizione sulle ascisse il penultimo X sarà:

x[strati-1] = sqrt( r^2-y[strati-1]^2) = sqrt(1600-1580.0625)=sqrt(19.9375)= 4.4651

Ecco il problema di stampa della nostra sfera: quando verrà stampata la penultima corona circolare, questa sarà lontana dal centro di ben 4.4651mm. Ciò significa che l’ultimo strato dovrebbe coprire un raggio impossibile per il nostro ugello. Sì, perchè gli ugelli al massimo possono essere di 1mm o 1.2mm, non img_20151120_184820certamente da 5mm!

 

 

 

 

 

SOLUZIONE

Per risolvere questo problema esistono tre modi:

  • struttura di supporto
  • modificare il disegno, ispessendo la calotta
  • buon software CAM

Desidero tralasciare i primi due punti e vorrei considerare l’ultimo.

Molti CAM (Cura, Simplify 3D, ecc.) eseguono semplicemente quello che è il disegno originario, e mi sembra anche ovvio, ma non fanno altre considerazioni.

Nel nostro caso il software si dovrebbe accorgere cosa può essere eseguito e cosa è impossibile, oppure come risolvere un problema apparentemente impossibile.

Qui è il punto di forza di un buon CAM, in questi casi Makerbot Desktop è un’ottima soluzione: si accorge della difficoltà e modifica il disegno originale quanto basta, cioè ispessendo quel tanto che basta la calotta. Si tratta di piccole differenze, ma sono quelle che fanno la qualità.

CONCLUSIONE

Makerbot costa qualcosa in più rispetto ad altre macchine, ma quanto è utile avere un sistema “zoppo”?

Esiste una alternativa all’uso di  Makerbot Desktop, am di questa ne parlerò in un prossimo articolo.

 

e buona sfera a tutti!

 

 

 

 

 

Salva

Salva