Comunicación Serial Wpf

Bienvenid@ lector/a, en esta nueva entrada veremos cómo leer y escribir datos a un puerto serial, específicamente el puerto serial corresponderá al de un Arduino, por lo cual el Puerto COM queda habilitado automáticamente cuando instalas Arduino IDE.

Primero que todo que es comunicación serial o serie, según es.wikipedia.org la comunicación serie es el proceso de envió de datos de un bit a la vez, de forma secuencial, sobre un canal de comunicación o un bus de datos.

Imagen referencia: Señales de comunicación serie.


Empezando crearemos un una nueva solución para WPF tal como se muestra en el siguiente LINK
A continuación crearemos la interfaz gráfica como se muestra en la Imagen 1.


Imagen 1: Interfaz gráfica primaria.


Como paso siguiente crearemos una nueva clase llamada “ScrollingTextBox”, esta clase se encargara de ir actualizando el TextBox de log (txtRecibe), es decir, su función es agregar el texto recibido o enviado en el TextBox y además dejar el Scroll de este mismo en la última línea escrita. Para realizar esto deben de seguir los pasos de la Imagen 2 e Imagen 3.

Imagen 2: Agregar nueva clase.


Imagen 3: Nombrar la nueva clase y crearla.


Una vez hecho lo anterior deben de pegar el siguiente Código, el que se encargara de lo antes mencionado.

   1:  using System;
   2:  using System.Collections.Generic;
   3:  using System.Linq;
   4:  using System.Text;
   5:  using System.Threading.Tasks;
   6:  using System.Windows.Controls;
   7:   
   8:  namespace Serial
   9:  {
  10:      public class ScrollingTextBox : TextBox
  11:      {
  12:   
  13:          protected override void OnInitialized(EventArgs e)
  14:          {
  15:              base.OnInitialized(e);
  16:              VerticalScrollBarVisibility = ScrollBarVisibility.Auto;
  17:              HorizontalScrollBarVisibility = ScrollBarVisibility.Auto;
  18:          }
  19:   
  20:          protected override void OnTextChanged(TextChangedEventArgs e)
  21:          {
  22:              base.OnTextChanged(e);
  23:              CaretIndex = Text.Length;
  24:              ScrollToEnd();
  25:          }
  26:   
  27:      }
  28:  }
Luego de realizar el paso anterior nos enfocaremos netamente en el “MainWindows.xaml.cs”, ya que este se encargara de toda la lógica del programa. En primer lugar agregaremos las librerías necesarias para la comunicación Serial.

  • System.IO.Ports
  • System.Collections.Concurrent
  • System.Windows.Threading
  • System.Threading
  • System.Collections.Generics      

Una vez importadas, inicializaremos las variables que se implementaran.

   1:  private SerialPort _serialport;
   2:  private DateTime _datetime;
   3:  private int[] frecuencias;
   4:  private String comparacion;

Iniciaremos los valores por defectos de las frecuencias o baudios que se utilizan para la comunicación serial, y los puertos COM disponibles en el sistema.

   1:  frecuencias = new int[]{4800,9600,19200,38400,57600,115200,230400,250000};
   2:  foreach (String s in System.IO.Ports.SerialPort.GetPortNames())
   3:  {
   4:      comboPuertos.Items.Add(s);
   5:  }
   6:   
   7:  comboFrecuencia.ItemsSource = frecuencias;


Enseguida crearemos un método que se encargara de realizar la conexión serial entre nuestra PC y el dispositivo físico o virtual en cuestión.

   1:  private void conectar_puertoserial(String puerto, int frecuencia)
   2:  {
   3:    _serialport = new SerialPort(puerto, frecuencia, Parity.None, 8, StopBits.One);
   4:   
   5:     String formato = string.Format("Conectado");
   6:     try
   7:     {
   8:         _serialport.Open();
   9:         actualiza_consolaUI(formato);
  10:         _serialport.DataReceived += new SerialDataReceivedEventHandler(SerialPortDataReceived);
  11:      }
  12:      catch (Exception ex) { MessageBox.Show(ex.ToString(), "Error"); }
  13:  }


