Privacy Policy

Le novità di Windows 10 Creator Update: guida all'uso

L'update da tanto atteso e annunciato da Microsoft è stato rilasciato ufficialmente in questi giorni, per altro installabile tramite Media Creation Tool anche alcuni giorni prima del rilascio effettivo. Questa nuova release del sistema porte numerose novità volte a migliorare l'esperienza d'uso dell'utente, introducendo funzioni nuove e implementazioni di sicurezza che aumentano ancora di più la protezione dell'utente....

Come aggiornare da Windows 7 / Windows 8 a Windows 10 CU: metodo valido ancora per poco!

Qualcuno penserà: che titolo strano! La facoltà di aggiornare a Windows 10 gratuitamente è finita con il 29 luglio: assolutamente vero! Ma vi è un metodo disponibile per chi utilizza tecnologie assistive, Infatti basterà recarsi nella seguente pagina....

La Versione 8 di Android chiamata OREO è stata rilasciata: vediamo alcune novità inerenti la sicurezza e con quali smartphone sarà compatibile...

In questi giorni si è vociferato in merito la nuova versione di Android, che sarà la 8.0, la quale si chiamerà OREO ed andrà a portare una ventata di novità in tema sicurezza, visto e considerato che la piattaforma Android è quella che ne soffre maggiormente rispetto ai concorrenti Apple e Microsoft.

Le principali risorse Utili della MS Community

Nella Microsoft Community ci sono veramente numerosi articoli e risorse molto utili per chi utilizza quotidianamente il proprio computer, partendo da Windows XP a Windows 10. Di seguito, un elenco delle risorse più seguite e ritenute utili dagli utenti italiani...

Che cos'è una Botnet? Esempi pratici e spiegazione

Il termine Botnet ultimamente è entrato di forza nelle nostre vite,a causa di eventi di grossa importanza avvenuti nelle ultime settimane. E' stata fatta una spiegazione approssimativa di cosa sia una Botnet, in questo articolo vorremmo spiegare nel dettaglio che cos'è una Botnet, com'è strutturata e portare alcuni esempi pratici recenti di un suo utilizzo.

Visualizzazione post con etichetta Arduino. Mostra tutti i post
Visualizzazione post con etichetta Arduino. Mostra tutti i post

martedì 11 ottobre 2016

Serial Class per Universal Windows Platform (Parte due).

Introduzione.
Nel precedente articolo che trovate a questo link, abbiamo discusso tutto ciò che riguarda l’utilizzo della Classe SerialComunication, inclusa nel namespace Windows.Devices. In questa seconda e ultima parte, creeremo un progetto di prova con Visual Micro, un Plug-in installabile per poter programmare le schede della famiglia Arduino direttamente da Visual Studio. Alla fine del primo articolo abbiamo creato l’interfaccia grafica e creato il codice per la gestione della comunicazione seriale, con il seguente risultato finale.




Progetto di prova.
Avviamo Visual Studio 2015, dal menù file selezioniamo nuovo progetto, selezioniamo dai modelli installati la sezione C++  come mostrato in figura, e lo denominiamo Test comunicazione seriale.
Figura 1
Figura 2: il progetto di prova con Visual Micro.
Confermiamo con Ok, e saremo condotti nell’editor di codice come visibile in figura.
Figura 3
Figura 3: il file TestComunicazioneSeriale.ino con Visual Micro.
Siamo a questo punto pronti per scrivere un breve esempio di codice per le schede Arduino. Il vantaggio di utilizzare Visual Micro da un mio punto di vista, e la comodità di avere un intellisense che semplifica non poco la scrittura del codice, suggerendo man mano i metodi e/o proprietà al momento della digitazione di un determinato oggetto. Altra cosa non da poco, quella di eseguire il debug del nostro codice a differenza dell’ide Arduino classico, dove nessuna delle due cose e disponibile. Da evidenziare una cosa: il Debugger per Visual Micro non e incluso di default, ma va acquistato separatamente, avete tuttavia una trial dove e possibile provarlo prima dell’acquisto se lo si ritiene opportuno. Detto questo, scriviamo ora il codice che svolge le seguenti operazioni:
  1. Spegnimento Led con comando denominato 1.
  2. Accensione Led con comando denominato 2.
  3. Pulse 1 secondo Led con comando denominato 3.
  4. Pulse 2 secondi Led con comando denominato 4.
E veramente molto semplice quello che faremo, e una scelta voluta, semplicemente per far capire come funziona la comunicazione seriale tra Arduino e Raspberry pi2, ovvio si può fare tanto ma tanto di più,  ma lo scopo dell’articolo e quello di spiegare il funzionamento senza entrare in cose o argomenti particolari. Scriviamo ora il codice C++ seguente e ne commenteremo poi tutte le fasi.
/*
  Name:        TestComunicazioneSeriale.ino
  Created:    07/08/2016 14:43:27
  Author:    Carmelo La Monica
*/

