none
Causa del error. RRS feed

  • Pregunta

  • Hola:

    Tengo este código hecho, en el cual recibe valores por cada 0.1 segundos datos entre 0 a 1023 como rango. En Arduino IDE 1.6.9 me funciona bien los datos que muestra.

    Código fuente de Arduino:

    int valorPot=0;
    
    void setup()
    { 
      Serial.begin(115200); 
    }
    
    void loop()
    {
         valorPot=analogRead(2);
         Serial.println(valorPot);
         delay(100); // 0.1 segundos.
    }

    En el WindowsForm de Visual C# 2015 he pue4sto un label y ahí demuestra los valores del 0 al 1023 que recibe cada dos por tres. En este caso 550 como puedes ver en la captura abajo.

    Código fuente e C# es este aquí abajo.

    using System;
    using System.Collections.Generic;
    using System.ComponentModel;
    using System.Data;
    using System.Drawing;
    using System.Linq;
    using System.Text;
    using System.Threading.Tasks;
    using System.Windows.Forms;
    
    using System.IO.Ports; // No olvidar.
    
    namespace Arduino_In_Analogico_prueba_02
    {
        public partial class Form1 : Form
        {
            // Utilizaremos un string como buffer de recepción.
            string Recibidos = "";
            string Recibidos_Correcto = "";
            int Variar_este_valor = 0;
    
            public Form1()
            {
                InitializeComponent();
    
                if (!serialPort1.IsOpen)
                {
                    try
                    {
                        serialPort1.Open(); // Abre el puerto.
                    }
                    catch (System.Exception ex)
                    {
                        MessageBox.Show(ex.ToString());
                    }
    
                    serialPort1.DataReceived += new SerialDataReceivedEventHandler(serialPort1_DataReceived);
                }
            }
    
            // Al recibir datos.
            private void serialPort1_DataReceived(object sender, SerialDataReceivedEventArgs e)
            {
                Recibidos = serialPort1.ReadExisting(); // Entrada de datos por el puerto serie.
                Recibidos_Correcto = Recibidos.Replace("\n\r", "").Replace("\n","").Replace("\r",""); // Delimitador. Anular \n y \r.
    
                Invoke(new EventHandler(Actualizar));
            }
    
            // Procesar los datos recibidos en el bufer y extraer tramas completas.
            private void Actualizar(object sender, EventArgs e)
            {
                try
                {
                    Variar_este_valor = Convert.ToInt32(Recibidos_Correcto); // Convertir string a int.
                }
    
                catch (FormatException)
                {
                    // La cadena de entrada no tiene el formato correcto.
                    return;
                }
    
                label1.Text = Recibidos_Correcto.ToString(); // Mostrar resultado en un label y convertirlo a string.
            }
        }
    }
    

    La parte que no entiendo es la de catch, tuve que hacerlo porque me da problemas a la hora e leer, solo que parpadea el label cada vez que salta el try catch.

    Quizás el código de C# desde el principio se pueda hacer de otra manera, no de esta forma, es decir, quiero hacerlo lo más eficiente, no el que he elegido.

    ¿Alguna sugerencia?

    Saludos.


    http://electronica-pic.blogspot.com

    sábado, 18 de junio de 2016 8:52

