About read values of received data (Complete code for last post)

Atendiendo la petición de un lector pidiéndome el código completo…

Public Class Form1
    ''' <summary>
    ''' Complete code to test the frame reading values sample (last post)
    ''' PepLluis, 11/10/2011
    ''' </summary>
    ''' <param name="sender"></param>
    ''' <param name="e"></param>
    ''' <remarks></remarks>
    Private Sub Form1_Load(sender As System.Object, e As System.EventArgsHandles MyBase.Load
        ' Simulate string frame with values
        Dim frame = "{W111}{M222}{F333}{S444}"
        ' define Label and textboxes
        Dim Label1 As New Label With
            {.Name = "Label1", .AutoSize = True, .Location = New Drawing.Point(12, 10), .Text = "Frame :" + frame}
        Dim TextBox1 As New TextBox With {.Name = "TextBox1", .Width = 60, .Location = New Drawing.Point(12, 30)}
        Dim TextBox2 As New TextBox With {.Name = "TextBox2", .Width = 60, .Location = New Drawing.Point(12, 50)}
        Dim TextBox3 As New TextBox With {.Name = "TextBox3", .Width = 60, .Location = New Drawing.Point(12, 70)}
        Dim TextBox4 As New TextBox With {.Name = "TextBox4", .Width = 60, .Location = New Drawing.Point(12, 90)}
        ' add controls to form
        Me.Controls.AddRange({Label1, TextBox1, TextBox2, TextBox3, TextBox4})
        ' define char as fields separators and values iden
        Dim separators As Char() = {"{""W""M""S""F""}"}
        ' get fields
        Dim fields As String() = (
              From f As String In frame.Split(separators)
              Where f.Length > 0
            ).ToArray
        ' get textBoxes names
        Dim textBoxesNames() =
            (
                From Tbn As Object In Me.Controls
                Where Tbn.GetType.Name = "TextBox"
                Select CType(Tbn, TextBox).Name Order By Name
            ).ToArray
        ' assign values to textboxes
        For Index As Integer = 0 To textBoxesNames.Count - 1
            Me.Controls.Item(textBoxesNames(Index)).Text = fields(Index)
        Next
    End Sub
End Class

 

Regards! :-)  
PepLluis,

Easy or difficult, does not matter for VB or C# if you build your style

 

Pregunta:

Perdido en la recepción de datos.

A menudo recibo vuestras preguntas pidiéndome si os puedo aportar alguna idea para resolver casuísticas concretas. Lamentablemente por falta de tiempo no siempre puedo dedicar un post a cada una de vuestras inquietudes, sin embargo en ocasiones se plantean situaciones que se repiten y en caso de resolverlas considero que pueden ayudar a más personas con la misma inquietud y creo que este es el caso :

Pedro me escribe con lo siguiente: <Estoy encallado en un punto del cual me está costando salir… tengo un hardware especifico por el que el puerto serie me envía una trama conteniendo la información de varios valores separados por unos delimitadores>

La pregunta es: Como puedo detectar cuando recibo los indicadores, como distingo la letra que identifica el dato y finalmente como puedo leer únicamente su valor y colocarlo en un textbox. 

 Question :

I’m lost receiving RS232 data.

I often get questions asking me if I can contribute with any idea to solve concrete cases. Unfortunately due to lack of time I cannot always devote a post to each of your concerns, however sometimes there are situations that are repeated in case of solving them believe that they can help more people with the same concern and provably that may be the case:

Peter write me with the next question : < I am aground at a point which is costing me leave; I have an specific hardware with a serial port, that port sends me a frame containing information from several values separated by a few delimiters>

The question is: How I can detect the indicators positions, and how I can distinguish the letter that identifies the data and finally how can read only its value and send this to a textbox.

 

 Visual basic = 

Public Class Form1
 
    Private Sub Form1_Load(sender As System.Object, e As System.EventArgsHandles MyBase.Load
        Dim frame = "{W111}{M22}{F33}{S44}"
        Dim separators As Char() = {"{""W""M""S""F""}"}
        Dim fields As String() = (From f As String In frame.Split(separators) Where f.Length > 0).ToArray
        Dim textBoxesNames() = (From Tbn As Object In Me.Controls Where Tbn.GetType.Name = "TextBox" Select CType(Tbn, TextBox).Name Order By Name).ToArray
        For Index As Integer = 0 To textBoxesNames.Count - 1
            Me.Controls.Item(textBoxesNames(Index)).Text = fields(Index)
        Next
    End Sub
End Class

C# =

using System;
using System.Linq;
using System.Windows.Forms;
 
namespace WindowsFormsApplication1
{
    public partial class Form1 : Form
    {
        public Form1()
        {
            InitializeComponent();
        }
 
        private void Form1_Load(object sender, EventArgs e)
        {
            string frame = "{W111}{M22}{F33}{S44}";
            char[] separators = new char[] { '{''W''M''S''F''}' };
            string[] fields = (from string f in frame.Split(separators) where f.Length > 0 select f).ToArray();
            string[] textBoxesNames = (from Tbn in this.Controls.OfType<TextBox>() where Tbn.GetType().Name == "TextBox" orderby Tbn.Name select Tbn.Name).ToArray();
            for (int Index = 0; Index < textBoxesNames.Count(); Index++)
            {
                this.Controls[textBoxesNames[Index]].Text = fields[Index];
            }
        }
    }
}

Regards,
PepLluis,

Initialize SerialPorts in .Net microFramework

using Microsoft.SPOT;
using Microsoft.SPOT.Hardware;
using Supplier.NETMF.Hardware;
using Supplier.NETMF.Hardware.BoardModel;
using System.IO.Ports;
 
namespace Application1
{
    public class Program
    {
        static SerialPort MyCom; 
        public static void Main()
        {
            // 'Ports' name reference may be different for each manufacturer
            MyCom = new SerialPort(Ports.COM1,9600);
            while (true)
            {
                // Main loop
	       // write your code here
            }
        }
    }
}

Señales de control del puerto serie a través del ‘PinChanged’

Fernando, contestando a tu pregunta de cómo capturar los cambios en las señales de control de puerto serie, te dejo este ejemplo básico esperando te sea de utilidad.

    Dim MiSerialPort As New IO.Ports.SerialPort
 
    Sub Inicializando()
        MiSerialPort.Open()
        AddHandler MiSerialPort.PinChanged, AddressOf MiSerialPort_PinChanged
    End Sub
 
    Private Sub MiSerialPort_PinChanged(ByVal sender As System.ObjectByVal e As System.IO.Ports.SerialPinChangedEventArgs)
        Select Case e.EventType
            Case IO.Ports.SerialPinChange.CtsChanged
                ‘Clear To Send
                If MiSerialPort.CtsHolding Then
                    ‘CTS esta en ON
                Else
                    ‘CTS esta en OFF
                End If
            Case IO.Ports.SerialPinChange.DsrChanged
                ‘Data Set Ready
                If MiSerialPort.DsrHolding Then
                    ‘DSR esta en ON
                Else
                    ‘DSR esta en OFF
                End If
            Case IO.Ports.SerialPinChange.Ring
                ‘Ring
            Case IO.Ports.SerialPinChange.Break
                ‘Break
            Case IO.Ports.SerialPinChange.CDChanged
                ‘Carrier Detect
                If MiSerialPort.CDHolding Then
                    ‘…
                
Else
                    ‘….
                End If
        End Select
    End Sub

:-))
Pep Lluis,

Como puedo seleccionar el puerto COM que yo quiero?

Complementando els post ‘Serial Port – Enumeración & Disponibilidad’ y en respuesta a la pregunta:

 como puedo seleccionar el puerto COM que yo quiero? Es decir, con el programa que pusiste en tu blog, el de elegir los COM disponibles con el combobox, como hago para abrir el puerto que selecciono y empezar a enviar las tramas?”

    Private Sub Form1_Load() Handles MyBase.Load

        ‘…

        ‘…

        ‘…

        ‘…

        AddHandler ComboBox1.SelectedIndexChanged, AddressOf PuertoSeleccionado

    End Sub

 

    Sub PuertoSeleccionado()

        SerialPort1.PortName = ComboBox1.SelectedValue

        Refrescar_Estatus()

    End Sub

 

    Sub AbrirCerrar() Handles Button1.Click

        If SerialPort1.IsOpen Then

            SerialPort1.Close()

        Else

            SerialPort1.Open()

        End If

        Refrescar_Estatus()

    End Sub

 

    Sub Refrescar_Estatus()

        If SerialPort1.IsOpen Then

            Me.Button1.Text = SerialPort1.PortName + ” (Is Open)”

            Me.Button1.BackColor = Color.Green

        Else

            Me.Button1.Text = SerialPort1.PortName + ” (Is Closed)”

            Me.Button1.BackColor = Color.Red

        End If

    End Sub

 

Entre el telégrafo y el USB: El Puerto Serie

El día 16 de Febrero veremos en Second Nug como durante muchos años el puerto serie ha dado soporte a todo tipo de dispositivos: Mouse, Impresoras, Fax, sensores de todo tipo, terminales bancarios o incluso como pasarela a transmisores y protocolos como ZigBee, Bluetooth, etc. Las comunicaciones han supuesto siempre uno de los mayores retos para la evolución de los sistemas de información. Sin duda, el éxito de cualquier proceso depende en gran medida del nivel de interacción con lo que le rodea. Con tal herencia, argumentación e historia, ¿alguien se atreve a decir que el puerto serie esta extinto y cuando va a desaparecer?

Por eso, te proponemos que no te pierdas este recorrido que será transmitido bit a bit por Pep Lluis, MVP de Visual Basic, responsable de Informática industrial y miembro activo de Ineta (Latam y Europa) sobre algunas de las principales interfaces de comunicación y, si el tiempo lo permite, un pequeño laboratorio de cómo interactuar con una electrónica específica y el PC.

Como comunicarme con una Bascula

‘Respondiendo a la pregunta :

‘ ¿Cómo puedo establecer comunicación con una bascula que tiene un RS232?

‘En este ejemplo podremos ver diferentes formas de enviar una petición

‘ a una bascula, simulando que nos responde al enviar el carácter ‘P’

‘ y visualizar su respuesta en una etiqueta llamada ‘Recibidos’

 

Public Class Form1

    ‘Constructores

    Private BasculaCom As New System.IO.Ports.SerialPort        ‘Puerto conectado a la báscula

    Private Recibidos As New Label                              ‘Etiqueta para visualizar la recepción

    Private Peticion As New Button                              ‘Botón para disparar el envío

    Delegate Sub MostrarRecepcion(ByVal Texto As String)        ‘Delegado para asignar el valor recibido

 

    Private Sub Form1_Load(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles MyBase.Load

        ‘ Ajustar los parámetros de comunicaciones

        ‘ adaptándolos a las especificaciones o configuración

        ‘ de la bascula en concreto.

        BasculaCom.PortName = “COM1”                            ‘Conectaremos la bascula al puerto COM1

        BasculaCom.BaudRate = 9600                              ‘La velocidad de intercambio será de 9600

        BasculaCom.Parity = IO.Ports.Parity.None                ‘No verificaremos la paridad

        BasculaCom.StopBits = 1                                 ‘Final de Byte con 1 bit de Stop

        BasculaCom.Open()                                       ‘Abrir las comunicaciones con la bascula

       

        ‘ marco

        Dim marcoDGV = New FlowLayoutPanel                      ‘Conformar los controles del form

        marcoDGV.BorderStyle = BorderStyle.Fixed3D

        marcoDGV.Width = Me.Width

        marcoDGV.Height = Me.Height

        ‘ Añadir el marco con el Label y el Buton

        Recibidos.Text = “-“

        Peticion.Text = “Enviar p”

        marcoDGV.Controls.AddRange(New Control() {Peticion, Recibidos})

        Me.Controls.Add(marcoDGV)

 

        ‘Dirigir los eventos a las funciones para procesarlos

        AddHandler Peticion.Click, AddressOf EnviarUnaP         ‘Ejecución de ‘EnviarUnaP’ al pulsar el boton

        AddHandler BasculaCom.DataReceived, AddressOf Recibir   ‘Ejecución de ‘Recibir’ al recibir respuesta de la bascula

    End Sub

   

    ‘ Enviar una solicitud a la bascula

    Sub EnviarUnaP()

        ‘enviar una p

        BasculaCom.Write(“P”)

        ‘tambien puede ver/probar…

        BasculaCom.WriteLine(“P”)

        BasculaCom.Write(Chr(80))

        ‘… etc

    End Sub

 

    ‘al recibir de la bascula los bytesToRead indicara

    ‘un valor superior a 0, indicando el numero de caracteres

    Sub Recibir()

        ‘Dim NumeroDeBytesEnBuffer As Integer = BasculaCom.BytesToRead

        MostrarRececibidos(BasculaCom.ReadExisting)

    End Sub

   

    ‘ Mostrar los bytes recibidos en el Label recibidos

    Private Sub MostrarRececibidos(ByVal [texto] As String)

        If Recibidos.InvokeRequired Then

            Dim delegado As New MostrarRecepcion(AddressOf MostrarRececibidos)

            Me.Invoke(delegado, New Object() {[texto]})

        Else

            Me.Recibidos.Text = [texto]

        End If

    End Sub

 

End Class

 

Se puede cambiar la velocidad del puerto serie?

‘ Repondiendo a la pregunta sobre si
‘ Se puede cambiar la velocidad de Transmsion/Recepcion dinamicamente

‘..     Dim MiPuerto As New System.IO.Ports.SerialPort
‘..     MiPuerto = My.Computer.Ports.OpenSerialPort(“COM1”)

‘En este ejemplo enviamos una trama “Hola” a una velocidad diferente
‘cada vez que invoquemos el procedimiento EnviarTrama

‘Evidentemente podeis asociarlo a un combo, de manera que utilice la
‘velocidad asociada a la selección del mismo

… Sub EnviarTrama …
        Select Case MiPuerto.BaudRate
            Case 19200
                MiPuerto.BaudRate = 9600
            Case 9600
                MiPuerto.BaudRate = 4800
            Case 9600
                MiPuerto.BaudRate = 2400
            Case Else
                MiPuerto.BaudRate = 19200
        End Select
        MiPuerto.WriteLine(“Hola… enviando a :” + MiPuerto.BaudRate.ToString)

Saludos;
Pep Lluis,

Serial Port – Enumeración & Disponibilidad – Tambien en C#

 

         Saber sobre la disponibilidad de nuestros puertos serie antes de su selección en un combobox.

  How to know about availability of our computer serial ports before select one from a combo box.

A menudo las aplicaciones que requieren seleccionar un dispositivo antes de efectuar algún tipo de comunicacion, no ofrecen ninguna información adicional sobre el estado del dispositivo. Sobre todo si hablamos del puerto serie, normalmente nos ofrecen una simple enumeración de los COM. Esto último es el causante de que la aplicación nos permita seleccionar un puerto que en ocasiones no existe o está siendo usado por otro programa.

Os propongo una idea con la intención de mejorar y facilitar la selección de este tipo de dispositivos en nuestras aplicaciones.

Básicamente se trata de enumerar en un ‘ComboBox’ personalizado los puertos existentes en nuestro equipo, utilizando el mandato :

My.Computer.Ports.SerialPortNames.ToArray

En el momento de la inicialización del ‘combobox’ asignaremos el evento de ‘DrawItem’ a la función que enriquecerá el aspecto, añadiendo al nombre un rectángulo coloreado y el texto correspondiente a la disponibilidad del puerto.

AddHandler ComboBox1.DrawItem, AddressOf cmbo_SerialPorts_Status

No dudéis en contactar conmigo si necesitáis aclarar o necesitáis entender alguna parte del código.

Para poder darle mayor difusión los comentarios del código están en inglés, aunque si os parece oportuno y necesario puedo posteároslo también en español.

Sometimes our communications applications are required to select any type of external device, and normally these applications are not giving any extra information about their availability. This is the case when talk around serial ports, normally when select the port only have a simple enumeration of COM’s, this may be confusing at time leaving at users selecting inexistent ports or ports that simply are already in use.

With this sample, you can improve and make easy these device selections in our applications.

The main think is enumerate serial port inside our customized ‘ComboBox’, using :

My.Computer.Ports.SerialPortNames.ToArray

After when initialize our combo only need assign ‘DrawItem’ event to function with our personalized combo draw,

AddHandler ComboBox1.DrawItem, AddressOf cmbo_SerialPorts_Status

This function are adding red rectangle and “busy” text when no have availability, and green rectangle and “available” text when the port is free.

Please no doubt in contact with me if you need any other explanation or opinion about this.

 

 SerialEnum_Es

SerialEnum_en 

 

public partial class Form1 : Form
    {
        //Enumerate Serial Ports on Machine
        //Get Serial Port availability
        String[] Puertos = System.IO.Ports.SerialPort.GetPortNames();

 

        public Form1()

        {

            InitializeComponent();

        }

 

        private void Form1_Load(object sender, EventArgs e)

        {

            this.comboBox1.DrawMode = DrawMode.OwnerDrawVariable;       //seleccionar mi propio modo de arrastre

            this.comboBox1.DropDownStyle = ComboBoxStyle.DropDownList;  //aspecto al men desplegable

            this.comboBox1.DataSource = Puertos;                        //puertos serie disponibles

            this.comboBox1.TabIndex = 0;                                //seleccione en primer lugar tabIndex

        }

 

       

        private void comboBox1_DrawItem_1(object sender, DrawItemEventArgs CmboItem)

        {

            // Dibuja el fondo del item.

            CmboItem.DrawBackground();

            // Los valores por defecto si el puerto est disponible.

            string status = “Disponible”;

            SolidBrush brush = new SolidBrush(Color.Green);

            System.Drawing.Font font = this.Font;

            Brush fontbrush = Brushes.Black;

            Rectangle rectangle = new Rectangle(2, CmboItem.Bounds.Top + 2, CmboItem.Bounds.Height – 4, CmboItem.Bounds.Height – 4);

            // Comprobar disponibilidad del puerto

            try

            {

                // Si abre y cierra los puertos sin excepcin.

                // dibuja el item con la fuente por defecto y rectngulo verde.

                System.IO.Ports.SerialPort PortTest = new System.IO.Ports.SerialPort();

                PortTest.PortName = Puertos[CmboItem.Index].ToString();

                PortTest.Open();

                PortTest.Close();

            }

            catch (Exception ex)

            {

                // Si el puerto no est disponible

                // dibuja el item con la fuente cursiva y tachado y rectngulo rojo

                brush = new SolidBrush(Color.Red);

                status = “En Uso”;

                font = new Font(FontFamily.GenericSansSerif, this.Font.Size, FontStyle.Italic ^ FontStyle.Strikeout);

                fontbrush = Brushes.DimGray;

            }

            // llenar item combo con rectangulo.

            CmboItem.Graphics.FillRectangle(brush, rectangle);

            // escribir el texto con la condicin actual del puerto de este item.

            CmboItem.Graphics.DrawString(Puertos[CmboItem.Index].ToString() + ” – “ + status, font, fontbrush, new RectangleF(CmboItem.Bounds.X + rectangle.Width, CmboItem.Bounds.Y, CmboItem.Bounds.Width, CmboItem.Bounds.Height));

            // dibujar foco del rectngulo cuando el ratn est sobre un item.

            CmboItem.DrawFocusRectangle();

        }

    }