char incomingByte = '0';   // for incoming serial data
int ledPin = 13;
// the setup function runs once when you press reset or power the board
void setup()
{
    Serial.begin(9600);     // opens serial port, sets data rate to 9600 bps
    pinMode(ledPin, OUTPUT);
}
// the loop function runs over and over again until power down or reset
void loop()
{
    // send data only when you receive data:
    if (Serial.available() > 0)
    {
         // read the incoming byte:
        incomingByte = Serial.read();
    }
    if (incomingByte == '1')
    {
        Serial.println("LedOff");
        digitalWrite(ledPin, LOW);    // sets the LED off    
        incomingByte = '0';
    }
    if (incomingByte == '2')
    {
        Serial.println("LedOn");
        digitalWrite(ledPin, HIGH);   // sets the LED on
        incomingByte = '0';
    }
    if (incomingByte == '3')
    {
        Serial.println("LedOn");
        digitalWrite(ledPin, HIGH);   // sets the LED on
        delay(1000);                  // waits for a second           
        Serial.println("LedOff");
        digitalWrite(ledPin, LOW);    // sets the LED off
        delay(1000);
    }
    if (incomingByte == '4')
    {
        digitalWrite(ledPin, HIGH);   // sets the LED on
        Serial.println("LedOn");
        delay(2000);                  // waits for a second                  
        digitalWrite(ledPin, LOW);    // sets the LED off
        Serial.println("LedOff");
        delay(2000);
    }
}
Analiziamo il codice appena scritto. Definiamo due variabili:
char incomingByte = '0';   // for incoming serial data
int ledPin = 13;
La prima di tipo char, dove andremo a verificare i valori, che possono essere da 1 a 4 come scritto precedentemente. La seconda e la variabile int ledPin, ossia dove andremo a collegare il led, per la precisione sul pin 13 della scheda Arduino Uno.
void setup()
{
    Serial.begin(9600);     // opens serial port, sets data rate to 9600 bps
    pinMode(ledPin, OUTPUT);
}
Nel metodo setup(), che viene eseguito una sola volta, inizializziamo la comunicazione seriale con una baudrate di 9600 bit/s e impostiamo la variabile ledPin come un uscita (OUTPUT)con l’istruzione pinMode, così da dare un valore di tensione quando da codice la imposteremo ad 1 accendendo in questo modo il Led.
// the loop function runs over and over again until power down or reset
void loop()
{
    // send data only when you receive data:
     if (Serial.available() > 0)
     {
         // read the incoming byte:
         incomingByte = Serial.read();
     }
    if (incomingByte == '1')
     {
         Serial.println("LedOff");
         digitalWrite(ledPin, LOW);    // sets the LED off    
         incomingByte = '0';
     }
    if (incomingByte == '2')
     {
         Serial.println("LedOn");
         digitalWrite(ledPin, HIGH);   // sets the LED on
         incomingByte = '0';
     }
    if (incomingByte == '3')
     {
         Serial.println("LedOn");
         digitalWrite(ledPin, HIGH);   // sets the LED on
         delay(1000);                  // waits for a second           
        Serial.println("LedOff");
         digitalWrite(ledPin, LOW);    // sets the LED off
         delay(1000);
     }
    if (incomingByte == '4')
     {
         digitalWrite(ledPin, HIGH);   // sets the LED on
         Serial.println("LedOn");
         delay(2000);                  // waits for a second                  
        digitalWrite(ledPin, LOW);    // sets the LED off
         Serial.println("LedOff");
        delay(2000);
    }
}
Nel metodo loop() che viene eseguito in maniera continua, utilizziamo una serie di istruzioni if, andando a comparare il valore della variabile incomingByte. Come e possibile osservare, ci sono quattro costrutti if tutti con una condizione, 1,2,3 o 4. Tornando per un attimo al progetto creato nella prima parte, abbiamo assegnato ad ogni button dell’interfaccia un valore che sarà inviato alla porta seriale dopo il click si di essi, per precisone:
  1. Tasto “Spegni Led” scriverà valore ‘1’ sulla porta seriale.
  2. Tasto “Accendi Led” scriverà valore ’2’ sulla porta seriale.
  3. Tasto “Pulse 1000 ms” scriverà valore ‘3’ sulla porta seriale.
  4. Tasto “Pulse 2000 ms” scriverà valore ‘4’ sulla porta seriale.
Il valore inviato dall’interfaccia sulla Raspberry Pi2 e Windows 10 IoT, sarà letto nel metodo loop() del programma sulla scheda Arduino uno, inizierà il confronto dei costrutti if, se uno dei quattro soddisfa la condizione, sarà eseguito il codice al suo interno. Supponiamo che si faccia click sul pulsante “Pulse 1000 ms”, sarà inviato il valore ‘3’ sulla porta seriale, e sarà soddisfatta sul codice C++ Arduino la seguente condizione.
    if (incomingByte == '3')
     {
        Serial.println("LedOn");
        digitalWrite(ledPin, HIGH);   // sets the LED on
        delay(1000);                  // waits for a second           
        Serial.println("LedOff");
        digitalWrite(ledPin, LOW);    // sets the LED off
        delay(1000);
    }
A questo punto incomingByte avrà valore ‘3’ per cui avremo un lampeggio con campionatura di un secondo del led, questo grazie all’istruzione delay(1000), che sta a significare una pausa di un secondo. Tutto continuerà così fino a quando non daremo un altro comando dell’interfaccia Windows 10, se facessimo click sul pulsante “Spegni Led”, sarà eseguita la prima condizione if sul codice C++ Arduino, perché incomingByte avrà valore ‘1’, spegnendo così il Led se osserviamo il codice precedente.
Test del progetto.
Di seguito un video che dimostra tutto ciò che abbiamo letto e affrontato in questi due articoli. Un video vale a volte più di mille righe di testo e/o parole. Trovare il video a questo link.
Conclusioni.
In questa seconda parte, abbiamo completato e dimostrato con un esempio semplicissimo in che modo possono comunicare via seriale una scheda Raspberry Pi2 con installato Windows IoT core e una scheda Arduino Uno. Abbiamo visto la gestione del progetto con Visual Studio e un applicazione di tipo Universal nella prima parte, concludendo poi con la seconda parte creando un esempio con Visual Micro, e visto in maniera pratica mediante video il funzionamento finale del progetto. Ora tocca a voi e buon coding Smile.

lunedì 5 settembre 2016

Progetto #SeismoCloud della Sapienza di Roma: puoi partecipare anche tu!

E' doveroso un cenno al programma SEISMOCLOUD dell'Università della Sapienza di Roma, infatti questo progetto ha l'obiettivo seguente:

Il nostro obiettivo è di avvisare le persone residenti nelle zone coinvolte dal sisma entro pochi secondi dal verificarsi della scossa all'epicentro, quindi, in molti casi, prima che il sisma li raggiunga.
La Mappa dei sismometri attualmente attivi, raggiungibile qui

Per completezza riporto la spiegazione dettagliata del programma che potete trovare nel sito ufficiale:

