Quantcast
Viewing all 84 articles
Browse latest View live

Matrice di led con HT1632C (1)

Qualche tempo fa ho acquistato da SureElectronics un display a matrice di led.

Image may be NSFW.
Clik here to view.

Il prodotto è costituito da 4 matrici di 8×8 led, controllate dall’integrato HT1632C di Holtek:

Image may be NSFW.
Clik here to view.

In questo primo tutorial vedremo come comunicare con il chip di controllo…

PROTOCOLLO DI COMUNICAZIONE

L’integrato HT1632C adotta un protocollo simile a quello SPI; è possibile controllarlo attraverso 3 PIN:

  • CS (chip select)
  • DATA
  • WR (write)

Il pin CS va portato a livello logico o per abilitare la comunicazione; il display di SureElectronics consente una configurazione a cascata potendo collegare fino a 4 moduli uno dopo l’altro. Sul retro del display è disponibile un dip switch per configurare il particolare indrizzo del singolo display:

Image may be NSFW.
Clik here to view.

Il connettore presenta, tra gli altri collegamenti, 4 PIN di chip select attraverso i quali è possibile attivare uno dei 4 display collegati in cascata:

Image may be NSFW.
Clik here to view.

Attraverso il pin DATA avviene la comunicazione seriale sia in input che in output. Internamente al chip HT1632C è già presente una resistenza di pull-up.

Il pin WR controlla la scrittura verso l’integrato HT1632C: il livello logico del pin DATA viene letto sul fronte di salita (da livello logico 0 a livello logico 1) di tale pin.

Se è necessario ricevere dei dati dall’integrato, è inoltre disponibile il pin RD che – in maniera simile al pin WR – indica all’integrato quando rendere disponibile il dato sul pin DATA.

INDIRIZZAMENTO

L’integrato HT1632C ha una memoria RAM organizzata in 64×4 bits; ad ogni cella di memoria corrisponde una uscita. Un valore logico alto memorizzato nella cella, corrisponde ad un valore logico alto dell’uscita (e quindi all’accensione del led).

Attraverso dei comandi di READ e WRITE è possibile controllare il contenuto della RAM e quindi lo stato delle uscite. Entrambi i comandi supportano sia l’accesso ad un singolo banco di memoria, sia la possibilità di controllare, con una singola operazione, tutte le celle.

CONCLUSIONI

In questo primo tutorial abbiamo dato uno sguardo al display e al chip di controllo; nel prossimo vedremo come comandarlo da Arduino… stay tuned!


enc28J60 e Arduino (8)

Dopo la pubblicazione del mio articolo su come controllare un led via web, mi è stato chiesto un esempio con più led. Oggi vi mostrerò come comandare due led e come migliorare l’aspetto della pagina html grazie all’aggiunta di immagini…

LE IMMAGINI

Per prima cosa, dobbiamo capire cosa succede quando, all’interno della pagina HTML, sono presenti riferimenti a risorse esterne (immagini, javascript…):

  • il browser dell’utente richiede la pagina HTML;
  • il browser interpreta la pagina e identifica le risorse esterne;
  • per ogni risorsa, il browser la richiede al server web.

Quando il server web risponde alla richiesta, comunica (all’interno dell’header della risposta) al browser il tipo di file che sta inviando utilizzando lo standard MIME. Ecco un esempio (catturato con Fiddler) relativo ad una immagine PNG:

Image may be NSFW.
Clik here to view.

Lo sketch Arduino dovrà quindi:

  • leggere la richiesta del browser (contenuta nel buffer Ethernet::buffer);
  • identificare la risorsa che il browser sta richiedendo (pagina HTML, immagini…);
  • costruire un header contenente il corretto Content-Type;
  • inviare header e risorsa al browser.

RISORSE BINARIE

Le immagini sono files binari: nel nostro semplice esempio dovremo inserirle direttamente nello sketch di Arduino, convertendole in array di bytes. Esiste una comoda utility che ci aiuta in questa conversione: bin2h.

Il risultato della conversione è un file di testo contenente la risorsa codificata:

Image may be NSFW.
Clik here to view.

Per occupare meno spazio nella RAM del microcontrollore, salviamo l’immagine nella memoria programma con la direttiva PROGMEM:

Image may be NSFW.
Clik here to view.

A causa della limitata memoria del microcontrollore ATMega328 e del funzionamento della libreria EtherCard, non è possibile utilizzare risorse più grandi di circa 500 bytes!

Nella prossima pagina, vedremo lo sketch Arduino…

Matrice di led con HT1632C (2)

Riprendiamo oggi il nostro display a matrice di led con un primo esempio di utilizzo con Arduino…

COLLEGAMENTI

Come detto, per pilotare il display sono sufficienti 3 pin. Possiamo utilizzare qualsiasi pin digitale di Arduino: per comodità nello sketch sono definiti degli alias:

#define DISPLAY_CS    3
#define DISPLAY_WR    4
#define DISPLAY_DATA  5

Il display viene alimentato a 5V, possiamo prelevare alimentazione e massa sempre da Arduino:

Image may be NSFW.
Clik here to view.

Il connettore presenta 4 pin di CS: va collegato ad Arduino quello relativo all’id (vedi il dip switch) del modulo

COMUNICAZIONE

Per comunicare con il display, il codice Arduino dovrà per prima cosa mettere a livello logico 0 il pin CS.

Quindi, per ogni bit,

  • mettere a livello logico basso il pin RW
  • inviare il bit sul pin DATA
  • mettere a livello logico alto il pin RW

