Come usare la seriale RS232
L’interfaccia RS232 è un protocollo standard che permette lo scambio, a bassa velocità, tra dispositivi digitali. Lo standard RS232 nacque nei prima anni 60 e nonostante sia un protocollo piuttosto vecchio è ancora oggi utilizzato per la comunicazione tra microcontrollori, dispositivi industriali e da svariati circuiti che non necessitano di elevate velocità di comunicazione.
Il termine seriale significa che i bit vengono trasferiti uno dopo l’altro su un singolo filo elettrico.
Il segnale RS232 è rappresentato nella figura seguente e può essere visualizzato tramite un comune oscilloscopio
Come possiamo vedere i valori di tensione del segnale RS232 vanno da -12Vdc a 12Vdc. Il segnale è composto sempre da un bit di start seguito da 8 bit di dati. Il bit 1 (Alto) è identificato da una tensione di -12Vdc mentre il bit 0 (Basso) corrisponde ad un livello di tensione di +12Vdc.
La velocità della comunicazione seriale è espressa in bps (bit per second) ed indica, appunto, la quantità di bit inviati in un secondo. La durata di un singolo bit dipende dalla velocità scelta per la trasmissione. Se per i nostri scopi abbiamo bisogno di una comunicazione seriale a 9600bps il singolo bit avrà una larghezza di 104us (1/9600).
Il connettore disponibile in molti pc desktop è un DB9 maschio ed è composto da nove pin, i quali svolgono delle funzioni specifiche:
Il Netduino ha due ‘porte’ seriali disponibili tramite i pin 0 e 1 (UART1) e i pin 2 e 3 (UART2). Questi piedini lavorano con logica TTL e non possono essere collegati direttamente al connettore DB9 del pc, ma si ha bisogno di un componente esterno che converta il segnale TTL (0/5 Vdc) in un segnale RS232 (-12/+12 Vdc).
Ci sono diversi componenti che permettono questa conversione, io solitamente uso il MAX233 il cui circuito di impiego (pagina 21 del datasheet) è molto semplice e non necessita di ulteriori componenti esterni (condensatori o resistenze).
Lo schema elettrico del progetto è il seguente e risulta molto semplice nei collegamenti:
La trasmissione dei dati avviene tramite il pin 1 del Netduino, che è collegato all’ingresso 3 del MAX233; l’uscita RS232 è disponibile sul pin 5 del MAX233 ed è collegata al pin 2 del connettore DB9 femmina (corrispondente al pin RX del PC). Viceversa il PC trasmette sul pin 3 del connettore DB9 maschio che è collegato tramite il connettore DB9 femmina al pin 4 del MAX233 che provvederà a convertire il segnale RS233 in TTL, l’uscita TTL del MAX233 disponibile sul pin 3 è collegata al pin 0 del Netduino.
Ora che il circuito è pronto, passiamo alla creazione del software di esempio per testare la comunicazione seriale tra Netduino e PC.
Avviamo un nuovo progetto con Visual C#.
Prima di scrivere il codice aggiungiamo un riferimento alla libreria Microsoft.SPOT.Hardware.SerialPort. In esplora soluzioni clicchiamo con il pulsante destro del mouse sulla voce Riferimenti, dal menu contestuale visualizzato, clicchiamo su Aggiungi Riferimento…, verrà visualizzata la finestra Add Reference. Clicchiamo sul tab .Net, poi sul componente Microsoft.SPOT.Hardware.SerialPort e confermiamo con il pulsante OK.
Ora apriamo il file Program.cs ed iniziamo a scrivere il codice che permetterà al Netduino di inviare, ad intervalli di tempo regolari, una serie di caratteri al pc:
using System; using System.Threading; using Microsoft.SPOT; using Microsoft.SPOT.Hardware; using SecretLabs.NETMF.Hardware; using SecretLabs.NETMF.Hardware.Netduino; using System.IO.Ports; using System.Text; namespace NetduinoApplication1 { public class Program { public static void Main() { SerialPort UART1 = new SerialPort("COM1", 9600, Parity.None, 8, StopBits.One); OutputPort led = new OutputPort(Pins.ONBOARD_LED, false); UART1.Open(); String Messaggio = "Ciao!"; Byte[] bytesMessaggio = Encoding.UTF8.GetBytes(Messaggio); while(true) { led.Write(true); UART1.Write(bytesMessaggio, 0, bytesMessaggio.Length); Thread.Sleep(100); led.Write(false); Thread.Sleep(500); } UART1.Close(); } } }
La prima cosa da fare è caricare il namespace System.IO.Ports (per accedere alla porta seriale) e System.Text (per convertire una stringa in un array di bytes e viceversa) (righe di codice 8 e 9).
UART1 è l’oggetto che ci permette di accedere alla porta COM1 del Netduino (pin 0 e 1, mentre COM 2 è riferita ai pin 2 e 3) impostata per lavorare ad una velocità di 9600bps, con nessuna parità, 8 bit di dati ed un bit di stop.
Queste impostazioni devono essere identiche a quelle della seriale del pc.
Per avviare la comunicazione è necessario aprire la porta seriale, con il metodo Open() dell’oggetto UART1, mentre per spedire i dati dobbiamo utilizzare il metodo Write(). Questo metodo accetta un array di byte e bisogna specificare l’offset di questo array da spedire.
L’oggetto led indica quando vengono spediti i dati sulla porta del Netduino, il metodo Sleep() crea invece un ritardo tra una spedizione e l’altra.
Avviamo il debug(F5) per fare girare il programma sul Netduino.
I dati vengono inviati al pc, per visualizzarli utilizziamo il programma HyperTerminal. Per i possessori di Windows Xp, dovete andare in:
Start->Tutti i programmi->Accessori->Comunicazioni->HyperTerminal
all’avvio il programma chiede di dare un nome alla sessione, mettiamone uno indicativo e clicchiamo sul pulsante OK
La schermata seguente chiede quale porta seriale vogliamo usare, solitamente i pc odierni hanno una sola porta indicata come COM1 (verificate sul manuale della scheda madre), clicchiamo sul pulsante OK.
La finestra successiva mostra i vari parametri configurabili per la porta COM1
Inseriamo gli stessi parametri che sono presenti nel codice C# relativi all’oggetto UART1
SerialPort UART1 = new SerialPort("COM1", 9600, Parity.None, 8, StopBits.One);
quindi:
Bit per secondo = 9600, Bit di dati = 8, Parità= Nessuno, Bit di Stop = 1, Controllo di Flusso = Nessuno.
Assicuriamoci che il cavo seriale colleghi il MAX233 ed il PC e confermiamo con il pulsante OK per avviare la ricezione dei dati dal Netduino
Certamente è una bella emozione (a noi fanatici prende così!!) aver avviato una comunicazione tra un dispositivo hardware ed il pc.
Il passo successivo è modificare il programma per dare la capacità al Netduino di ricevere comandi dal pc per creare una comunicazione bidirezionale completa.
Ecco l codice per poter predisporre il Netduino alla ricezione dei comandi.
using System; using System.Threading; using Microsoft.SPOT; using Microsoft.SPOT.Hardware; using SecretLabs.NETMF.Hardware; using SecretLabs.NETMF.Hardware.Netduino; using System.IO.Ports; using System.Text; namespace NetduinoApplication1 { public class Program { public static void Main() { OutputPort led = new OutputPort(Pins.ONBOARD_LED, false); SerialPort UART1 = new SerialPort("COM1", 9600, Parity.None, 8, StopBits.One); UART1.Open(); String Messaggio = "RX OK!"; String MessaggioPC = ""; Int32 NumByteDisponibili = 0; Byte[] bytesMessaggio = Encoding.UTF8.GetBytes(Messaggio); Byte[] bytesRicevuti; while(true) { if (UART1.BytesToRead > 0) { NumByteDisponibili = UART1.BytesToRead; bytesRicevuti = new Byte[NumByteDisponibili]; UART1.Read(bytesRicevuti, 0, NumByteDisponibili); MessaggioPC = new String(Encoding.UTF8.GetChars(bytesRicevuti)); Debug.Print("Byte nel buffer del Netduino = " + NumByteDisponibili.ToString()); Debug.Print("Messaggio da PC = " + MessaggioPC); //Accendi il Led if (MessaggioPC == "a") { led.Write(true); } //Spegni il led if (MessaggioPC == "s") { led.Write(false); } //Blink if (MessaggioPC == "b") { Boolean Stato = true; for (Int32 Ciclo = 0; Ciclo <= 10; Ciclo++) { Stato = !Stato; led.Write(Stato); Thread.Sleep(100); } } //invia al pc un informazione UART1.Write(bytesMessaggio, 0, bytesMessaggio.Length); } Thread.Sleep(500); } UART1.Close(); } } }
Eseguiamo il debug(F5) per caricare il programma sul Netduino.
Per capire se il pc ha inviato dei dati al Netduino utilizziamo la proprietà BytesToRead dell’oggetto UART1; questa proprietà ci indica quanti byte sono presenti nel buffer della seriale del Netduino. Il codice verifica ciclicamente quando ci sono dei bytes nel buffer (UART1.BytesToRead > 0); in funzione del numero di byte presenti, creo un array della dimensione appropriate (bytesRicevuti = new Byte[NumByteDisponibili];).
Successivamente eseguo il metodo Read() che svuota il buffer della seriale e riempe l’arraybytesRicevuti.
Ora posso lavorare con i dati inviati dal pc!
Nel codice d’esempio accendo, spengo e faccio blinkare il led on board a seconda del dato inviato dal pc, utilizzando le varie istruzioni if. Da notare il metodo GetChar() che permette di codificare i byte nello standard UTF8.
Per comunicare con il Netduino posso sempre utilizzare HyperTerminal; nella configurazione standard HyperTerminal non visualizza i caratteri digitati con la tastiera.
Modifichiamo questa caratteristica andando nelle opzioni del programma cliccando sul menu File e poi sulla voce Proprietà.
Nella finestra appena visualizzata clicchiamo sul tab Impostazioni e poi sul pulsante Impostazioni ASCII….
Questa finestra presenta varie opzioni, spuntiamo la voce Eco dei caratteri digitati localmente, e confermiamo con il pulsante OK.
Proviamo subito il codice!
Dalla finestra HyperTerminal digitiamo una a per accendere il led on board, una s per spegnerlo e la b per farlo blinkare. Il Netduino eseguirà queste operazioni e invierà al pc il testo RX OK! tramite l’istruzione UART1.Write(bytesMessaggio, 0, bytesMessaggio.Length);.
Questo semplice esperimento ci insegna le basi per iniziare ad interfacciare il pc con il Netduino e per capire come convertire il segnale TTL in segnale RS232.
Aspetto vostri commenti e consigli.