SeismoCloud è una rete comunitaria per la rilevazione dei terremoti e per l'invio di Early Warning, ovvero di avvisi che precedono (di alcuni secondi) l'arrivo di una scossa sismica. La rete funziona grazie a sismometri a basso costo sia fissi, costruiti come dispositivi dedicati, sia mobili, cioè basati su app per smartphone grazie all'uso dei sensori presenti nei dispositivi cellulari. Ogni persona può contribuire alla rilevazione dei terremoti installando l'app o montando e installando a casa un sismometro fisso.
Tutti i sismometri sono registrati all'interno del cloud. Ogni volta che un sismometro rileva una vibrazione, che dipenda da un terremoto o no, la comunica via internet al server (cioè al computer centrale) di SeismoCloud.
Il server, ricevendo le informazioni dei sismometri dal territorio ed eseguendo un algoritmo dedicato, è in grado di determinare il verificarsi di un terremoto nei primi secondi dall'inizio della scossa all'epicentro. Infatti, se si verifica un terremoto, i sismometri della zona dell'epicentro rilevano una vibrazione contemporaneamente. Se il numero di sismometri presente è sufficiente, il server registra il terremoto, ed effettua la stima dell'intensità della scossa e della distanza entro la quale il terremoto può provocare danni. In base a questa stima viene quindi inviato l'early warning, cioè la notifica sugli smartphone degli utenti delle province potenzialmente interessate. 

I sismometri sono di due tipi, ovvero FISSO e MOBILE: quello fisso è costruibile tramite le istruzioni che potete trovare qui, divise per argomento e tipo:





 

La versione Mobile, com'è ovvio, è quella tramite l'app dedicata disponibile per Android e iOS, i link sono di seguito




martedì 23 febbraio 2016

Windows Remote Arduino parte uno.

Introduzione.

Con questo mini articolo e con la mia esperienza iniziale, vorrei porre una breve panoramica della libreria di Windows Remote Arduino, una delle tecnologie utilizzate nella Più grande sfida Arduino Maker del mondo.


Cosa e Windows Remote Arduino.

Windows Remote Arduino, è una libreria open - source, che permette a qualsiasi dispositivo Windows 10, sia esso un Windows Phone, Surf ace, PC, o anche Raspberry Pi 2 e altre schede con installato Windows 10, di controllare a distanza una scheda  Arduino in diverse modalità. La libreria consente agli sviluppatori di poter integrare i sensori Arduino nei progetti Windows, e gestire attività o applicativi di una certa complessità dove con il solo Arduino non sarebbe possibile realizzare a pieno. Trovate la libreria Windows Remote  Arduino sulla pagina GitHub dedicata, all’interno di un repository intitolato "remote-wiring”. Per coloro che si avvicinano per la prima volta al mondo Windows, Arduino o generalizzando all’Internet of Things, qui di seguito trovate un buon punto di partenza. Di seguito, vediamo in dettaglio cosa e quali funzionalità la libreria Windows remote Arduino, è in grado di controllare:
  • GPIO Pin analogici e digitali di I/O.
    • La funzione DigitalWrite().
    • La funzione DigitalRead().
    • Ingressi analogici (PWM) mediante funzione AnalogRead().
    • Uscite analogiche (PWM) mediante funzione AnalogWrite().
    • Impostazione dei pin, quindi dichiarandoli come input o output.
    • Ricezione di eventi quando i valori dei pin subiscono una variazione di stato logico.
  • Inviare e ricevere dati tra dispositivi mediante protocollo I2C.


Uno sguardo più da vicino.

Ora che abbiamo visto un po' di quello che Windows Remote Arduino può fare, prima di scrivere codice o iniziare a spiegarne qualcosa, esploriamo come funziona il tutto. In questa sezione vedremo il processo che sta alla base della progettazione della libreria, dando uno sguardo da vicino alla struttura e come detto, passando alla parte pratica dai prossimi articoli con esempi di codice. Vedremo sia la parte hardware sia la parte software. Per coloro che invece intendono proseguire il percorso di sviluppo sin da subito, le istruzioni di installazione complete ed esempi di codice possono essere trovati a questo link.


Le decisioni che stanno alla base della progettazione.

Discutiamo in merito alla progettazione delle API di Windows Remote Arduino. Per esempio, partendo dalle funzioni pinMode e digitalWrite, familiari agli sviluppatori Arduino che, anziché reinventarle, sono rimaste invariate allo scopo di lasciare ciò che è già familiare senza stravolgere la sintassi agevolando così la fase di sviluppo.
Le API sono state realizzate per rispecchiare il più possibile quelli che sono i concetti Arduino. Ci sono naturalmente dei cambiamenti, poiché il WinRT è fondamentalmente diverso dal Wiring base utilizzato negli sketch Arduino. Tuttavia, con un po' di riorganizzazione, è possibile utilizzare gran parte della logica e comandi di uno sketch Arduino in un applicativo Windows 10 UWP.
Dopo aver progettato le API, è necessario un protocollo per facilitare la comunicazione tra Windows 10 e una scheda della famiglia Arduino, il protocollo utilizzato e Firmata, a mio avviso è stata la scelta più sensata. Anche in questo caso, si tratta di un progetto open - source che è stato implementato in molti altri linguaggi, tra cui Arduino Wiring, incluso oltretutto di default nei progetti Arduino.


Architettura.

Per quanto ho letto e capito, Windows Remote Arduino, è suddiviso in tre strati. Il primo denominato Stream comunication, ossia la comunicazione fisica, lo strato iniziale, necessario per lo scambio di dati e  informazioni tra Windows e il dispositivo Arduino. Al di sopra del livello iniziale  di comunicazione, abbiamo il protocollo Firmata che abbiamo discusso precedentemente, che si occupa di decodificare i dati grezzi in arrivo e renderli messaggi comprensibili. Infine, l’ultimo strato denominato RemoteWiring, il quale astrae tutti i messaggi di protocollo è consente così il controllo remoto delle schede Arduino da Windows.


Concetti iniziali per lo sviluppo con la libreria.