infatti il valore presente sul pin DATA viene letto sul fronte di salita del pin RW.

Leggendo il datasheet del chip HT1632C, si nota come comandi e indirizzi vadano inviati dal bit più significativo (MSB), mentre i dati da quello meno significativo (LSB):

Image may be NSFW.
Clik here to view.

COMANDI

L’integrato HC1632C definisce 3 comandi, identificati dai primi 3 bit inviati:

  • READ, 110
  • WRITE, 101
  • COMMAND, 100

I primi due comandi sono seguiti dall’indirizzo di memoria e dai dati; il terzo invece è seguito da un codice comando che specifica il particolare comando da eseguire.

INIZIALIZZAZIONE

All’accensione, il display è disabilitato:

Image may be NSFW.
Clik here to view.

Per poterlo utilizzare, dovremo inviare i comandi di SYS EN e LED On (come vedremo questi due comandi saranno inviati all’interno del metodo setup() del nostro sketch).
Nella prossima pagina vedremo un primo sketch di esempio…

Matrice di led con HT1632C (3)

In questo post, vedremo come visualizzare dei caratteri sul nostro display…

CODIFICA

Guardando il datasheet del display, si vede come i led siano mappati sulle celle della memoria RAM partendo dall’angolo in alto a sinistra:

Image may be NSFW.
Clik here to view.

Su un foglio di carta a quadretti prepariamo la scritta da visualizzare ricordando

che l’altezza dei caratteri è di 8 quadretti e che possiamo arrivare al massimo a 32 colonne:

Image may be NSFW.
Clik here to view.

Ad ogni quadretto nero corrisponde un bit a 1; ad ogni quadretto bianco corrisponde un bit a 0.

Scriviamo ora i bits, leggendoli come indicato dalle frecce e utilizzando come prefisso B per indicare ad Arduino che si tratta di valori binari:Image may be NSFW.
Clik here to view.

PROGMEM

Arduino ha una memoria RAM molto limitata (2KB): per memorizzare grandi quantità di dati possiamo sfruttare la memoria programma (32KB in Arduino Uno) utilizzando la direttiva PROGMEM:

Image may be NSFW.
Clik here to view.

Per leggere i dati memorizzati con tale tecnica, è necessario utilizzare dei metodi dedicati (definiti in pgmspace.h); in particolare noi utilizzeremo pgm_read_byte():

Image may be NSFW.
Clik here to view.

SKETCH

Lo sketch completo è disponibile nel repository GitHub.

Il suo funzionamento è molto semplice:

  • memorizza in PROGMEM la scritta da visualizzare (text[])
  • inizializza il display
  • invia la scritta (24 colonne) leggendo byte per byte l’array text[]
  • invia infine 8 colonne (64bit) di zeri per completare le 32 colonne del display

Ecco lo sketch in azione:

Image may be NSFW.
Clik here to view.

Image may be NSFW.
Clik here to view.

Matrice di led con HT1632C (4)

Nel precedente tutorial, abbiamo visto come visualizzare sul display una scritta statica, codificata e memorizzata nella memoria programma di Arduino. In questo tutorial vedremo come costruire scritte dinamiche…

CODIFICA FONT

Per comporre a runtime una scritta, dobbiamo codificare i singoli caratteri, memorizzandoli nella memoria programma.

Possiamo procedere manualmente (“disegnando” ogni carattere su carta); per velocizzare l’attività ho sviluppato un programma per Windows, LetterToBinary:

Image may be NSFW.
Clik here to view.