El fragmento anterior recibe como parámetro un puerto como cadena y una frecuencia de baudios en entero, luego se instancia un objeto tipo SerialPort con los datos recibido y algunos parámetros extras de configuración, en seguida abre el puerto y enseña visualmente que se conectó, y empieza a recibir los datos a través del método “SerialPortDataReceived” que se programara enseguida.
El método “SerialPortDataReceived” como su nombre lo indica se encarga de recibir todos los datos que se envíen desde el puerto COM conectado.

   1:  private void SerialPortDataReceived(object sender, SerialDataReceivedEventArgs e)
   2:  {
   3:     String reciberx = _serialport.ReadExisting();
   4:     String formato = string.Format("Recibido:{0}",reciberx.TrimEnd());
   5:   
   6:     if (reciberx.Length > 2 && reciberx != comparacion)
   7:     {
   8:          actualiza_consolaUI(formato);
   9:          comparacion = reciberx;
  10:      }       
  11:  }


El fragmento anterior guarda el dato en una cadena de texto, solo si existe algo que recibir, es decir si el dispositivo conectado en este caso Arduino envía datos, en seguida pregunta si el largo de la cadena recibida tiene un tamaño deseado y es diferente a una variable de comparación. La variable de comparación se encarga de verificar que la cadena recibida sea diferente a una anterior, para así liberar carga cuando venga repetida.

El método “actualizar_consolaUI” se encarga de actualizar el log de lo que se esta realizando, todas las acciones dentro de este método esta bajo un hilo del sistema, ya que si no se hiciera en segundo plano la modificación visual de los elementos de WPF estos harían saltar un error de hilos

   1:  private void actualiza_consolaUI(String s) {
   2:     Application.Current.Dispatcher.Invoke(
   3:           DispatcherPriority.Background,
   4:           new ThreadStart(delegate
   5:            {
   6:                _datetime = DateTime.Now;
   7:                String formato = String.Format("[{0}]{1}\n", _datetime, s);
   8:                txtrecibe.AppendText(formato);
   9:                txtrecibe.Focus();                             //Obtiene el focus
  10:                txtrecibe.CaretIndex = txtrecibe.Text.Length;  //Obtiene el tamaño de la caja
  11:                 txtrecibe.ScrollToEnd();                       //setea scroll al final
  12:             }));
  13:          }


A continuación se procede a programar los botones que realizaran las acciones de: Conectar, Desconectar y enviar datos hacia el puerto Serial. Como lo primero que se realiza es la conexión empezara por el botón conectar, el cual básicamente obtiene los valores del puerto y la frecuencia que se desea utilizar.

   1:  private void btn_conectar_Click(object sender, RoutedEventArgs e)
   2:  {
   3:     String puerto = comboPuertos.Text;
   4:     int frecuencia = Convert.ToInt32(comboFrecuencia.Text);   
   5:     conectar_puertoserial(puerto, frecuencia);
   6:  }


El botón desconectar, realiza la función de cerrar y liberar cualquier puerto COM que se halla ocupado.

   1:  private void btn_desconectar_Click(object sender, RoutedEventArgs e)
   2:  {
   3:    if (_serialport.IsOpen)
   4:     {
   5:          _serialport.Close();              
   6:          actualiza_consolaUI("Desconectado");
   7:     }
   8:  }


En cuanto al botón enviar, este trabaja en cooperación con el TextBox txt_enviar, en el cual se envía todo lo que exista en dicha caja de texto.

   1:  private void btn_enviar_Click(object sender, RoutedEventArgs e)
   2:  {
   3:      String dato_a_enviar = txt_enviar.Text;
   4:      _serialport.Write(dato_a_enviar);         
   5:      String formato = string.Format("Enviado:{0}", dato_a_enviar);   
   6:   
   7:         actualiza_consolaUI(formato);
   8:  }

Resultados:

Imagen 4: Conectando.


Imagen 5: Recibiendo datos.


Pero sin más les dejos la solución de la aplicación en este LINK

APLICACIÓN DESARROLLADA CON VISUAL STUDIO 2013

Este sitio fue creado en primera instancia como un lugar donde ir acumulando información y/o apuntes que considere de utilidad para un futuro cercano, pero a medida que ha avanzado el tiempo este lugar se ha vuelto un punto de encuentro para muchas personas que se están iniciando en el mundo de la programación, es por eso que si estás leyendo esto estas invitado a participar en de esta comunidad que día a día va creciendo.


Si estás dispuesto a cooperar te sugiero que dejes tus inquietudes, dudas o aportes en la caja de comentario de cualquiera de las entradas del blog o haciendo directamente desde el formulario de contacto que puede encontrar en la página de inicio y responderé a la brevedad.

Entradas más populares de este blog

Convertir decimal a binario, octal y hexadecima

Crear servicio web en Visual C# (WebService)