elhacker.net cabecera Bienvenido(a), Visitante. Por favor Ingresar o Registrarse
¿Perdiste tu email de activación?.


Tema destacado: Guía actualizada para evitar que un ransomware ataque tu empresa


+  Foro de elhacker.net
|-+  Programación
| |-+  Programación General
| | |-+  .NET (C#, VB.NET, ASP) (Moderador: kub0x)
| | | |-+  Leer bien los datos recibidos.
0 Usuarios y 1 Visitante están viendo este tema.
Páginas: [1] Ir Abajo Respuesta Imprimir
Autor Tema: Leer bien los datos recibidos.  (Leído 724 veces)
Meta


Desconectado Desconectado

Mensajes: 3.502



Ver Perfil WWW
Leer bien los datos recibidos.
« en: 15 Marzo 2025, 20:37 pm »

Buenas comper@s:

Uso comunicación por el puerto serie /USB con Arduino y RealTerm para probar y funciona.

Envío el comando tal cual, por ejemplo, B\r desde RealTerm o PuTTY, y recibe el comando exactamente tal cual quiero desde Arduino:

#Comando B recibido\r


Ver zoom.

El problema de C# .net 8.0 usando Windows Form, no lee bien y llevo horas y horas. En mi caso, en vez de usar RealTerm, quiero usar el mio propio hecho con C#. Al enviar comandos como en este ejemplo, B\r a Arduino, lo lee bien, el problema es al devolver los datos que si lo devuelve y bien y C# no lo interpreta bien.

O no recibe los datos, lo recibes a medias, o entre medios hace un salto de línea por la cara, hace cosas muy raras.

Código Arduino:
Código
  1. #include <LiquidCrystal.h>
  2.  
  3. // Inicializa la librería con sus pines indicados
  4. LiquidCrystal lcd(8, NULL, 9, 4, 5, 6, 7);
  5.  
  6. // Definir el pin para la luz de fondo y el LED
  7. const byte LuzFondo = 10;
  8. const byte Led = 13;
  9.  
  10. // Variable para almacenar el comando recibido
  11. String comando = "";  // Asegúrate de declarar la variable de tipo String
  12. char caracter;
  13.  
  14. void setup()
  15. {
  16.  // Inicializa el LCD
  17.  lcd.begin(16, 2);  
  18.  lcd.print("Esperando comando");
  19.  
  20.  // Inicia la comunicación serial
  21.  Serial.begin(2400);
  22.  delay(1000);  // Espera para asegurar que el LCD se inicialice
  23. }
  24.  
  25. void loop()
  26. {
  27.  // Mientras haya datos disponibles en el puerto serie, los leemos carácter a carácter
  28.  while (Serial.available() > 0)
  29.  {
  30.    caracter = Serial.read();  // Leer un carácter del puerto serie
  31.    comando.concat(caracter);  // Concatenar el carácter al comando
  32.    delay(10);  // Pequeña espera para no saturar el canal serie
  33.  }
  34.  
  35.  // Verificamos si el comando es "B\r" o "X72\r" y respondemos en consecuencia
  36.  if (comando == "B\r")
  37.  {
  38.    digitalWrite(Led, HIGH);  // Enciende el Led 13
  39.    Serial.write("#Comando B recibido\r");  // Envía el mensaje de vuelta a C#
  40.    lcd.setCursor(0, 0);
  41.    lcd.print("Comando B       ");  // Muestra en el LCD
  42.  }
  43.  else if (comando == "X72\r")
  44.  {
  45.    digitalWrite(Led, LOW);  // Apaga el Led 13
  46.    Serial.write("#Comando X72 recibido\r");  // Envía el mensaje de vuelta a C#
  47.    lcd.setCursor(0, 0);
  48.    lcd.print("Comando X72     ");  // Muestra en el LCD
  49.  }
  50.  else if (comando == "X5\r")
  51.  {
  52.    digitalWrite(Led, LOW);  // Apaga el Led 13
  53.    Serial.write("#Comando X5 recibido\r");  // Envía el mensaje de vuelta a C#
  54.    lcd.setCursor(0, 0);
  55.    lcd.print("Comando X5      ");  // Muestra en el LCD
  56.  }
  57.  
  58.  // Limpiamos la cadena de comando para volver a recibir el siguiente comando
  59.  comando = "";  
  60. }
  61.  

Código C#:


Código
  1. using System.Text;
  2. using System.IO.Ports;
  3.  
  4. namespace SAI_Arduino_LCD_01
  5. {
  6.    public partial class Form1 : Form
  7.    {
  8.        private SerialPort puertoSerie;
  9.        private string lastReceivedData = "";  // Variable para guardar el último dato recibido
  10.  
  11.        public Form1()
  12.        {
  13.            InitializeComponent();
  14.            InicializarPuertoSerie();
  15.        }
  16.  
  17.        // Método para inicializar la configuración del puerto serie
  18.        private void InicializarPuertoSerie()
  19.        {
  20.            puertoSerie = new SerialPort()
  21.            {
  22.                BaudRate = 2400,
  23.                Parity = Parity.None,                               // Esquema para comprobar la paridad de cada byte recibido.
  24.                StopBits = StopBits.One,                            // Número de bits de parada por byte.
  25.                DataBits = 8,                                       // Número de bits de datos por byte.
  26.                Handshake = Handshake.None,                         // Protocolo de establecimiento.
  27.                Encoding = Encoding.GetEncoding(28591),             // Codificación.
  28.                DtrEnable = true,                                   // Línea de terminal de datos.
  29.                RtsEnable = true,                                   // Línea de solicitud.
  30.                ReadTimeout = 500,                                  // Tiempo de espera de lectura en ms.
  31.                WriteTimeout = 500,                                 // Tiempo de espera de escritura en ms.
  32.                DiscardNull = false,                                // Descartar bytes nulos recibidos.
  33.                ParityReplace = 63,                                 // Reemplaza los bytes recibidos con errores de paridad.
  34.                ReadBufferSize = 4096,                              // Tamaño del búfer de lectura en bytes.
  35.                WriteBufferSize = 2018,                             // Tamaño del búfer de escritura en bytes.
  36.                ReceivedBytesThreshold = 1                          // Número de bytes que se necesitan.
  37.            };
  38.  
  39.            puertoSerie.DataReceived += PuertoSerie_DataReceived; // Suscribimos al evento
  40.        }
  41.  
  42.        // Evento que se activa cuando se reciben datos del puerto serie
  43.        private void PuertoSerie_DataReceived(object sender, SerialDataReceivedEventArgs e)
  44.        {
  45.            try
  46.            {
  47.                // Verificamos si el puerto está abierto
  48.                if (!puertoSerie.IsOpen)
  49.                {
  50.                    ActualizarRichTextBox("Puerto no abierto.");
  51.                    return;
  52.                }
  53.  
  54.                // Leer todos los datos disponibles hasta que no haya más
  55.                string data = puertoSerie.ReadExisting();  // Usamos ReadExisting para leer todo
  56.  
  57.                // Solo actualizar si los datos recibidos son diferentes de los anteriores
  58.                if (!string.IsNullOrEmpty(data) && data != lastReceivedData)
  59.                {
  60.                    lastReceivedData = data; // Actualizar el último dato recibido
  61.                    ActualizarRichTextBox(data);  // Mostrar los datos recibidos
  62.                }
  63.            }
  64.            catch (TimeoutException)
  65.            {
  66.                // Si hay un Timeout, podemos ignorar y no mostrar nada
  67.            }
  68.            catch (Exception ex)
  69.            {
  70.                ActualizarRichTextBox("Error: " + ex.Message + "\r\n");
  71.            }
  72.        }
  73.  
  74.        // Método para actualizar el RichTextBox de manera segura desde cualquier hilo
  75.        private void ActualizarRichTextBox(string mensaje)
  76.        {
  77.            if (InvokeRequired)
  78.            {
  79.                Invoke(new Action<string>(ActualizarRichTextBox), mensaje);
  80.            }
  81.            else
  82.            {
  83.                richTextBox1.AppendText(mensaje + "\r\n");
  84.            }
  85.        }
  86.  
  87.        // Método para enviar un comando por el puerto serie
  88.        private void EnviarComando(string comando)
  89.        {
  90.            try
  91.            {
  92.                // Verificar si el puerto está abierto
  93.                if (!puertoSerie.IsOpen)
  94.                {
  95.                    puertoSerie.Open();
  96.                }
  97.  
  98.                // Enviar cada carácter del comando como valor ASCII
  99.                foreach (char c in comando)
  100.                {
  101.                    puertoSerie.Write(new byte[] { (byte)c }, 0, 1);  // Escribir un byte correspondiente al carácter ASCII
  102.                }
  103.  
  104.                // Enviar el retorno de carro \r como un byte
  105.                puertoSerie.Write(new byte[] { 13 }, 0, 1);  // ASCII de '\r' es 13
  106.  
  107.                // Esperar un breve tiempo para asegurar que Arduino procese el comando antes de continuar
  108.                Thread.Sleep(200); // Ajusta el tiempo según sea necesario
  109.  
  110.                ActualizarRichTextBox("Enviado: " + comando + "\r\n");
  111.            }
  112.            catch (UnauthorizedAccessException ex)
  113.            {
  114.                MessageBox.Show("El puerto COM está en uso por otro proceso. Error: " + ex.Message);
  115.            }
  116.            catch (Exception ex)
  117.            {
  118.                MessageBox.Show("Error al intentar enviar el comando: " + ex.Message);
  119.            }
  120.        }
  121.  
  122.        // Cerrar el puerto de manera segura cuando se cierre el formulario
  123.        private void Form1_FormClosing(object sender, FormClosingEventArgs e)
  124.        {
  125.            if (puertoSerie.IsOpen)
  126.            {
  127.                try
  128.                {
  129.                    puertoSerie.Close();
  130.                }
  131.                catch (Exception ex)
  132.                {
  133.                    MessageBox.Show("Error al cerrar el puerto: " + ex.Message);
  134.                }
  135.            }
  136.        }
  137.  
  138.        private void Form1_Load(object sender, EventArgs e)
  139.        {
  140.            try
  141.            {
  142.                string[] puertos = SerialPort.GetPortNames();
  143.                comboBox_Puertos.Items.AddRange(puertos);  // Llenar el ComboBox con los puertos disponibles
  144.  
  145.                if (comboBox_Puertos.Items.Count > 0)
  146.                {
  147.                    comboBox_Puertos.SelectedIndex = 0; // Seleccionar el primer puerto automáticamente
  148.                }
  149.            }
  150.            catch (Exception ex)
  151.            {
  152.                MessageBox.Show("Error al cargar los puertos: " + ex.Message);
  153.            }
  154.        }
  155.  
  156.        // Método para conectar con el puerto seleccionado
  157.        private void btnConectar_Click(object sender, EventArgs e)
  158.        {
  159.            if (comboBox_Puertos.SelectedItem == null)
  160.            {
  161.                MessageBox.Show("Por favor, selecciona un puerto COM antes de intentar conectar.");
  162.                return;
  163.            }
  164.  
  165.            string puertoSeleccionado = comboBox_Puertos.SelectedItem.ToString();
  166.            puertoSerie.PortName = puertoSeleccionado;  // Configurar el puerto
  167.  
  168.            try
  169.            {
  170.                // Verificar si el puerto ya está abierto y cerrarlo si es necesario
  171.                if (puertoSerie.IsOpen)
  172.                {
  173.                    puertoSerie.Close();
  174.                    ActualizarRichTextBox("Puerto cerrado previamente.\r\n");
  175.                }
  176.  
  177.                // Abrir el puerto
  178.                puertoSerie.Open();
  179.                ActualizarRichTextBox("Conexión exitosa con " + puertoSeleccionado + "\r\n");
  180.            }
  181.            catch (Exception ex)
  182.            {
  183.                MessageBox.Show("Error al abrir el puerto: " + ex.Message);
  184.            }
  185.        }
  186.  
  187.        // Métodos de comando
  188.        private void button_Comando_B_Click(object sender, EventArgs e) => EnviarComando("B");
  189.        private void button_Comando_X72_Click(object sender, EventArgs e) => EnviarComando("X72");
  190.        private void button_Comando_X5_Click(object sender, EventArgs e) => EnviarComando("X5");
  191.    }
  192. }
  193.  

Con RealTerm, Putty y otros, funciona bien.

¿En qué estoy fallando?

Un cordial saludo y muchas gracias por su tiempo.


En línea

Páginas: [1] Ir Arriba Respuesta Imprimir 

Ir a:  

WAP2 - Aviso Legal - Powered by SMF 1.1.21 | SMF © 2006-2008, Simple Machines