Respuestas

  • Tu rutina del arduino lee un voltaje cada 0.1 seg, lo digitaliza, convierte el valor del sample a un texto y te lo envía al puerto serial de tu pc.

    Si el tipo te manda "819\r\n", vos podés estar recibiéndolo en 2 eventos data received, por ejemplo "81", "9\r\n".

    Estás recolectando mal la data de tu clase serialport.

    Vos tenés que poner un loop en tu evento data received, ir leyendo char por char, acumular todo lo que no sea '\r' o '\n', y cuando detectas el CR seguido del LF, muestras la data que acumulaste y luego limpias el acumulador y sigues con el loop.

    Dicho sea de paso, todas esas conversiones son innecesarias. El arduino te envía texto, y lo que muestras es texto. Puedes tranquilamente quitar ese try/catch para el tipo FormatException.

    • Marcado como respuesta Metaconta lunes, 4 de julio de 2016 16:45
    sábado, 18 de junio de 2016 12:34
  • Pegas un mensaje de 100 líneas y no pones lo más importante. 

    ¿Cuál es el dato, cuál es el texto, que no puedes convertir a Int32?

    Antes de invocar a Actualizar, o antes de invocar a Convert  ¿cuál es el texto en Recibidos_Correcto?

    Fijate que 0.1seg, para tu pc, significan cientos de millones de instrucciones procesadas. Tu programa podría haber procesado 100 eventos data received de ser necesario. Podrías estar recibiendo un fragmento de texto de 2 char "\r\n", y quedarte con una cadena vacía que obviamente es inconvertible...

    ---

    Además, quitas el try/catch y dejas el convert. No es lo que yo te propuse. Si quitas el convert, que es completamente innecesario, puedes prescindir del try/catch.

    • Editado walter_5 lunes, 20 de junio de 2016 22:18
    • Marcado como respuesta Metaconta lunes, 4 de julio de 2016 16:45
    lunes, 20 de junio de 2016 22:12
  • Hola Metaconta

    Al split añadele esta opción para eliminar los vacios.

    string[] Palabras = Recibidos.Split(Delimitador, StringSplitOptions.RemoveEmptyEntries);

    Y luego sigues mostrando la variavle Recibidos despues de tratar los datos tiendrias que mostrar Comandos

    foreach (string Comandos in Palabras)
                {
                    label1.Text = Comandos.; // No es necesario ToString() comandos ya es string.
                }

    Un saludo.


    Es de buena educación dar las gracias cuando te ayudan, si alguna respuesta te ha sido de utilidad agradécelo marcandola como útil.
    Blog


    • Editado Rodripelto lunes, 27 de junio de 2016 6:35
    • Marcado como respuesta Metaconta lunes, 4 de julio de 2016 16:45
    lunes, 27 de junio de 2016 6:33
  • Hola,

    Por lo que cuentas yo diria que la trama de datos en el puerto no es costante, sin estar ahí es dificil saber el motivo, puede ser incluso que el aurdino de vez en cuando envíe mal los datos, con paciencia y puntos de interrupción tendrias que analizar los datos que recibes para poder tomar una decisión de como tratarlos, siento no poder ayudarte mas pero a distancia es complicado.

    Un saludo.

    Es de buena educación dar las gracias cuando te ayudan, si alguna respuesta te ha sido de utilidad agradécelo marcandola como útil.
    Blog

    • Marcado como respuesta Metaconta lunes, 4 de julio de 2016 16:45
    miércoles, 29 de junio de 2016 7:13

