Foros Club Delphi

Foros Club Delphi (https://www.clubdelphi.com/foros/index.php)
-   .NET (https://www.clubdelphi.com/foros/forumdisplay.php?f=17)
-   -   Recibir dos tramas por RS232 diferentes. (https://www.clubdelphi.com/foros/showthread.php?t=96498)

REHome 24-11-2023 06:47:35

Recibir dos tramas por RS232 diferentes.
 
Hola:

Puedo recibir tramas de bytes por el puerto serie, una es esta si envía este comando:
Código:

serialPort1.Write("B\r");
#I230.3O230.0L007B100V25.7F50.2H50.2R0080S„€ˆ„À

y la otra es esta si envías este otro comando diferente:
Código:

serialPort1.Write("X72\r");
#2000,1400,230,45.0,55.0,8.6

En la primera tengo el código hecho en Windows Form y funciona.
Código:

using System;
using System.IO.Ports;
using System.Threading;
using System.Windows.Forms;

namespace Termite_SAI_04
{
    public partial class Form1 : Form
    {
        private delegate void DelegadoAcceso(String accion);
        public Form1()
        {
            InitializeComponent();
        }

        private void button_Ver_datos_Click(object sender, EventArgs e)
        {
            serialPort1.Write("B\r");
        }

        private void button_Ver_Tabla_Click(object sender, EventArgs e)
        {
            serialPort1.Write("X72\r");
        }

        private void Form1_Load(object sender, EventArgs e)
        {
            try
            {
                serialPort1 = new SerialPort("COM3", 2400, Parity.None, 8, StopBits.One);
                serialPort1.Handshake = Handshake.None;
                serialPort1.DataReceived += new SerialDataReceivedEventHandler(sp_DataReceived);
                serialPort1.ReadTimeout = 500;
                serialPort1.WriteTimeout = 500;
                serialPort1.Open();
                serialPort1.Write("B\r");
            }
            catch (Exception ex)
            {
                MessageBox.Show(ex.Message);
            }
        }

        void sp_DataReceived(object sender, SerialDataReceivedEventArgs e)
        {
            if (this.Enabled == true)
            {
                Thread.Sleep(500);
                string entrada = serialPort1.ReadExisting();
                this.BeginInvoke(new DelegadoAcceso(si_DataReceived), new object[] { entrada });
                //serialPort1.Write("B\r"); // Envía comando.
            }
        }

        private void si_DataReceived(string accion)
        {
            try
            {
                char[] separadores = { '#', 'I', 'O', 'L', 'B', 'V', 'F', 'H', 'R', 'S' };

                string[] salida = accion.Split(separadores, StringSplitOptions.RemoveEmptyEntries);

                label_I.Text = salida[0] + " Vac";
                label_O.Text = salida[1] + " Vac";
                label_L.Text = salida[2].TrimStart('0') + " %"; // Quita los ceros de la izquierda.
                label_B.Text = salida[3] + " %";
                label_V.Text = salida[4] + " Vdc";
                label_F.Text = salida[5].PadRight(5, '0') + " Hz"; // Añade ceros a la derecha.
                label_H.Text = salida[6].PadRight(5, '0') + " Hz";

                // Convertir variable tipo string a tipo int, es decir, la variable tipo string "salida[7]"
                // se convierte en tipo int "resultadoSalida7".
                int resultadoSalida7 = Int32.Parse(salida[7]);

                // ¿Es igual a 1 minuto?
                if ((resultadoSalida7 % 60) == 1)
                {
                    label_R.Text = resultadoSalida7 / 60 + " hora y " + resultadoSalida7 % 60 + " minuto.";
                }

                // ¿Es mayor a 60 segundos o 1 minuto?
                if ((resultadoSalida7 % 60) > 1)
                {
                    label_R.Text = resultadoSalida7 / 60 + " hora y " + resultadoSalida7 % 60 + " minutos.";
                }

                // ¿Es igual a 60 segundos o 1 minuto?
                if ((resultadoSalida7 % 60) == 0)
                {
                    label_R.Text = resultadoSalida7 / 60 + " hora y " + resultadoSalida7 % 60 + " minutos.";
                }
            }

            catch (IndexOutOfRangeException ex)
            {
                Console.Write("Índice fuera de los límites de la matriz.");
                MessageBox.Show(ex.Message);
            }

            catch (FormatException ex)
            {
                Console.Write("La cadena de entrada no tiene el formato correcto.");
                MessageBox.Show(ex.Message, "Error");
            }
        }
    }
}

Aquí abajo es el trozo de códigos para leer esa trama que no se donde ponerlo.
Código:

            char[] separadores2 = { '#', ',' };

            string[] salida2 = entrada2.Split(separadores2, StringSplitOptions.RemoveEmptyEntries);

            label_Resultado_valores_nonimales_de_alimentacion.Text = salida2[0] + " VA / " + salida2[1] + " W";
            label_Resultado_voltaje_nominal.Text = salida2[2] + " Vac";
            label_Resultado_corriente_nominal.Text = salida2[5] + " A";
            label_Resultado_valores_nominales_de_frecuencia.Text = salida2[3] + " ~ " + salida2[4] + " Hz";

¿Alguna ayuda?

Gracias.

tsk 24-11-2023 15:00:31

Ve lo que te puse en el otro post sobre los diccionarios, ahí tienes la respuesta de que es lo que debes de hacer, tan sólo crea un variable donde puedas tener guardado el último comando que acabas de enviar.

Si quieres tener funciones separadas para cada caso, te serviría algo parecido a esto.

Código PHP:

IDictionary<string,Func<string,string[]>> commands = new Dictionary<string,Func<string,string[]>>(); 

Después añades cada uno de tus comandos de la siguiente forma

Código PHP:

commands.Add("B\r",funcion_que_trata_el_caso_de_B);
commands.Add("X72\r",funcion_que_trata_elcaso_de_X72); 

Entonces, dentro de tu función si_DataReceived simplemente colocas algo como

Código PHP:

private void si_DataReceived(string accion)
{
    
commands[current_command](accion);



REHome 26-11-2023 13:06:44

Gracias, lo tomaré en cuenta.

REHome 26-11-2023 16:21:03

Antes que nada.

Me he dado cuenta que a veces me falla el dispositivo SAI.

Al enviar este comando B<cr>, o lo que es lo mismo:
Código:

        private void button_Ver_datos_Click_1(object sender, EventArgs e)
        {
            serialPort1.Write("B\r");
        }

Recibo este dato:
Código:

#I229.6O230.0L006B100V25.6F50.2H50.2R0080S„€€„À
En el cual al fijarme bien, siempre que recibo una trama de Bytes siempre empieza con # y acaba en <cr>, retorno de carro para que sepa el programa que ha finalizado la trama.

Con razón que con el tiempo, siempre me da resultados malos o raros o fuera de límite como me sale el error.


La franja horaria es GMT +2. Ahora son las 03:18:12.

Powered by vBulletin® Version 3.6.8
Copyright ©2000 - 2024, Jelsoft Enterprises Ltd.
Traducción al castellano por el equipo de moderadores del Club Delphi