Per tutti i casi di utilizzo, la classe RemoteDevice contenuta nello strato RemoteWiring, e il punto di partenza, il punto iniziale che lo sviluppatore deve utilizzare per l’interazione tra i due dispositivi. Per interagire, abbiamo a disposizione le seguenti implementazioni IStream che dobbiamo necessariamente utilizzare al momento che creiamo un oggetto RemoteDevice:  usbserial, BluetoothSerial, NetworkSerial o DfRobotBleSerial, contenuti nello strato Stream comunication menzionato precedentemente. Dopo aver invocato il metodo begin() sull'oggetto Stream, tutte le successive chiamate delle API vengono effettuate tramite l'istanza RemoteDevice creata.  Possiamo così impostare i modi o stati dei pin, leggere i valori di pin digitali e/o analogici, avviare la comunicazione I2C ad altri dispositivi che supportano questo protocollo, e pilotare anche servo esempio motori stepper o altro hardware semplicemente utilizzando questa singola classe.


Espandere le funzionalità di Windows Remote Arduino.

Per gli utenti più esperti, Windows Remote Arduino consente anche di personalizzare i comandi e funzionalità, questo mediante Firmata SysEx - ulteriori informazioni possono essere reperite a questo Link. Per esempio la gestione della comunicazione SPI, è possibile tramite comandi SysEx. I comandi SysEx consentono agli sviluppatori di scrivere codice complesso e/o personalizzato che può essere eseguito con Windows Remote Arduino.


L'aggiunta del supporto SPI.

Solitamente, vi sono due metodi di comunicazione  (I2C e SPI)  che microcontrollori tipicamente usano per comunicare con altri dispositivi. Questo è comunemente richiesto per molti sensori, e altro hardware che hanno una propria MCU. Ciascuno di questi due metodi hanno i loro pro e contro, ma entrambi sono ampiamente supportati con Arduino.
Adesso, la libreria Windows Remote Arduino dipende dal protocollo Firmata per funzionare. Uno degli svantaggi di usare Firmata è che non vi è alcun supporto SPI esistente – ora le operazioni SPI con Windows Remote Arduino sono possibili utilizzando i comandi avanzati SysEx come menzionato prima. Fortunatamente, l'architettura a tre strati consentirebbe allo strato Firmata da scambiare informazioni in maniera relativamente semplice con un'altra implementazione del protocollo. Da lì, la classe RemoteDevice potrebbe essere modificata per accettare il nuovo protocollo, o una nuova implementazione di RemoteDevice potrebbe essere scritta per utilizzare il nuovo livello di protocollo.


Conclusione.

In questo primo articolo, ho cercato sulle basi della mia iniziale esperienza con Windows Remote Arduino, di dare dei cenni iniziali, su cosa e, cosa possiamo fare, come funziona, quali sono i pro e contro che ogni cosa purtroppo ha. Sono fiducioso che pian piano diventerà un’ottima scelta per gestire da Windows 10 i sensori della famiglia Arduino, non che pilotare qualcosa di più complesso come servomotori, motori stepper e altro hardware che in questo momento richiede uno sviluppo più accurato. Nei prossimi articoli, inizieremo la parte pratica, partendo dalla creazione dei un progetto UWP, e installare la libreria Windows Remote Arduino mediante Nuget.


Ulteriori risorse.

Di seguito lascio ulteriori link per approfondire in dettaglio come funziona la libreria Windows Remote Arduino.


martedì 29 dicembre 2015

Gestire sensori analogici su Raspberry Pi2

Introduzione.

Riprendiamo il nostro percorso sullo sviluppo e prototipazione con la board RaspberryPi2. Nel precedente articolo che trovate a questo link, il nostro obbiettivo era quello di comandare l’accensione di un Led. In questi ultimi giorni tra l’altro, e uscita la nuova release di Windows 10 IoT, ossia la 10.0.10586.0, che ha portato con se diverse novità che vedremo negli articoli successivi a questo. Il nostro scopo ora, e quello come da titolo, di gestire un sensore di tipo analogico. A differenza di uno digitale, il sensore analogico detto in maniera molto sintetica, si prenda come esempio uno di temperatura, fornisce un valore di tensione costante nel tempo, secondo il valore di temperatura che è rilevato dal sensore stesso. Altro esempio, un potenziometro, ossia una resistenza di tipo variabile, che secondo come agiamo su di essa mediante la sua manopola, varierà il suo valore in Ohm e di conseguenza varia anche il valore della tensione in uscita. Fino alla versione 10.0.10240.0 alla quale faremo riferimento, non vi e la possibilità di collegare sensori analogici sui pin della Gpio poiché mancano ingressi e uscite PWM (acronimo di power with modulation), per cui dobbiamo ricorrere ai cosiddetti ADC Converter (Analog to digital converter), ossia un circuito elettronico in grado di convertire un segnale analogico in valore di tipo binario espresso in byte.

Hardware necessario.

Dopo questa breve introduzione, passiamo allo step successivo. Per la realizzazione del nostro circuito, abbiamo bisogno del seguente materiale hardware:
  • Raspberry Pi2 con installata la versione 10.0.10240.0 dotata di cavo di alimentazione.
  • Cavo Hdmi così da connettere la Raspberry Pi2 a un monitor.
  • Monitor dotato di ingresso HDMI.
  • Cavo ethernet.
  • Breadboard, ovvero la base necessaria per il montaggio componenti e cablaggio elettrico.
  • Jumper maschio-maschio e maschio-femmina.
  • Sensore di temperatura analogica TMP36.
  • ADC converter MCP3008.

Un breve accenno sul circuito integrato MCP3008.   

