C sharp - No me unciona con Windows Form y otros programas externos si

 
Vista:
sin imagen de perfil
Val: 168
Bronce
Ha mantenido su posición en C sharp (en relación al último mes)
Gráfica de C sharp

No me unciona con Windows Form y otros programas externos si

Publicado por Meta (138 intervenciones) el 15/03/2025 20:39:14
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

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

Código C#:
Captura-de-pantalla-2025-03-15-193131

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

Con RealTerm, Putty y otros, funciona bien.

¿En qué estoy fallando?

Un cordial saludo y muchas gracias por su tiempo.
Valora esta pregunta
Me gusta: Está pregunta es útil y esta claraNo me gusta: Está pregunta no esta clara o no es útil
0
Responder