Il codice sorgente (C#) del programma è disponibile in un repository GitHub; per scaricare la versione compilata fai click qui.

Usando LetterToBinary è possibile ottenere subito la codifica di un carattere e copiarla nella clipboard di Windows; ho utilizzato questo applicativo per codificare tutto il set di caratteri (font) Ai Pointe, di Ritchie Ned Hansel:

Image may be NSFW.
Clik here to view.

Il font è quindi memorizzato in un array all’interno della memoria programma:

Image may be NSFW.
Clik here to view.

DESCRITTORE FONT

Perché Arduino possa comporre una scritta utilizzando il font appena codificato, è necessario fornire due informazioni:

  • la lunghezza (= numero di byte) del singolo carattere
  • l’offset di inizio del carattere all’interno dell’array

Ho separato il font dallo sketch principale memorizzandolo in un file .h, all’interno del quale è definita una struttura FONT_INFO:

typedef struct {  
  unsigned char length;  
  unsigned int offset;
} FONT_INFO;

e un array con elementi FONT_INFO, uno per ogni carattere:

FONT_INFO aipoint_info[] = {
  {2, 0},	// !
  {5, 2},	// "
  {5, 7},	// #
  {5, 12},	// $
  {5, 17},	// %
  ...

Attraverso questo array Arduino può sapere che – ad esempio – il carattere $ ha lunghezza 5 bytes e inizia dal byte 12 dell’array aipointe_font[].

Osservando la tabella dei codici ASCII, notiamo che siamo partiti a codificare dal carattere ! Tale carattere ha valore decimale 33 ed è memorizzato all’elemento 0 dell’array aipointe_info[]: questo significa che, per sapere la posizione occupata in tale array dai vari caratteri, dovremo sottrarre al loro valore decimale il numero 33.

Nella prossima pagina vedremo come scrivere uno sketch che utilizzi il font così codificato…

enc28J60 e Arduino (9)

Dopo la pubblicazione del precedente tutorial, alcuni utenti mi hanno scritto per chiedermi se fosse possibile aumentare la dimensione delle immagini che Arduino può gestire.

Gli sviluppatori della libreria EtherCard stanno rivedendo il meccanismo di gestione dei pacchetti, nel frattempo è possibile aggirare il problema inserendo nella pagina HTML riferimenti ad immagini ospitate su altri siti:

Image may be NSFW.
Clik here to view.

L’esempio di oggi deriva da una richiesta: poter comandare un relay via Internet, con una interfaccia pensata per smartphones.

Schema logico

Utilizziamo Arduino + Ethernet Shield e colleghiamo ad un PIN di Arduino un modulo relay acquistato su eBay:

Image may be NSFW.
Clik here to view.

Colleghiamo quindi l’Ethernet Shield al router ADSL di casa e configuriamo tale router in modo che esegua NAT delle connessioni in ingresso sulla porta 80 verso l’IP assegnato allo shield:

Image may be NSFW.
Clik here to view.

Possiamo quindi raggiungere il nostro Arduino via Internet conoscendo l’IP pubblico della nostra connessione o affidandoci a un servizio di DNS dinamico (magari aggiornato da Arduino, come ho spiegato qui).

Interfaccia

L’interfaccia è volutamente molto semplice: una scritta che indica lo stato attuale e un pulsante per attivare/disattivare il relay:

Image may be NSFW.
Clik here to view.

Per adattare la pagina web allo schermo dello smartphone, ho utilizzato il seguente tag META:

Image may be NSFW.
Clik here to view.

Le icone utilizzate provengono dal set Soft Scraps di Jojo Mendoza che ringrazio per averlo reso disponibile gratuitamente per utilizzi non commerciali

Trovate due pagine statiche di esempio nel repository Github.

Sketch

Lo sketch per Arduino riprende buona parte degli esempi precedenti, modificando solo la parte di invio della pagina HTML:

Image may be NSFW.
Clik here to view.

L’intero sketch è come al solito disponibile su Github.

Demo

Matrice di led con HT1632C (5)

Concludiamo questa serie di tutorial con uno sketch che riceve una stringa di caratteri via seriale e la visualizza sul display eseguendo lo scrolling.

Inizio l’articolo con un breve filmato che mostra lo sketch in azione; nelle prossime pagine vi spiegherò in dettaglio il suo funzionamento:

Trovate lo sketch completo nel repository Github.

enc28J60 e Arduino (10)

Il breve tutorial di oggi prende spunto da una richiesta di Antonio: poter cambiare la porta su cui è in ascolto il webserver.

La modifica è molto semplice, basta impostare la variabile hisport:

Image may be NSFW.
Clik here to view.

In questo caso, sarà possibile collegarsi al webserver specificando la porta 90:

Image may be NSFW.
Clik here to view.


enc28J60 e Arduino (11)

Il tutorial di oggi è un po’ particolare: spiega come rendere wireless il nostro ethernet shield.

Esistono diversi shield Wi-fi per Arduino: partendo da quello ufficiale, fino a shields basati su integrati Microchip, “cugini” dell’enc28j60 soggetto di questi tutorial.

A volte però può essere più comodo (e forse più economico!) collegare Arduino alla rete Wi-fi sfruttando lo shield ethernet che già abbiamo, abbinandolo ad un router wireless.

In particolare ho scoperto il nano router TL-WR702N di TP-LINK che, ad un costo di circa 20€ su eBay, ha tra le proprie funzionalità anche la modalità client, nella quale il router fa da “ponte” tra un dispositivo connesso alla sua porta ethernet e la rete Wi-fi.

Il router TL-WR702N inoltre ha dimensioni davvero ridotte e può essere alimentato tramite un connettore micro USB:

Image may be NSFW.
Clik here to view.
 Image may be NSFW.
Clik here to view.

Configurarlo in modalità client è molto semplice:

Per prima cosa diamo al nostro PC un indirizzo fisso, 192.168.0.10, e colleghiamoci al router con il cavo ethernet:

Image may be NSFW.
Clik here to view.

Apriamo il browser e digitiamo http://192.168.0.254, accedendo con utente e password admin.

Selezioniamo Client mode:

Image may be NSFW.
Clik here to view.

Clicchiamo su Survey per cercare la nostra rete Wi-fi, quindi inseriamo i parametri di sicurezza:

Image may be NSFW.
Clik here to view.

Attendiamo il restart del router:

Image may be NSFW.
Clik here to view.

Sarà ora possibile collegare Arduino e raggiungerlo tramite la rete Wi-fi!

Image may be NSFW.
Clik here to view.

enc28J60 e Arduino (12)

Oggi vedremo un modo un po’ particolare per inviare SMS da Arduino…

In commercio si trovano diversi shields che consentono di collegare Arduino alla rete GSM per inviare/ricevere SMS, sfruttare la connessione dati (GPRS o UMTS) o effettuare chiamate.

Un modo alternativo per inviare SMS da Arduino è sfruttare uno degli SMS Gateway presenti su Internet: questi servizi consentono, tramite form Web o chiamate API, di inoltrare SMS a dispositivi mobili. Tra i vari service providers, ho scelto Skebby.

Image may be NSFW.
Clik here to view.

I principali servizi che Skebby mette a disposizione sono:

  • classic, consegna garantita, sms lunghi, personalizzazione mittente
  • basic, consegna best effort, servizio economico
  • zerocent, gratuito, invio a terminali con installata l’app di Skebby

Vedremo come utilizzare Arduino per inviare SMS classic (a pagamento con mittente personalizzato) e SMS zerocent (gratuito ma richiede l’app installata).

Il funzionamento logico è il seguente:

Image may be NSFW.
Clik here to view.
Registrazione

Per poter utilizzare i servizi di Skebby, è necessario registrarsi:

Image may be NSFW.
Clik here to view.

Al momento della registrazione, ti verranno dati in omaggio 10 SMS.

Nella prossima pagina, lo sketch per Arduino…

enc28J60 e Arduino (13)

L’articolo di oggi vi mostrerà come ottenere via Internet l’ora esatta, utilizzando il servizio NTP (Network Time Protocol).

NTP

NTP è un protocollo client-server a livello applicativo; utilizza come protocollo di trasporto UDP sulla porta 123.

Interrogando un server NTP, si ottiene come risposta un valore (timestamp) di 64bit così suddiviso:

  • i primi 32bit indicano il numero di secondi trascorsi dal giorno 01/01/1900
  • i rimanenti 32bit sono la frazione del secondo attuale

Image may be NSFW.
Clik here to view.

Esistono diversi server NTP: negli Stati Uniti ad esempio il NIST (National Institute of Standards and Technology) mantiene una rete di server. Vivendo in Italia, ho scelto di utilizzare come time server per questo articolo quello offerto dall’INRiM (Istituto Nazionale di Ricerca Metereologica):

static byte ntpServer[] = {193,204,114,232};

Arduino

La libreria EtherCard mette a disposizione due metodi per interagire con un server NTP:

  • ntpRequest(ntpServer, srcPort), invia la richiesta al server specificato;
  • ntpProcessAnswer(&timeStamp, srcPort), riceve la risposta e ne estrae il timestamp (solo i primi 32bit).

Il parametro srcPort serve per identificare, tra i vari pacchetti che lo shield Ethernet può ricevere, quello che contiene la risposta del server: il suo valore è arbitrario ma deve essere uguale sia nella Request che nella ProcessAnswer.

Image may be NSFW.
Clik here to view.

Una volta ottenuto il valore di timestamp, è necessario convertirlo in data-ora. Il procedimento è il seguente:

  • si conta il numero di anni completi contenuti nel valore di timestamp;
  • si passa poi a verificare quanti mesi completi sono contenuti nel resto;
  • si prosegue con giorni, ore, minuti;
  • il resto finale indica il numero di secondi attuali.

Alcune piccole complicazioni:

Gli anni possono essere bisestili: per tali anni il numero di secondi da considerare non è 365*86400 ma 366*86500. Per calcolare se un anno è bisestile si può utilizzare la formula:

boolean isLeapYear(unsigned int year) {
 
  return (year % 4 == 0 && (year % 100 != 0 || year % 400 == 0));
}

Il numero di giorni in un mese è variabile: il valore è memorizzato in un apposito array:

static int days_in_month[] = {31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31};

Se l’anno è bisestile, Febbraio ha 29 giorni:

if(isLeapYear(year) && month == 1) seconds = SECONDS_IN_DAY * 29;

Il timestamp infine è riferito a GMT, se siamo in un differente fuso orario, dobbiamo correggerne il valore:

#define TIME_ZONE               +1
[...]
printDate(timeStamp + 3600 * TIME_ZONE);

Lo sketch completo è disponibile su Github… ecco uno screenshot del suo funzionamento:

Image may be NSFW.
Clik here to view.

Da Arduino a C# via socket

Quando Arduino deve comunicare via rete, spesso si sceglie il protocollo HTTP perché consente di utilizzare come client un semplice browser web (IE, Firefox…). A volte però è necessario che Arduino invii dei dati ad altre applicazioni: in questo caso possiamo sfruttare una comunicazione socket.

Questo tutorial è suddiviso in due parti:

  • nella prima, vedremo come sviluppare una applicazione socket in C#
  • nella seconda, vedremo come scrivere uno sketch per Arduino

Socket server in C#

Il framework .Net mette consente di operare sui socket in due modalità: sincronaasincrona.

I metodi sincroni sono bloccanti: il thread nel quale sono eseguiti si ferma fino al termine della chiamata. Se ad esempio chiamiamo il metodo Receive() per leggere dati dal socket, tale metodo bloccherà l’esecuzione finché i dati saranno disponibili o finché scatterà un timeout.

I metodi asincroni invece chiedono al framework di gestire l’operazione, indicandogli quale oggetto callback chiamare quanto tale operazione è terminata. Normalmente tali metodi iniziano con Begin (ad esempio BeginReceive()). Programmare utilizzando metodi asicroni è però più complesso: per questo tutorial utilizzerò quindi i metodi sincroni, creando però un diverso thread per non bloccare la GUI del mio applicativo.

Il nostro SocketServer sarà quindi formato da due elementi:

  • la GUI (Form1.cs) che consentirà all’utente di interagire con il programma

Image may be NSFW.
Clik here to view.

  • la classe SocketHandler (Program.cs) che si occuperà di dialogare via socket con Arduino

Image may be NSFW.
Clik here to view.

Il programma riceverà da Arduino il valore della temperatura rilevata da una sonda e lo visualizzerà sia in forma testuale che in forma grafica (usando una progress bar); è inoltre presente una text area per il log di debug.

La classe Socket

Il framework .Net mette a disposizione l’oggetto Socket per gestire le connessioni in ingresso.

Per prima cosa, includiamo il package System.Net.Sockets, quindi – se l’utente preme il pulsante Start listening – configuriamo l’oggetto Socket perché sia in ascolto sulla porta TCP specificata:

IPAddress listeningIp = IPAddress.Any;
IPEndPoint listeningEndPoint = new IPEndPoint(listeningIp, listeningPort);
listeningSocket = new Socket(listeningIp.AddressFamily, SocketType.Stream, 
  ProtocolType.Tcp);
listeningSocket.Bind(listeningEndPoint);
listeningSocket.Listen(10);

Creiamo una nuova istanza dell’oggetto IPEndPoint specificando l’indirizzo IP su cui essere in ascolto (nel nostro esempio Any, ovvero ogni interfaccia di rete presente) e la porta. Quindi creiamo una istanza dell’oggetto Socket con protocollo TCP. Infine leghiamo (= bind) tale istanza all’endpoint e mettiamola in ascolto, in attesa di nuove connessioni (10 indica il numero massimo di connessioni in coda).

SocketHandler socketHandler = new SocketHandler(listeningSocket, this);
serverThread = new Thread(new ThreadStart(socketHandler.startListening));
serverThread.Start();

Per evitare di bloccare il resto del programma, creiamo un nuovo Thread in cui eseguiamo la classe SocketHandler che gestirà la connessione in ingresso:

try
 {
  // Wait for incoming connection
  handlerSocket = listeningSocket.Accept();
  handlerSocket.ReceiveTimeout = 5000;
  IPAddress clientAddress = ((IPEndPoint)handlerSocket.RemoteEndPoint).Address;

Il metodo Accept() è bloccante: il thread resterà in attesa di una nuova connessione… all’arrivo di questa viene impostato un timeout in lettura di 5 secondi e viene letto l’indirizzo IP del client che si è appena connesso.

while (true)
{
  // Save received bytes
  byte[] buffer = new byte[1024];
  int bytesRec = handlerSocket.Receive(buffer);
  message += Encoding.ASCII.GetString(buffer, 0, bytesRec);
 
  // Message completed? Parse it...
  if (message.Contains("\r"))
  {
    myForm.setTemp(message.Replace('.', ','));
    myForm.log(" message received: " + message);
    break;
  }
}

Leggiamo quindi i dati in ingresso con il metodo Receive (anche questo bloccante: se non arrivano dati entro 5 secondi viene sollevata una timeout exception) fino al carattere di “a capo” (\r), ricevuto il quale possiamo visualizzare la temperatura ricevuta.

Tips

Il sorgente completo del programma è disponibile su Github; prima di passare allo sketch Arduino ecco un paio di suggerimenti:

- utilizzando diversi thread, è necessario prestare attenzione a come si aggiornano gli elementi della GUI: tali elementi infatti possono essere aggiornati solo dal thread che li ha creati. Da thread diversi, dobbiamo quindi chiamare metodi delegati del thread principale:

myForm.setTemp(message.Replace('.', ','));
[...]
public delegate void setTempCallback(string temperature);
public void setTemp(string temperature)
{
  if (InvokeRequired) this.Invoke(new setTempCallback(setTemp), 
    new object[] { temperature });
  else
  {                
    float floatTemp;

- chiamare il metodo Abort() di un thread bloccato in Accept() non è sufficiente per chiudere tale thread, è necessario prima invocare il metodo Close() dell’oggetto Socket:

listeningSocket.Close();
serverThread.Abort();
log("Listening stopped");

Matrice di led con HT1632C (6)

Alcuni utenti mi hanno scritto chiedendomi esempi “reali” di utilizzo del display… in questo articolo vi mostrerò uno sketch per realizzare un termometro.

Il sensore

Per ottenere la temperatura ambiente, ho scelto di utilizzare il sensore DS18B20 di Maxim Integrated.

Il collegamento con Arduino è molto semplice: il sensore ha 3 pin (VDD, GND e DQ); ho scelto di collegare DQ al pin 2:

Image may be NSFW.
Clik here to view.

Il sensore DS18B20 supporta due modalità di alimentazione:

  • tramite il pin VDD
  • parassita, tramite il pin DQ (in questo caso il pin VDD va collegato a massa)

In entrambi i casi, il pin DQ richiede una resistenza di pull-up da 4.7Kohm.

La liberia

Miles Burton ha sviluppato una comoda libreria per dialogare con il sensore di Maxim… il suo utilizzo è molto semplice:

- includiamo nello sketch le due librerie  OneWire e DallasTemperature:

#include <OneWire.h>
#include <DallasTemperature.h>

- inizializziamo la libreria indicando il pin a cui è collegato il sensore:

#define ONE_WIRE_BUS  2
OneWire oneWire(ONE_WIRE_BUS);
DallasTemperature sensors(&amp;oneWire);

- leggiamo il valore (float) della temperatura (avendo un solo sensore collegato, questo avrà indice 0):

sensors.requestTemperatures();
float float_temp = sensors.getTempCByIndex(0);

Image may be NSFW.
Clik here to view.

Il display

Per visualizzare ilvalore letto sul display, utilizziamo la funzione sprintf per creare il testo completo:

sprintf(display_string, "Temperature: %s", string_temp);

Unico piccolo problema è che sprintf non supporta i tipi di dati float; dobbiamo quindi convertire prima tale valore in formato stringa.

Demo

Lo sketch è disponibile su Github, eccolo in azione:

Matrice di led con HT1632C (7)

L’esempio di oggi arriva da una richiesta di Francesco: poter scegliere la scritta visualizzata sul display tramite la pressione di pulsanti.

PROGMEM

Per memorizzare del contenuto statico (= le diverse scritte da visualizzare) possiamo sfruttare la memoria programma di Arduino, utilizzando la direttiva PROGMEM:

PROGMEM char btn1_text[] = {"BTN-1"};
PROGMEM char btn2_text[] = {"BTN-2"};

Salvare i dati in tale memoria ci consente di risparmiare memoria RAM; dobbiamo però fare attenzione a come accediamo a tali variabili: per copiarne il contenuto in una variabile in RAM dobbiamo usare la funzione strcpy_P:

strcpy_P(display_string, btn1_text);

PULSANTI

Collegare uno o più pulsanti ad Arduino è molto semplice, ricordiamoci sempre di configurare i PIN a cui sono collegati come INPUT:

#define BTN1_PIN      10
#define BTN2_PIN      11
[...]
pinMode(BTN1_PIN, INPUT);
pinMode(BTN2_PIN, INPUT);

Ho scritto una function per leggere lo stato di un bottone, inserendo un piccolo ritardo per debounce:

boolean check_button(int button) {
 
  if(digitalRead(button) == HIGH) return false;
  delay(50);
  if(digitalRead(button) == HIGH) return false;
  delay(200);
  return true;
}

Il tutto realizzato su una piccola breadboard:

Image may be NSFW.
Clik here to view.

SKETCH

Lo sketch è disponibile su Github, ecco un video che ne mostra il funzionamento:

enc28J60 e Arduino (14)

In questo tutorial vedremo come realizzare un piccolo sito web che riceve dati da Arduino (tramite il nostro ethernet shield), li memorizza e li visualizza su un grafico.

Schema logico

Il nostro sito web sarà formato da due pagine:

  • la prima, saveTemp.php, riceverà i dati da Arduino e li memorizzerà in un file di testo;
  • la seconda, displayTemp.php, leggerà il file di testo e visualizzerà i dati memorizzati.

Image may be NSFW.
Clik here to view.
Nell’esempio, leggerò con Arduino la temperatura dell’ambiente tramite il sensore DS18B20 di cui vi ho già parlato in questo articolo.

Per realizzare le pagine, ho scelto di utilizzare il linguaggio PHP, molto diffuso in ambito web.

Per semplicità, i dati saranno salvati in un file CSV (comma-separated values); in applicazioni reali conviene invece utilizzare un database, ad esempio MySQL

Invio dati

Per inviare i dati al server Web, ho scelto di utilizzare il metodo GET del protocollo HTTP. Tale metodo invia i parametri in chiaro all’interno della URL, con la forma nome=valore e separandoli con il simbolo &:

Image may be NSFW.
Clik here to view.

Per evitare che altri possano inviare dati, oltre al parametro temp, è necessario inviare alla pagina anche una password tramite il parametro pwd.

Lo sketch Arduino legge la temperatura dal sensore, la converte in formato stringa e la “stampa” in un oggetto Stash:

sensors.requestTemperatures();
float float_temp = sensors.getTempCByIndex(0);
 
char string_temp[7];
dtostrf(float_temp, 4, 2, string_temp);
 
Stash stash;
byte sd = stash.create();
stash.print(string_temp);
stash.save();

Infine prepara la richiesta in un altro oggetto Stash e la invia con il metodo tcpSend():

Stash::prepare(PSTR("GET /demo/saveTemp.php?temp=$H&amp;pwd=$F HTTP/1.0" "\r\n"
    "Host: $F" "\r\n" "\r\n"),
    sd, password, website);
session_id = ether.tcpSend();

Grazie all’identificativo di sessione (session_id) è possibile ottenere in seguito la risposta ottenuta dal server e verificare se contiene un messaggio di errore (“KO”):

const char* reply = ether.tcpReply(session_id);
[...]
if(strstr(reply, "KO - ") != 0) Serial.println(strstr(reply, "KO - "));

In PHP è possibile accedere ai dati tramite l’array associativo $_GET:

$temp = $_GET["temp"];
$pwd = $_GET["pwd"];

Verificata la password, il valore di temperatura ricevuto viene salvato nel file insieme ad un timestamp:

define("LOG_FILE", "./temperatures.csv");
[...]
$file_handler = fopen(LOG_FILE, "a+");
fwrite($file_handler, time() . "," . $temp . "\n");

Nella prossima pagina vedremo come visualizzare i dati in un grafico…


Macchina a stati finiti e Arduino

Dopo la pubblicazione dei miei sketch, ricevo spesso domande sul perché al loro interno vada a definire degli stati e più in generale su cosa sia una macchina a stati finiti. In questo tutorial, spiegherò come utilizzare tale modello per realizzare un semplice timer.

SimpleTimer

Utilizzeremo Arduino per realizzare un timer giornaliero, con un solo orario di accensione e spegnimento. Collegheremo Arduino ad un RTC (real-time clock) per avere l’ora corrente e ad un relay per controllare una lampadina.

Ho scelto di utilizzare due breakout board, una per l’integrato DS1307 (RTC) e una per il relay, così collegate ad Arduino:

Image may be NSFW.
Clik here to view.

L’integrato DS1307 ha una interfaccia i2c, utilizziamo quindi i PIN A4 (SDA) e A5 (SCL), mentre il modulo relay richiede un solo PIN digitale (nell’esempio il PIN 2).

RTC e Arduino

Per leggere l’orario dal modulo RTC, ho scelto la libreria RTCLib fornita da Adafruit, già usata in un precedente post.

Il suo utilizzo è semplice: per prima cosa dobbiamo includere nello sketch due files:

#include <Wire.h>
#include "RTClib.h"

Quindi definiamo un nuovo oggetto RTC_DS1307:

RTC_DS1307 RTC;

All’interno del setup(), inizializziamo la libreria Wire (i2c) e l’oggetto RTC:

Wire.begin();
RTC.begin();

Per leggere l’orario corrente, è quindi sufficiente chiamare il metodo now(), che restituisce un oggetto DateTime. Questo oggetto ha poi metodi per recuperare le varie parti (giorno, ora, minuto…) di data e ora:

DateTime now = RTC.now();
int hour = now.hour();
[...]

MSF

Una macchina a stati finiti è un modello che descrive il comportamento di un sistema. Il sistema può avere un numero finito di stati e in ogni istante può essere in un solo di essi, lo stato corrente. Il sistema può passare da uno stato all’altro in base ad eventi e/o condizioni: tale passaggio si chiama transizione.

Nel nostro esempio, il sistema potrà avere solo due stati:

  • luce accesa (= relay attivo)
  • luce spenta (= relay disattivo)

Il passaggio da uno stato all’altro dipende dall’orario corrente e dai due orari impostati di accensione e spegnimento. Una MSF si può visivamente definire tramite il suo diagramma degli stati:

Image may be NSFW.
Clik here to view.

All’interno dello sketch, definiamo due costanti che indicano i due diversi stati possibili:

#define STATE_OFF  0
#define STATE_ON   1

e una variabile che memorizzerà lo stato corrente:

int fsm_state;

Nel setup() è importante definire lo stato iniziale:

fsm_state = STATE_OFF;

All’interno del loop(), utilizziamo lo statement Switch per identificare lo stato attuale e verificare se ci sono le condizioni per una transizione di stato:

switch(fsm_state) {
  case STATE_OFF:
    if(now > START_TIME && now < END_TIME) {
        [...]
        fsm_state = STATE_ON;
      }
      break;
    case STATE_ON:
      if(now > END_TIME) {
      [...]
      fsm_state = STATE_OFF;
    }
    break;
}

Funzionamento

Lo sketch completo è disponibile nel mio repository su Github, ecco un paio di foto del progetto funzionante:

Image may be NSFW.
Clik here to view.

Image may be NSFW.
Clik here to view.

Allegro A4988 e Arduino (1)

Image may be NSFW.
Clik here to view.
In alcuni progetti, per comandare dei motori passo-passo ho utilizzato un driver basato sul chip Allegro A4988. Questo tutorial, diviso in tre parti, illustrerà il funzionamento di tale chip attraverso esempi pratici con Arduino.

Motori passo-passo

Un motore passo-passo (spesso chiamato stepper), è un motore elettrico sincrono in corrente continua, la cui rotazione è divisa in un elevato numero di passi. Inviando opportuni impulsi al motore, è possibile far eseguire al motore l’avanzamento di un passo.

Image may be NSFW.
Clik here to view.

Per una trattazione completa della teoria di funzionamento dei motori passo-passo, su Internet sono disponibili diversi articoli: vi consiglio la lettura di quello di VincenzoV e di quello di Mauro Alfieri.

I motori passo-passo si suddividono in:

  • unipolari
  • bipolari

Il chip Allegro A4988 è pensato per controllare motori bipolari.

Caratteristiche di un motore

Nella scelta di un motore passo-passo, vanno considerate alcune caratteristiche principali.

Image may be NSFW.
Clik here to view.

Per prima cosa la dimensione del motore: la National Electrical Manufacturers Association (NEMA) ha definito uno standard che prevede di etichettare i motori “NEMAxx“, con xx un numero che indica la dimensione (ad esempio un motore NEMA17 ha dimensione 1.7 x 1.7 pollici).

Secondo parametro importante è la coppia, che misura la “forza” che il motore può esprimere. Sebbene il S.I. (Sistema Internazionale) preveda come unità di misura per la coppia il N·m (Newton per metro), i produttori spesso ne utilizzano altre (Kg·m, Kg·cm, oz·inch…); su Internet sono disponibili dei comodi convertitori online.

Come parametri elettrici, spesso vengono riportati la massima corrente per fase (A) e la tensione nominale (V). La tensione nominale non è la massima tensione di alimentazione, ma è la tensione che impone la massima corrente per fase. Come vedremo, è quindi possibile alimentare il motore con tensioni più elevate, a patto di limitare la corrente in modo che non superi il valore massimo.

Nella prossima pagina vedremo come controllare questi motori con l’integrato A4988…

Allegro A4988 e Arduino (2)

Dopo aver capito il funzionamento di un motore passo-passo e aver introdotto il driver Pololu basato sul chip Allegro A4988, è ora arrivato il momento di muovere il motore con Arduino!

Il motore

Per testare gli sketch, ho scelto di utilizzare un motore della mia stampante 3d, siglato 42BYGH4807 (qui il datasheet):

Image may be NSFW.
Clik here to view.

Driver

Ho montato il driver Pololu su una breadboard; ho quindi collegato motore e alimentazione secondo lo schema riportato nella prima parte di questo tutorial:

Image may be NSFW.
Clik here to view.

Arduino

Il driver è quindi collegato ad Arduino, al quale ho aggiunto un LCD Keypad shield:

Image may be NSFW.
Clik here to view.

Nella pagina seguente vedremo il funzionamento dello sketch…

Allegro A4988 e Arduino (3)

In questa ultima parte del tutorial relativo al driver A4988, vedremo come realizzare un controller per regolare velocità e direzione di rotazione di un motore stepper.

Circuito

Utilizzeremo lo stesso circuito del post precedente:

  • un Arduino Uno;
  • un LCD Keypad shield;
  • un driver Pololu A4988 montato su breadboard;
  • un motore stepper NEMA17.

Image may be NSFW.
Clik here to view.

GUI

Il nostro controller darà la possibilità di regolare la velocità (da 0 a 70 RPM, giri/minuto) e la direzione di rotazione.

Sul display LCD verranno visualizzati velocità e direzione corrente e una progress bar:

Image may be NSFW.
Clik here to view.

La regolazione avviene tramite i 5 pulsanti disponibili:

  • UPDOWN regolano la velocità;
  • LEFTRIGHT regolano la direzione;
  • SELECT attiva lo stop di emergenza (velocità = 0).

Rotazione continua

Per garantire una rotazione continua, lo sketch di Arduino dovrà inviare al driver Pololu i comandi di step ad una frequenza costante.

Vediamo un esempio: per una velocità di 60RPM e con un motore da 200 passi / giro, Arduino deve inviare al driver (60*200)/60 = 200 comandi / sec ovvero un comando ogni 5ms.

Per garantire un timing così preciso, utilizzo gli interrupt generati dal Timer1 di Arduino come spiegato in questo articolo.

Su Playground esiste una comoda libreria per configurare tale Timer:

#include 
[...]
Timer1.initialize(100);
Timer1.attachInterrupt(timerIsr);

Con queste istruzioni, si configura il Timer1 per generare un interrupt ogni 100 millisecondi (0.1ms) e per chiamare, ad ogni interrupt, la funzione timerIsr().

La distanza temporale tra un comando di step e il successivo dipende dalla velocità attuale (nell’esempio sopra per 60RPM tale distanza è di 5ms). Visto che le velocità possibili sono soltanto 15 (da 0 a 70RPM con passo 5RPM), ho calcolato tale distanza (in ticks di 0.1ms) per le varie velocità e l’ho inserita in un array:

const int speed_ticks[] = {
-1, 600, 300, 200, 150, 120, 100, 86, 75, 67, 60, 55, 50, 46, 43};

All’interno della funzione timerIsr() incremento un contatore e – se ho raggiunto il numero di ticks per la velocità impostata – invio un comando di step al driver:

void timerIsr() {
 
  if(actual_speed == 0) return;
 
  tick_count++;
 
  if(tick_count == ticks) {  
 
    // make a step
    digitalWrite(PIN_STEP, HIGH);
    digitalWrite(PIN_STEP, LOW);
 
    tick_count = 0;
  }
}

Nella prossima pagina vedremo il resto dello sketch e un esempio di funzionamento…

Mediacenter con Raspberry Pi

La Raspberry Pi, grazie alla GPU Videocore 4 integrata nel chip Broadcom BCM2835, è perfetta come mediacenter; la GPU è infatti in grado di decodificare video in full HD. In questo tutorial vedremo l’installazione e l’utilizzo di Raspbmc.

Cosa mi serve

Il nostro piccolo mediacenter sarà composto da:

  • una Raspberry Pi Type B (con connettività ethernet);
  • un alimentatore micro USB da 2A;
  • una SD card da 4Gb.

Componenti opzionali sono:

  • un case per ospitare la Raspberry Pi (se ne trovano sia in plexiglass che in metallo su eBay e nei vari webstores);
  • una tastiera multimediale, magari wireless, con cui comandare il mediacenter stando comodamente seduti sul divano.

Ho acquistato tutti i gli elementi da RS Components, uno dei distributori ufficiali.

Image may be NSFW.
Clik here to view.
 Image may be NSFW.
Clik here to view.

Image may be NSFW.
Clik here to view.
 Image may be NSFW.
Clik here to view.

Raspbmc

Raspbmc è una distribuzione Linux pensata per Raspberry Pi che già include al suo interno l’ottimo media player XBMC.

L’installazione è molto semplice: per prima cosa scarichiamo dal sito ufficiale il setup (disponibile per Windows, Linux e MacOSX):

Image may be NSFW.
Clik here to view.

Quindi inseriamo la SD nel lettore del PC ed eseguiamo il setup. Selezioniamo il volume che corrisponde alla SD, accettiamo la licenza e premiamo Install:

Image may be NSFW.
Clik here to view.

Il programma di setup eseguirà il download da Internet del sistema base e lo installerà sulla SD. Attendiamo il messaggio di conferma:

Image may be NSFW.
Clik here to view.

Primo collegamento

Inseriamo ora la SD nello slot della Raspberry Pi, quindi colleghiamo il cavo ethernet (è necessario il collegamento ad Internet per il primo setup), quello video (composito o HDMI), l’alimentazione e tastiera/mouse USB:

Image may be NSFW.
Clik here to view.
 Image may be NSFW.
Clik here to view.

Il sistema eseguirà il download da Internet delle versioni più recenti della root partition e del software XBMC; dopo qualche minuto e qualche riavvio, XMBC sarà pronta per l’utilizzo!

Image may be NSFW.
Clik here to view.
 Image may be NSFW.
Clik here to view.

Viewing all 84 articles
Browse latest View live