Come da datasheet che trovate a questo link, si tratta di un convertitore analogico/digitale alimentato ad una tensione Max di 5 v DC, risoluzione 10 bit. Di seguito le caratteristiche principali.

  • 10-bit resolution
  • ± 1 LSB Max DNL
  • ± 1 LSB Max INL
  • 4 (MCP3004) or 8 (MCP3008) input channels
  • Analog inputs programmable as single-ended or pseudo-differential pairs
  • On-chip sample and hold
  • SPI serial interface (modes 0,0 and 1,1)
  • Single supply operation: 2.7V - 5.5V
  • 200 ksps max. sampling rate at VDD = 5V
  • 75 ksps max. sampling rate at VDD = 2.7V
  • Low power CMOS technology
  • 5 nA typical standby current, 2 µA max.
  • 500 µA max. active current at 5V
  • Industrial temp range: -40°C to +85°C • Available in PDIP, SOIC and TSSOP packages
Possiamo osservare che il tipo di comunicazione con la raspberry avviene mediante protocollo SPI. Di seguito la piedinatura.

Figura 1: La piedinatura dell’MCP3008.

Partendo dal pin 1 al pin 8, abbiamo I canali da CH0 A CH7, dove andremo a collegare l’uscita del/I sensori analogici. Ogni canale come vedremo, va configurato seguendo le indicazioni del costruttore come da datasheet allegato. I pin 16-15 vanno collegati al positivo, I pin 14-9 allo zero volt (o Ground della raspberry Pi2). I pin 13-12-11-10 sui pin del bus SPI0 o SPI1 della scheda Raspberry.

Circuito elettrico/elettronico. 

Qui di seguito il circuito finale del nostro progetto, realizzato con Fritzing, un ottimo software per la realizzazione di schemi elettrici/elettronici.

Figura 2: Il circuito elettronico.

Per non confondersi nei collegamenti elettrici, vediamo di seguito come collegare la Gpio con l’intergrato MCP 3008. Osservando la figura 1, vediamo che tra I pin 1 e 16 abbiamo un segno di riconoscimento, ruotando di 90° il componente in senso antiorario, il pin 1 sarà quello in basso a sinistra, il pin 8 quello in basso a destra, il 9 in alto a destra e il 16 in alto a sinistra.
  • PIN 16 MCP3008 ----> 3,3V DC (CAVO ROSSO)
  • PIN 15 MCP3008 ----> 3,3V DC (CAVO ROSSO)
  • PIN 14 MCP3008 ----> GND (CAVO NERO)
  • PIN 13 MCP3008 ----> SPIO_SCLK (CAVO ROSSO)
  • PIN 12 MCP3008 ----> SPIO_MISO (CAVO GRIGIO)
  • PIN 11 MCP3008 ----> SPIO_MOSI (CAVO BLU)
  • PIN 10 MCP3008 ----> SPIO_CE0_N DC (CAVO VERDE)
  • PIN 9 MCP3008   ----> GND (CAVO NERO)
  • PIN 1 MCP3008   ----> PIN VOUT SENSORE TMP36 DC (CAVO GIALLO)
Questi sono I collegamenti del circuito integrato MCP3008 con la scheda Raspberry Pi2.

Sensore di temperatura TMP36.   


Figura 3: Piedinatura sensore TMP36.

Si tratta di un sensore di temperatura analogico, il quale fornisce un valore di tensione di 10mv per grado direttamente proporzionale al valore di temperatura che è rilevato. Ha un range di lettura che va da -40  a 125 °C. Vediamo ora come collegarlo. Guardando l’immagine precedente, notiamo che ha tre pin, il primo a sinistra(1) lo colleghiamo alla tensione di 3,3 v DC, il pin centrale(2) come da figura sull’ingresso CH0 del MPC3008, il pin di destra(3) su GND.
  • PIN SINISTRA TMP36   ----> 3,3V DC (CAVO ROSSO)
  • PIN CENTRALE TMP36 ----> SU PIN 1 MCP3008(CAVO GIALLO)
  • PIN DESTRA TMP36     ----> GND (CAVO NERO)

Creazione del progetto di prova con Visual Studio 2015.  

Terminata la parte hardware, dai materiali necessari ai componenti e loro caratteristiche, e giunto ora il momento di dedicarsi alla parte software. Useremo per la creazione del progetto Visual Studio 2015. Se ancora non e stato eseguito, oltre Visual Studio 2015 e sistema operativo Windows 10 (almeno la versione Professional), e necessario scaricare ed installare L’sdk per lo sviluppo su Windows 10 che trovare a questo link. A installazioni terminate, avviamo Visual Studio 2015, e creiamo mediante il comando File, nuovo progetto un’applicazione usando il template App vuota(Windows universale) come mostrato in figura e denominiamo il progetto con “AnalogTemperature”.

Figura 4: La schermata Nuovo progetto.

Confermiamo con tasto OK. A progetto creato, per sviluppare in ambito IoT, abbiamo bisogno delle librerie necessarie. In esplora soluzioni posizioniamo il cursore su “Riferimenti”, tasto destro selezioniamo “Aggiungi riferimento”, e nella successiva schermata alla sezione “Estensioni” selezioniamo Windows IoT Exstension for the UWP come visibile nella successiva immagine.


Figura 5: La schermata Gestione riferimenti.
A livello di Estensioni abbiamo tutto il necessario. Dobbiamo ora creare un paio di classi che ci serviranno per la gestione del sensore TMP36 e MCP 3008.

Creazione Classi MCP3008 e TMP36.   

In esplora soluzioni, posizioniamo il cursore sul nome del progetto, tasto destro del mouse e scegliamo il comando “Inserisci” e subito dopo “Classe” e diamo il nome MCP3008 come il circuito integrato. Con la stessa procedura, creiamo una classe chiamata TMP36. All’interno della classe MCP3008 inseriamo il codice seguente.
using System;
using Windows.Devices.Enumeration;
using Windows.Devices.Spi;
using Windows.UI.Popups;

namespace AnalogTemperature
{
    public class MCP3008
    {
        SpiDevice _DEVICE;
        TMP36 _TMP36 = new TMP36();
        string _CHOICECHANNEL;


        const double _MAXVALUE = 1023.0;
        const int _MINVALUE = 0;
        const int _RESOLUTIONBITS = 10;
        const int _SHIFTBYTE = 8;

