InputPort OutputPort come utilizzare e configurare le porte digitali del Netduino
Pin digitali
La scheda Netduino prende spunto dal progetto Arduino, infatti, la forma della scheda e la disposizione dei connettori è identica a quella di Arduino UNO. I pin digitali sono 14 e possono essere configurati via software come ingressi o uscite (InputPort OutputPort). La possibilità di decidere programmaticamente la funzione di ognuno di questi pin permette una elevata flessibilità nell’adattare Netduino al mondo esterno.
La tensione di lavoro dei pin è di 3.3Vdc ma è possibile lavorare anche con tensioni in ingresso di 5Vdc (TTL). Per quanto riguarda la corrente prelevabile abbiamo valori massimi di 8 mA; i pin 2, 3, e 7 riescono a fornire 16mA massimi.
I pin sono collegati direttamente al chip Atmel, occorre fare molta attenzione ai collegamenti esterni, un corto circuito o una tensione di sovraccarico potrebbero danneggiare irreparabilmente il microcontrollore.
Configurazione pin in uscita
Vediamo come configurare un pin digitale in uscita, utilizzando la classe OutputPort (Microsoft.SPOT.Hardware.OutputPort). I parametri da passare al costruttore sono l’identificativo del pin che vogliamo usare come uscita e il suo stato iniziale (Livello logico alto pari a3.3Vdc oppure livello logico basso pari a 0Vdc).
Ecco un esempio che mostra come configurare il pin0 del Netduino come uscita
//Pin 0 in uscita, inizializzato a livello logico basso OutputPort pin0 = new OutputPort(Cpu.Pin.GPIO_Pin0, false);
Se stiamo realizzando un circuito di esempio consiglio di inizializzare la porta in uscita a false (livello logico basso) per evitare di collegare per errore il pin a massa (corto circuito) con conseguente possibile rottura della porta del chip Atmel.
La classe Pins enumera tutte le porte del Netduino disponibili per la configurazione come uscite o ingressi.
L’operazione fondamentale disponibile per il pin è il cambio di livello utilizzando il metodo Write() dell’oggetto appena istanziato.
Il codice seguente mostra come utilizzare il metodo Write()
//Mette a livello alto (3.3Vdc) il pin D0 pin0.Write(true); //Mette a livello basso (0Vdc) il pin D0 pin0.Write(false); [/csharp] Sebbene il pin0 sia configurato come uscita, possiamo leggere, tramite il metodo Read(), il livello logico impostato con il metodo Write(): [csharp] //creo una variabile bool per memorizzare lo stato della porta Boolean Livello = false; //Mette a livello alto (3.3Vdc) il pin D0 pin0.Write(true); //leggo lo stato del livello Livello = pin0.Read(); //restituisce true Debug.Print(Livello.ToString()); //Mette a livello basso (0Vdc) il pin D0 pin0.Write(false); //leggo lo stato del livello Livello = pin0.Read(); //restituisce false Debug.Print(Livello.ToString());
La proprietà InitialState restituisce lo stato del livello al momento della creazione dell’oggetto
//creo una variabile bool per memorizzare lo stato della porta Boolean Livello = false; //Pin 0 in uscita, inizializzato a livello logico basso OutputPort pin0 = new OutputPort(Cpu.Pin.GPIO_Pin0, false); //Mette a livello alto (3.3Vdc) il pin D0 pin0.Write(true); //leggo lo stato del livello al momento della creazione //dell'oggetto pin0 Livello = pin0.InitialState; //restituisce false Debug.Print(Livello.ToString());
La proprietà ID fornisce il nome del piedino del microcontrollore Atmel (come definito nel datasheet)
//Creo un oggetto Pin Cpu.Pin nomePin; //Pin 0 in uscita, inizializzato a livello logico basso OutputPort pin0 = new OutputPort(Cpu.Pin.GPIO_Pin0, false); //Ottengo il nome del pin riferito al microcontrollore Atmel nomePin = pin0.Id; Debug.Print(nomePin.ToString());
Configurazione pin in ingresso
Per accettare segnali in ingresso dobbiamo decidere quali pin utilizzare e configurarli con la classe InputPort (Microsoft.SPOT.Hardware.InputPort). In questo caso i parametri da passare al costruttore sono 3, il primo definisce l’identificativo del pin da utilizzare come ingresso, il secondo permette di attivare il filtro antirimbalzo (glitch filter) e il terzo permette di attivare l’eventuale resistenza di pull-up interna al microcontrollore.
Il codice seguente utilizza il pin3 del Netduino come ingresso.
//Definisco il pin 3 come ingresso, abilito l'antirimbalzo e la reistenza di pullup InputPort pin3 = new InputPort(Cpu.Pin.GPIO_Pin3, true, Port.ResistorMode.PullUp);
Il metodo Read() permette di leggere il livello logico presente sul pin di ingresso. Read() restituisce un valore booleano in funzione del livello logico.
Boolean Livello = false; //Pin3 in ingresso InputPort pin3 = new InputPort(Cpu.Pin.GPIO_Pin0, true, Port.ResistorMode.PullUp); //leggo dal pin3 Livello = pin3.Read();
Le proprietà esposte dall’oggetto sono ID, GlitchFilter e Resistor
Boolean Livello = false; Boolean StatoFiltro= false; Port.ResistorMode Resistenza; //Variabile per contenere il nome del pin Cpu.Pin nomePin; //nome del pin come indicato nel datasheet del microcontrollore nomePin = pin3.Id; Debug.Print(nomePin.ToString()); //stato del filtro antirimbalso StatoFiltro = pin3.GlitchFilter; Debug.Print("StatoFiltro " + StatoFiltro.ToString()); //tipo di resistenza selezionato Resistenza = pin3.Resistor; Debug.Print("Resistenza " + Resistenza.ToString());
GlitchFilter
Il filtro antirimbalzo permette di eliminare gli impulsi spurii che si formano nei contatti metallici di un pulsante. All’atto della chiusura del pulsante il contatto non avviene immediatamente ma esiste un piccolo tempo di assestamento che da luogo a degli impulsi spurii che possono essere interpretati erroneamente dal Netduino. Attivando il filtro, introduciamo un certo ritardo prima di leggere lo stato dell’ingresso, in questo modo possiamo avere una lettura sicura poichè il contatto meccanico si è ormai stabilizzato.
La figura mostra gli impulsi spurii generati dall’interruttore:
ResistorMode
Questa proprietà è molto importante perché permette di eseguire delle letture sicure del livello logico in ingresso quando, il circuito esterno, non imposta un riferimento di tensione sul pin. Le resistenze di pull up permettono di forzare un livello logico alto stabile sul pin d’ingresso. Nel caso del microcontrollore SAM7X possiamo utilizzare solo le resistenze di PullUp, dato che non sono presenti quelle di pull down (Impostando Port.ResistorMode.PullDown otteniamo un eccezione).
Abbiamo visto che per leggere dai pin dobbiamo richiamare il metodo Read(), quindi se vogliamo tenere sempre sotto controllo lo stato dell’ingresso è necessario eseguire ciclicamente il metodo Read(); sarebbe comodo un sistema che monitorizzi l’ingresso in modo da rilevare i cambiamenti di stato. Fortunatamente il Netduino ed il .Net micro framework mettono a disposizione la classe InterruptPort che svolge proprio questa funzionalità.
Configurazione pin in ingresso con InterruptPort
La classe InterruptPort permette di utilizzare un pin come ingresso e di eseguire un metodo ogni qualvolta che si verifica un cambiamento di stato su tale pin. Vediamo come configurare un pin in ingresso con la classe InterruptPort
InterruptPort pin0 = new InterruptPort(Cpu.Pin.GPIO_Pin0, false, Port.ResistorMode.PullUp, Port.InterruptMode.InterruptEdgeBoth);
Il costruttore è molto simile alla classe InputPort ma in questo caso abbiamo un parametro aggiuntivo che definisce in che modo deve essere generato l’interrupt per quel pin. Le possibili opzioni sono:
Le opzioni sono diverse e riescono a soddisfare tutte le variazioni di segnale che possono interessare il pin in ingresso.
La parte importante è la possibilità di generare un evento ogni volta che si verifica un’interrupt. Il codice di esempio mostra come farlo
public static void Main() { //Definisco il pin0 come InterruptPort //L'interrupt viene generato sul fronte di salita InterruptPort pin0 = new InterruptPort(Cpu.Pin.GPIO_Pin0, false, Port.ResistorMode.PullUp, Port.InterruptMode.InterruptEdgeHigh); //Creo un evento quando si scatena un interrupt //Ogni volta che viene generato un evento viene eseguito il metodo EventoPinIngresso pin0.OnInterrupt += new NativeEventHandler(EventoPinIngresso); while(true) { //eseguo qualcosa Thread.Sleep(100); } } public static void EventoPinIngresso(uint data1, uint data2, DateTime time) { //eseguo qualcosa quando viene generato un interrupt Debug.Print(data1.ToString()); Debug.Print(data2.ToString()); Debug.Print(time.ToString()); }
In questo modo ogni volta che il segnale in ingresso scatena un interrupt, Netduino esegue il codice contenuto in EventoPinIngresso.
La firma del metodo EventoPinIngresso deve contenere due valori uint e una DateTime. Il primo valore (data1) contiene il numero del pin del microcontrollore, il secondo contiene il livello logico sul pin e il terzo (time) contiene il tempo in cui è stato scatenato l’evento.
Da notare che la gestione dell’evento è asincrona e quindi il Netduino continua ad eseguire il codice del ciclo while ed esegue autonomamente il metodo EventoPinIngresso quando si verifica un interrupt.
Questa funzionalità permette di creare codice che reagisce autonomamente agli eventi esterni e fa in modo che il Netduino si adatti meglio alle esigenze progettuali moderne.
Related posts
2 Comments
Lascia un commento Annulla risposta
Questo sito usa Akismet per ridurre lo spam. Scopri come i tuoi dati vengono elaborati.
Articoli popolari
Sorry. No data so far.
.Net micro framework Arduino Arduino Webserver Domotica Flyport I2C IOT Netduino OpenPicus raspberry RTC Speed Test
Come al solito… bell’articolo… devo dire che anche il concetto di interrupt è stato esposto con chiarezza ed è abbastanza sintetico… sto Netduino mi piace sempre di più… non sono espertissimo di arduino ma le funzionalità delle resistenze di GlitchFilter e pullup interne sono previste?
Grazie!
Arduino non ha un filtro antirimbalzo, ma puoi comunque realizzarlo via software, ci sono molti esempi a proposito. Per le resistenze di pull-up non sono sicuro ma penso che vengano abilitate di default.