Todas las respuestas

  • Tu rutina del arduino lee un voltaje cada 0.1 seg, lo digitaliza, convierte el valor del sample a un texto y te lo envía al puerto serial de tu pc.

    Si el tipo te manda "819\r\n", vos podés estar recibiéndolo en 2 eventos data received, por ejemplo "81", "9\r\n".

    Estás recolectando mal la data de tu clase serialport.

    Vos tenés que poner un loop en tu evento data received, ir leyendo char por char, acumular todo lo que no sea '\r' o '\n', y cuando detectas el CR seguido del LF, muestras la data que acumulaste y luego limpias el acumulador y sigues con el loop.

    Dicho sea de paso, todas esas conversiones son innecesarias. El arduino te envía texto, y lo que muestras es texto. Puedes tranquilamente quitar ese try/catch para el tipo FormatException.

    • Marcado como respuesta Metaconta lunes, 4 de julio de 2016 16:45
    sábado, 18 de junio de 2016 12:34
  • Tu rutina del arduino lee un voltaje cada 0.1 seg, lo digitaliza, convierte el valor del sample a un texto y te lo envía al puerto serial de tu pc.

    Si el tipo te manda "819\r\n", vos podés estar recibiéndolo en 2 eventos data received, por ejemplo "81", "9\r\n".

    Estás recolectando mal la data de tu clase serialport.

    Vos tenés que poner un loop en tu evento data received, ir leyendo char por char, acumular todo lo que no sea '\r' o '\n', y cuando detectas el CR seguido del LF, muestras la data que acumulaste y luego limpias el acumulador y sigues con el loop.

    Dicho sea de paso, todas esas conversiones son innecesarias. El arduino te envía texto, y lo que muestras es texto. Puedes tranquilamente quitar ese try/catch para el tipo FormatException.

    Hola:

    ¿Cómo sabes que se comporta así?

    Si el tipo te manda "819\r\n", vos podés estar recibiéndolo en 2 eventos data received, por ejemplo "81", "9\r\n".

    Hice el código este con el try / catch.

    using System;
    using System.Collections.Generic;
    using System.ComponentModel;
    using System.Data;
    using System.Drawing;
    using System.Linq;
    using System.Text;
    using System.Threading.Tasks;
    using System.Windows.Forms;
    
    using System.IO.Ports; // No olvidar.
    
    namespace Arduino_In_Analogico_prueba_02
    {
        public partial class Form1 : Form
        {
            // Utilizaremos un string como buffer de recepción.
            string Recibidos = "";
            string Recibidos_Correcto = "";
            int Variar_este_valor = 0;
    
            public Form1()
            {
                InitializeComponent();
    
                if (!serialPort1.IsOpen)
                {
                    try
                    {
                        serialPort1.Open(); // Abre el puerto.
                    }
                    catch (System.Exception ex)
                    {
                        MessageBox.Show(ex.ToString());
                    }
    
                    serialPort1.DataReceived += new SerialDataReceivedEventHandler(serialPort1_DataReceived);
                }
            }
    
            // Al recibir datos.
            private void serialPort1_DataReceived(object sender, SerialDataReceivedEventArgs e)
            {
                Recibidos = serialPort1.ReadExisting(); // Entrada de datos por el puerto serie.
                Recibidos_Correcto = Recibidos.Replace("\n\r", "").Replace("\n","").Replace("\r",""); // Delimitador. Anular \n y \r.
    
                Invoke(new EventHandler(Actualizar));
            }
    
            // Procesar los datos recibidos en el bufer y extraer tramas completas.
            private void Actualizar(object sender, EventArgs e)
            {
    
                    Variar_este_valor = Convert.ToInt32(Recibidos_Correcto); // Convertir string a int.
    
    
                label1.Text = Recibidos_Correcto.ToString(); // Mostrar resultado en un label y convertirlo a string.
    
                Recibidos = ""; // Limpiar.
            }
        }
    }

    Aparece este error, por eso puse el Try/Catch.

    Se produjo una excepción de tipo 'System.FormatException' en mscorlib.dll pero no se controló en el código del usuario

    Información adicional: La cadena de entrada no tiene el formato correcto.


    http://electronica-pic.blogspot.com

    lunes, 20 de junio de 2016 21:51
  • Pegas un mensaje de 100 líneas y no pones lo más importante. 

    ¿Cuál es el dato, cuál es el texto, que no puedes convertir a Int32?

    Antes de invocar a Actualizar, o antes de invocar a Convert  ¿cuál es el texto en Recibidos_Correcto?

    Fijate que 0.1seg, para tu pc, significan cientos de millones de instrucciones procesadas. Tu programa podría haber procesado 100 eventos data received de ser necesario. Podrías estar recibiendo un fragmento de texto de 2 char "\r\n", y quedarte con una cadena vacía que obviamente es inconvertible...

    ---

    Además, quitas el try/catch y dejas el convert. No es lo que yo te propuse. Si quitas el convert, que es completamente innecesario, puedes prescindir del try/catch.

    • Editado walter_5 lunes, 20 de junio de 2016 22:18
    • Marcado como respuesta Metaconta lunes, 4 de julio de 2016 16:45
    lunes, 20 de junio de 2016 22:12
  • Pegas un mensaje de 100 líneas y no pones lo más importante. 

    ¿Cuál es el dato, cuál es el texto, que no puedes convertir a Int32?

    Antes de invocar a Actualizar, o antes de invocar a Convert  ¿cuál es el texto en Recibidos_Correcto?

    Fijate que 0.1seg, para tu pc, significan cientos de millones de instrucciones procesadas. Tu programa podría haber procesado 100 eventos data received de ser necesario. Podrías estar recibiendo un fragmento de texto de 2 char "\r\n", y quedarte con una cadena vacía que obviamente es inconvertible...

    ---

    Además, quitas el try/catch y dejas el convert. No es lo que yo te propuse. Si quitas el convert, que es completamente innecesario, puedes prescindir del try/catch.

    Hola:

    Ejecuta bien, pero no muestra nada en pantalla.

    using System;
    using System.Windows.Forms;
    
    using System.IO.Ports; // No olvidar.
    
    namespace Arduino_In_Analogico_prueba_02
    {
        public partial class Form1 : Form
        {
            // Utilizaremos un string como buffer de recepción.
            string Recibidos = "";
            string Recibidos_Correcto = "";
    
            public Form1()
            {
                InitializeComponent();
    
                if (!serialPort1.IsOpen)
                {
                    try
                    {
                        serialPort1.Open(); // Abre el puerto.
                    }
                    catch (System.Exception ex)
                    {
                        MessageBox.Show(ex.ToString());
                    }
    
                    serialPort1.DataReceived += new SerialDataReceivedEventHandler(serialPort1_DataReceived);
                }
            }
    
            // Al recibir datos.
            private void serialPort1_DataReceived(object sender, SerialDataReceivedEventArgs e)
            {
                Recibidos = serialPort1.ReadExisting(); // Entrada de datos por el puerto serie.
                Recibidos_Correcto = Recibidos.Replace("\n\r", "").Replace("\n","").Replace("\r",""); // Delimitador. Anular \n y \r.
                Invoke(new EventHandler(Actualizar));
            }
    
            // Procesar los datos recibidos en el bufer y extraer tramas completas.
            private void Actualizar(object sender, EventArgs e)
            {   
                label1.Text = Recibidos_Correcto.ToString(); // Mostrar resultado en un label y convertirlo a string.
                Recibidos_Correcto = ""; // Limpiar.
            }
        }
    }

    Saludos.


    http://electronica-pic.blogspot.com

    martes, 21 de junio de 2016 21:01
  • Hola Metaconta,

    Si ahora no te muestra nada, de ahí el error de conversión, nada no se puede convertir a número, comparto la opinión de  walter_5 realmente no necesitas la conversión. Lo que tendrías que hacer es saber qué es lo que hay realmente en el puerto serie y que datos estas recibiendo, los puntos de interrupción son muy útiles para ese fin. Analiza lo que recibes y luego trátalo como corresponda, por ejemplo si es cadena vacía, directamente ni siquiera invoques el método actualizar, si el dato es incompleto lo acumulas y esperas que se complete la trama.

    Un saludo.




    Es de buena educación dar las gracias cuando te ayudan, si alguna respuesta te ha sido de utilidad agradécelo marcandola como útil.
    Blog

    miércoles, 22 de junio de 2016 7:03
  • Hola Metaconta,

    Si ahora no te muestra nada, de ahí el error de conversión, nada no se puede convertir a número, comparto la opinión de  walter_5 realmente no necesitas la conversión. Lo que tendrías que hacer es saber qué es lo que hay realmente en el puerto serie y que datos estas recibiendo, los puntos de interrupción son muy útiles para ese fin. Analiza lo que recibes y luego trátalo como corresponda, por ejemplo si es cadena vacía, directamente ni siquiera invoques el método actualizar, si el dato es incompleto lo acumulas y esperas que se complete la trama.

    Un saludo.




    Es de buena educación dar las gracias cuando te ayudan, si alguna respuesta te ha sido de utilidad agradécelo marcandola como útil.
    Blog

    Hola:

    Lo que hay en el puerto es 547\n\r por poner un ejemplo, eso si, por cada 100 ms.

    Saludos.


    http://electronica-pic.blogspot.com

    jueves, 23 de junio de 2016 10:43
  • Hola:

    Lo que hay en el puerto es 547\n\r por poner un ejemplo, eso si, por cada 100 ms.

    Saludos.


    http://electronica-pic.blogspot.com

    Hola,

    ¿Eso es lo que realmente hay o es lo que esperas tener? Son dos cosas muy distintas.

    Si es lo que realmente hay tú codigo no fallaria, eliminas \n y \r y te quedaria un numero. ¿Pero realmente eso esta en el puerto serie cada 100ms? no lo creo, de hay tus errores de conversión.

    Pon un punto de interrupción en esta linea.

     Recibidos_Correcto = Recibidos.Replace("\n\r", "").Replace("\n","").Replace("\r","");

    y nos cuentas que tienes, pero repitelo 10 o 15 veces no te limites a la primera.

    Un saludo.


    Es de buena educación dar las gracias cuando te ayudan, si alguna respuesta te ha sido de utilidad agradécelo marcandola como útil.
    Blog

    jueves, 23 de junio de 2016 11:30
  • Buena filosofía, una cosas es creer y otra es la realidad.

    Pues no se que le pasa, debería aparecer 347, luego 348, no todo junto.

    Saludos.


    http://electronica-pic.blogspot.com

    jueves, 23 de junio de 2016 19:04
  • Buenos días,

    Bien ya sabemos que no siempre el puerto tiene lo que esperamos, ahora tenemos que tratar el dato nosotros, la primera idea seria usar el metodo Split de la clase string, este lo que hace es generar un array le damos unos separadores que en tu caso seria la \r\n, en el caso que estamos viendo esto nos crearia un array de dos posiciones, una posición con 347 y otra con 348, despues ya depende o mando la primera posición a tú metodo actualizar o mando la segunda o con la ayuda de un foreach mando todas las posiciones del array al metodo actualizar.

    Otra opción seria con un foreach recorrer el string recibidos y analizar caracter por carecte a ver si es un numero, si es numero lo sumo a un bufer si es un separador \r o \n envio el bufer al metodo actualizar y lo limpio.

    Un saludo.


    Es de buena educación dar las gracias cuando te ayudan, si alguna respuesta te ha sido de utilidad agradécelo marcandola como útil.
    Blog

    viernes, 24 de junio de 2016 8:12
  • Buenos días,

    Bien ya sabemos que no siempre el puerto tiene lo que esperamos, ahora tenemos que tratar el dato nosotros, la primera idea seria usar el metodo Split de la clase string, este lo que hace es generar un array le damos unos separadores que en tu caso seria la \r\n, en el caso que estamos viendo esto nos crearia un array de dos posiciones, una posición con 347 y otra con 348, despues ya depende o mando la primera posición a tú metodo actualizar o mando la segunda o con la ayuda de un foreach mando todas las posiciones del array al metodo actualizar.

    Otra opción seria con un foreach recorrer el string recibidos y analizar caracter por carecte a ver si es un numero, si es numero lo sumo a un bufer si es un separador \r o \n envio el bufer al metodo actualizar y lo limpio.

    Un saludo.


    Es de buena educación dar las gracias cuando te ayudan, si alguna respuesta te ha sido de utilidad agradécelo marcandola como útil.
    Blog


    Hola:

    Por lo que cuentas, hice esto y no lee nada.

    using System;
    using System.Windows.Forms;
    
    using System.IO.Ports; // No olvidar.
    
    namespace Arduino_In_Analogico_prueba_02
    {
        public partial class Form1 : Form
        {
            // Utilizaremos un string como buffer de recepción.
            string Recibidos = "";
            string Recibidos_Correcto = "";
    
            public Form1()
            {
                InitializeComponent();
    
                if (!serialPort1.IsOpen)
                {
                    try
                    {
                        serialPort1.Open(); // Abre el puerto.
                    }
                    catch (System.Exception ex)
                    {
                        MessageBox.Show(ex.ToString());
                    }
    
                    serialPort1.DataReceived += new SerialDataReceivedEventHandler(serialPort1_DataReceived);
                }
            }
    
            // Al recibir datos.
            private void serialPort1_DataReceived(object sender, SerialDataReceivedEventArgs e)
            {
                Recibidos = serialPort1.ReadExisting(); // Entrada de datos por el puerto serie.
                Invoke(new EventHandler(Actualizar));
            }
    
            // Procesar los datos recibidos en el bufer y extraer tramas completas.
            private void Actualizar(object sender, EventArgs e)
            {
    
                char[] Delimitador = {' ', '\r', '\n', };
    
                string[] Palabras = Recibidos.Split(Delimitador);
    
                foreach (string Comandos in Palabras)
                {
                    label1.Text = Recibidos.ToString(); // Mostrar resultado en un label y convertirlo a string.
                    Recibidos = ""; // Limpiar.
                }
            }
        }
    }
    

    Otro paso.

    Saludos.


    http://electronica-pic.blogspot.com

    sábado, 25 de junio de 2016 15:36
  • Hola Metaconta

    Al split añadele esta opción para eliminar los vacios.

    string[] Palabras = Recibidos.Split(Delimitador, StringSplitOptions.RemoveEmptyEntries);

    Y luego sigues mostrando la variavle Recibidos despues de tratar los datos tiendrias que mostrar Comandos

    foreach (string Comandos in Palabras)
                {
                    label1.Text = Comandos.; // No es necesario ToString() comandos ya es string.
                }

    Un saludo.


    Es de buena educación dar las gracias cuando te ayudan, si alguna respuesta te ha sido de utilidad agradécelo marcandola como útil.
    Blog


    • Editado Rodripelto lunes, 27 de junio de 2016 6:35
    • Marcado como respuesta Metaconta lunes, 4 de julio de 2016 16:45
    lunes, 27 de junio de 2016 6:33
  • Hola Metaconta

    Al split añadele esta opción para eliminar los vacios.

    string[] Palabras = Recibidos.Split(Delimitador, StringSplitOptions.RemoveEmptyEntries);

    Y luego sigues mostrando la variavle Recibidos despues de tratar los datos tiendrias que mostrar Comandos

    foreach (string Comandos in Palabras)
                {
                    label1.Text = Comandos.; // No es necesario ToString() comandos ya es string.
                }

    Un saludo.


    Es de buena educación dar las gracias cuando te ayudan, si alguna respuesta te ha sido de utilidad agradécelo marcandola como útil.
    Blog


    Hola:

    Ahora lee datos. Lo que si te fijas bien, si está fijo a 825 por decir algún valor, a veces en milisegundos se ve que se pone a 0, a vecs 4 y luego su valor inicial, como que pierde algo.

    Saludos.


    http://electronica-pic.blogspot.com

    miércoles, 29 de junio de 2016 4:19
  • Hola,

    Por lo que cuentas yo diria que la trama de datos en el puerto no es costante, sin estar ahí es dificil saber el motivo, puede ser incluso que el aurdino de vez en cuando envíe mal los datos, con paciencia y puntos de interrupción tendrias que analizar los datos que recibes para poder tomar una decisión de como tratarlos, siento no poder ayudarte mas pero a distancia es complicado.

    Un saludo.

    Es de buena educación dar las gracias cuando te ayudan, si alguna respuesta te ha sido de utilidad agradécelo marcandola como útil.
    Blog

    • Marcado como respuesta Metaconta lunes, 4 de julio de 2016 16:45
    miércoles, 29 de junio de 2016 7:13
  • Será lo que dices, aún así, muchas gracias.

    http://electronica-pic.blogspot.com

    lunes, 4 de julio de 2016 16:45