        byte[] _CH0 = new byte[] { 1, 0x80, 0 };
        byte[] _CH1 = new byte[] { 1, 0x90, 0 };
        byte[] _CH2 = new byte[] { 1, 0xA0, 0 };
        byte[] _CH3 = new byte[] { 1, 0xB0, 0 };
        byte[] _CH4 = new byte[] { 1, 0xC0, 0 };
        byte[] _CH5 = new byte[] { 1, 0xD0, 0 };
        byte[] _CH6 = new byte[] { 1, 0xE0, 0 };
        byte[] _CH7 = new byte[] { 1, 0xF0, 0 };
        byte[] _DATARECEIVED = new byte[] { 0, 0, 0 };



        /// <param name="serialcomunication">Define type comunication</param>
        /// <param name="channel">Define number channel of MCP3008</param>
        /// <param name="spicomunication">Define spicomunication channel</param>
        /// <param name="mode">Define spi mode</param>
        public async void InitializeMCP3008(SerialComunication serialcomunication,Channel channel,SpiComunication spicomunication, SpiMode mode)
        {
            var spiconnectionsettings = new SpiConnectionSettings((int)spicomunication);
            spiconnectionsettings.ClockFrequency = _TMP36.CLOCK_SIGNAL;
            spiconnectionsettings.Mode = mode;

            string spiDevice = SpiDevice.GetDeviceSelector(spicomunication.ToString());
            var deviceInformation = await DeviceInformation.FindAllAsync(spiDevice);

            if(deviceInformation != null && deviceInformation.Count > 0)
            {
                _DEVICE = await SpiDevice.FromIdAsync(deviceInformation[0].Id, spiconnectionsettings);
                _CHOICECHANNEL = channel.ToString();
            }

            else
            {
                var dialog = new MessageDialog("Device not found");
                await dialog.ShowAsync();
                return;
            }
        }

        public double ReturnResult()
        {
            switch (_CHOICECHANNEL)
            {
                case "CH0":
                    _DEVICE.TransferFullDuplex(_CH0, _DATARECEIVED);
                    break;

                case "CH1":
                    _DEVICE.TransferFullDuplex(_CH1, _DATARECEIVED);
                    break;

                case "CH2":
                    _DEVICE.TransferFullDuplex(_CH2, _DATARECEIVED);
                    break;

                case "CH3":
                    _DEVICE.TransferFullDuplex(_CH3, _DATARECEIVED);
                    break;

                case "CH4":
                    _DEVICE.TransferFullDuplex(_CH4, _DATARECEIVED);
                    break;

                case "CH5":
                    _DEVICE.TransferFullDuplex(_CH5, _DATARECEIVED);
                    break;

                case "CH6":
                    _DEVICE.TransferFullDuplex(_CH6, _DATARECEIVED);
                    break;

                case "CH7":
                    _DEVICE.TransferFullDuplex(_CH7, _DATARECEIVED);
                    break;
            }

            var result = ((_DATARECEIVED[1] & 0x03) << _SHIFTBYTE) + _DATARECEIVED[2];
            var mvolt = result * (_TMP36.VOLTAGE / _MAXVALUE);
            var tempCelsius = mvolt / _RESOLUTIONBITS;
            return tempCelsius;
        }
    }

    public enum SerialComunication
    {
        SINGLE_ENDED,
        DIFFERENTIAL
    }

    public enum Channel
    {
        CH0, CH1, CH2, CH3, CH4, CH5, CH6, CH7
    }

    public enum SpiComunication
    {
        SPI0,
        SPI1
    }
}
Analizziamo il codice precedente. Sono state definite delle variabili a livello di classe. La prima non e altro che la classe base per verificare e gestire device collegati alla/e porte SPI della Gpio.
        SpiDevice _DEVICE;

Qui definiamo un nuovo oggetto di tipo TMP36 che vedremo dopo.

        TMP36 _TMP36 = new TMP36();

Le variabili che seguono, sono tutte le caratteristiche del circuito intergrato MCP3008, partendo da _MAXVALUE, che sarà il valore massimo in una risoluzione 10 bit come da caratteristiche che trovate nel datasheet. _MINVALUE rappresenta il valore  minimo, _RESOLUTIONBITS e la risoluzione massima del MCP3008,  _SHIFTBYTE rappresenta lo spostamento di 8 bit che va eseguito una volta acquisiti i valori che ci vengono restituiti dal pin DOUT del MCP3008. Le variabili da _CH0 A _CH7, rappresentano gli otto canali disponibili in cui e possibile collegare un componente di tipo analogico, noi useremo in questo esempio il _CH0. La variabile _CHOICECHANNEL, servirà per memorizzare quale canale e stato utilizzato e passare il byte con la configurazione corretta, lo vedremo nel metodo ReturnResult(). Rimane ancora _DATARECEIVED,  il byte che contiene alla fine le informazioni in bit da elaborare e mostrare all’utente come temperatura rilevata.

        string _CHOICECHANNEL;
        const double _MAXVALUE = 1023.0;
        const int _MINVALUE = 0;
        const int _RESOLUTIONBITS = 10;
        const int _SHIFTBYTE = 8;

        byte[] _CH0 = new byte[] { 1, 0x80, 0 };
        byte[] _CH1 = new byte[] { 1, 0x90, 0 };
        byte[] _CH2 = new byte[] { 1, 0xA0, 0 };
        byte[] _CH3 = new byte[] { 1, 0xB0, 0 };
        byte[] _CH4 = new byte[] { 1, 0xC0, 0 };
        byte[] _CH5 = new byte[] { 1, 0xD0, 0 };
        byte[] _CH6 = new byte[] { 1, 0xE0, 0 };
        byte[] _CH7 = new byte[] { 1, 0xF0, 0 }
 byte[] _DATARECEIVED = new byte[] { 0, 0, 0 };
Il metodo InitializeMCP3008, richiede alcuni parametri, il primo e il tipo di gestione lettura dei dati dai canali su MCP3008, che possiamo impostare su “single-ended” o “differenzial” come richiesto nel datasheet, il canale sul quale colleghiamo il sensore  nel nostro caso TMP36 su CH0, quale porta SPI utilizziamo sulla Gpio, infine il modo di comunicazione sul bus SPI.
        /// <param name="serialcomunication">Define type comunication</param>
        /// <param name="channel">Define number channel of MCP3008</param>
        /// <param name="spicomunication">Define spicomunication channel</param>
        /// <param name="mode">Define spi mode</param>
        public async void InitializeMCP3008(SerialComunication serialcomunication,Channel channel,SpiComunication spicomunication, SpiMode mode)
        {

Viene definita un istanza della classe SpiConnectionSettings, passando come argomento un intero che definisce quale bus SPI viene utilizzato, per noi sarà 0.

            var spiconnectionsettings = new SpiConnectionSettings((int)spicomunication);

Impostiamo poi la frequenza di clock e la modalità. Notiamo per impostare la frequenza di clock facciamo uso di una proprietà della classe TMP36.

            spiconnectionsettings.ClockFrequency = _TMP36.CLOCK_SIGNAL;
            spiconnectionsettings.Mode = mode;

Successivamente, con la classe SpiDevice e il metodo GetDeviceSelector, otteniamo tutti i bus SPI presenti sulla scheda Raspberry Pi2.  

            string spiDevice = SpiDevice.GetDeviceSelector(spicomunication.ToString());

In questa sezione con la classe DeviceInformation, recuperiamo tutte le informazioni necessarie sul/i bus SPI. 

            var deviceInformation = await DeviceInformation.FindAllAsync(spiDevice);

Se il parametro deviceInformation non e null, e maggiore di zero, possiamo definire quale bus SPI utilizzare,  aprire il canale di comunicazione che abbiamo impostato, per noi sarà come detto SPI0, passando al metodo FromIdAsync l’Id del bus e la configurazione.

            if(deviceInformation != null && deviceInformation.Count > 0)
            {
                _DEVICE = await SpiDevice.FromIdAsync(deviceInformation[0].Id, spiconnectionsettings);
                _CHOICECHANNEL = channel.ToString();
            }

            Else

Se non sono stati rilevati bus SPI avvertiamo l’utente con una MessageDialog.

            {
                var dialog = new MessageDialog("Device not found");
                await dialog.ShowAsync();
                return;
            }
        }
In questo metodo, secondo il canale che abbiamo deciso di usare, sarà chiamato sempre il metodo TransferFullDuplex, che si occuperà di inviare le impostazioni di ciascun canale sul bus SPI selezionato, e come secondo parametro il byte dove vi saranno memorizzati i dati convertiti da segnale analogico a digitale che dobbiamo poi elaborare in maniera opportuna. Infine avremo il risultato che sarà poi il nostro valore di temperatura finale.
        public double ReturnResult()
        {
            switch (_CHOICECHANNEL)
            {
                case "CH0":
                    _DEVICE.TransferFullDuplex(_CH0, _DATARECEIVED);
                    break;

                case "CH1":
                    _DEVICE.TransferFullDuplex(_CH1, _DATARECEIVED);
                    break;

                case "CH2":
                    _DEVICE.TransferFullDuplex(_CH2, _DATARECEIVED);
                    break;

                case "CH3":
                    _DEVICE.TransferFullDuplex(_CH3, _DATARECEIVED);
                    break;

                case "CH4":
                    _DEVICE.TransferFullDuplex(_CH4, _DATARECEIVED);
                    break;

                case "CH5":
                    _DEVICE.TransferFullDuplex(_CH5, _DATARECEIVED);
                    break;

                case "CH6":
                    _DEVICE.TransferFullDuplex(_CH6, _DATARECEIVED);
                    break;

                case "CH7":
                    _DEVICE.TransferFullDuplex(_CH7, _DATARECEIVED);
                    break;
            }

            var result = ((_DATARECEIVED[1] & 0x03) << _SHIFTBYTE) + _DATARECEIVED[2];
            var mvolt = result * (_TMP36.VOLTAGE / _MAXVALUE);
            var tempCelsius = mvolt / _RESOLUTIONBITS;
            return tempCelsius;
        }
    }
_DATARECEIVED, e un array di byte, a noi servono i primi due bit di sinistra del secondo elemento, mentre il primo, ossia _DATARECEIVED[0] lo ignoriamo perché non vi sarà alcun valore. Andiamo poi a sommare  _DATARECEIVED[1] con_DATARECEIVED[2]. I calcoli successivi, non fanno altro che ricavare il valore di temperatura, da notare _TMP36.VOLTAGE, che vedremo dopo. Ho inserito inoltre tre enumerazioni che serviranno nel momento in cui nella MainPage definiamo il codice per implementare il metodo InitializeMCP3008, sono il tipo di comunicazione, il canale utilizzato e su quale bus SPI intendiamo inviare e ricevere dati.
    public enum SerialComunication
    {
        SINGLE_ENDED,
        DIFFERENTIAL
    }

    public enum Channel
    {
        CH0, CH1, CH2, CH3, CH4, CH5, CH6, CH7
    }

    public enum SpiComunication
    {
        SPI0,
        SPI1
    }
 Questo e il necessario per la classe MCP3008. Passiamo ora alla classe TMP36, dopo averla creata, inseriamo il codice che segue.  
namespace AnalogTemperature
{
    public class TMP36
    {
        const int _CLOCKSIGNAL = 1650000;
        const double _VOLTAGE = 2000;


        public int CLOCK_SIGNAL
        {
            get
            {
                return _CLOCKSIGNAL;
            }
        }

        public double VOLTAGE
        {
            get
            {
                return _VOLTAGE;
            }
        }
    }
}

Semplicemente, sono definiti dei parametri che sono la frequenza di clock, e la tensione massima che può il sensore erogare a massimo regime, il  TMP36 a 125° c, eroga una tensione di circa 2 vdc.


Creazione dell’interfaccia grafica e codice nella classe MainPage.   

Definite alche le classi necessarie, vediamo come implementare il tutto nella Classe MainPage. In esplora soluzioni, doppio click con il mouse su MainPage.xaml, entrati nell’editor di codice definiamo la nostra interfaccia grafica, inserendo il seguente codice XAML.

<Page
    x:Class="AnalogTemperature.MainPage"
    xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
    xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
    xmlns:local="using:AnalogTemperature"
    xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
    xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
    mc:Ignorable="d">

    <Grid Background="{ThemeResource ApplicationPageBackgroundThemeBrush}">

        <Grid.RowDefinitions>
            <RowDefinition Height="Auto"/>
            <RowDefinition Height="Auto"/>           
        </Grid.RowDefinitions>

        <Grid.ColumnDefinitions>
            <ColumnDefinition Width="Auto"/>
            <ColumnDefinition Width="Auto"/>
            <ColumnDefinition Width="Auto"/>           
        </Grid.ColumnDefinitions>
       
       
            <TextBlock Grid.Row="0" Grid.ColumnSpan="3" x:Name="txtHeader" FontSize="50" Text="TMP 36 AND MCP 3008 SAMPLE"/>

            <TextBlock Grid.Column="0" Grid.Row="1" x:Name="txtReadingTemp" FontSize="30" Margin="15,0,0,0" Text="Temperature value is:"/>

            <TextBlock Grid.Column="1" Grid.Row="1" x:Name="txtReading" FontSize="30" Margin="15,0,0,0"/>

            <TextBlock Grid.Column="2" Grid.Row="1" x:Name="txtCelsius" FontSize="30" Margin="15,0,0,0" Text="°C"/>                  
    </Grid>
</Page>

Di per se e molto semplice, ma sufficiente per visualizzare il valore di temperatura restituito dal metodo ReturnResult() della classe MCP3008 che rappresenta il nostro obbiettivo. Con tasto F7, entriamo nell’editor di codice C#, inserendo la parte sottostante.

using System;
using Windows.UI.Xaml;
using Windows.UI.Xaml.Controls;
using Windows.Devices.Spi;

// Il modello di elemento per la pagina vuota è documentato all'indirizzo http://go.microsoft.com/fwlink/?LinkId=402352&clcid=0x410

namespace AnalogTemperature
{
    /// <summary>
    /// Pagina vuota che può essere utilizzata autonomamente oppure esplorata all'interno di un frame.
    /// </summary>
    public sealed partial class MainPage : Page
    {
        DispatcherTimer _timer = new DispatcherTimer();
        MCP3008 _mcp3008 = new MCP3008();

        public MainPage()
        {
            InitializeComponent();
            _mcp3008.InitializeMCP3008(SerialComunication.SINGLE_ENDED, Channel.CH0, SpiComunication.SPI0,SpiMode.Mode0);
            _timer.Interval = new TimeSpan(0, 0, 5);
            _timer.Start();
            _timer.Tick += _timer_Tick;
        }

        private void _timer_Tick(object sender, object e)
        {
            txtReading.Text = Math.Round(_mcp3008.ReturnResult()).ToString();
        }
    }
}


Analizzando il precedente codice C#, inizializziamo un Timer.

        DispatcherTimer _timer = new DispatcherTimer();

Definiamo un oggetto di tipo MCP3008.

        MCP3008 _mcp3008 = new MCP3008();

Ne implementiamo il metodo InitializeMCP3008,passando i parametri necessari.

            _mcp3008.InitializeMCP3008(SerialComunication.SINGLE_ENDED, Channel.CH0, SpiComunication.SPI0,SpiMode.Mode0);

Impostiamo la proprietà Interval del timer con un valore di tipo TimeSpan di 5 secondi,  lo avviamo con il metodo Start() ,e gestiamo infine il suo evento Tick.

             _timer.Interval = new TimeSpan(0, 0, 5);
            _timer.Start();
            _timer.Tick += _timer_Tick;


All’interno dell’evento Tick, andiamo a valorizzare la proprietà Text del controllo TextBox txtReading, mostrando il valore di temperatura richiamando il metodo ReturnResult(), ma prima arrotondiamo il valore con la classe statica Math e il metodo Round() per togliere i decimali di troppo.


        private void _timer_Tick(object sender, object e)
        {
            txtReading.Text = Math.Round(_mcp3008.ReturnResult()).ToString();
        }



Test dell’applicazione.

Terminata la parte di codice, prima di eseguire il test dell’applicazione, ci sono un paio di cose da vedere. La prima essendo che stiamo sviluppando su Raspberry Pi2, e quella di impostare la compilazione in modalità ARM, lo si può eseguire dal menù a tendina come presente in figura.

Figura 6: Il menù principale di Visual Studio 2015.

In riferimento all’immagine precedente, noterete che è attivata l’esecuzione come “Computer remoto”. Questo perché vogliamo eseguire l’applicazione sulla scheda Raspberry Pi2. Selezionate questa modalità, e alla schermata seguente andiamo a selezionate il device e l’indirizzo IP della Raspberry Pi2 deselezionando l’autenticazione, in alternativa è possibile modificare queste impostazioni, selezionando il progetto, tasto destro del mouse, selezioniamo il comando “Proprietà” e subito dopo “Debug”, saremo condotti nella seguente schermata.


Figura 7: La sezione debug nelle proprietà del progetto.

Terminata quest’attività, possiamo eseguire il Debug dell’applicazione. Tasto F5, e se tutto è stato eseguito in maniera corretta, ecco cosa visualizzeremo a monitor.

Figura 8: L’applicazione di esempio in esecuzione sulla Raspberry Pi2 e Windows 10 IoT.


Conclusione.

In quest’articolo, e stata fatta un’introduzione su cosa sono i sensori Analogici, cosa e un convertitore ADC, perché la scheda RaspberryPi2 necessita di questo componente per fare uso dei sensori e strumenti con segnale analogico. Nei prossimi articoli, vedremo di approfondire questi argomenti, utilizzando altri componenti e vedere come adattare diverse tipologie di sensori e strumenti analogici sul convertitore ADC e Raspberry.