# Prueben mis programas sobre puerto serie y aporten ideas



## Meta (Abr 24, 2016)

Hola:

He hecho algunos programas sobre el puerto serie tanto en modo consola como en Windows Form bajo Visual Studio .net. Se la tecnología que sea, en este caso he usado Arduino y puerto serie con VS .net 2015. También valen con PIC.

Quiero que prueben estas interfaz y me cuentan sus experiencias y consejos para mejorarlo. Lo pido porque con el tiempo haré tutoriales como estos ya presentados en su día que puedes ver aquí.

https://www.forosdeelectronica.com/f47/aporte-interfaz-arduino-138965/

La interfaz en modo consola.






Windows Form.





Código de Arduino:

```
int valorPot=0;

void setup(){ Serial.begin(115200); }

void loop(){
     valorPot=analogRead(2);
     Serial.println(valorPot);
     delay(100); // 0.1 segundos.
}
```
Saludos.


----------



## analogico (Abr 24, 2016)

no tengo esa version de vs

pero el otro dia necesitaba un programa y use este codigo   https://ingsistele.wordpress.com/2012/02/25/conectar-a-un-puerto-serie-com-usando-vb-net/

muy bueno resulto a la primera y eso que no use esa version de vs  

y es 100% .net no necesita apis  exernas


----------



## Meta (Abr 24, 2016)

Son ejecutables, no necesita tener instalado Visual Studio.


----------



## John Miller (Abr 24, 2016)

Hola bien día excelente aporte, tendras alguno para controlar un Stepper motor...

JM.


----------



## Meta (Abr 24, 2016)

John Miller dijo:


> Hola bien día excelente aporte, tendras alguno para controlar un Stepper motor...
> 
> JM.



Aún estoy probando si me funciona tanto en Windows Form y en Consola que al parecer que si, antes de hacer algo. 

Con un potenciómetro tengo intención de hacer ejemplo como entrada analógica controlada por un potenciómetro, con ello se puede sustituir sensores de temperatura, todo lo que lea entrada analógico.

Por supuesto, que motor PAP o Stepper que nombras, incluso servomotor, brillo de un Led, lo que se nos ocurra.

Apuntaré el Motor Stepper que indica.

Pueden aportar más idea, la de arriba es una que indicó nuestro amigo John Miller. Se hará con los lenguajes de Visual Studio .net en cada ejemplo.

Saludos.


----------



## D@rkbytes (Abr 24, 2016)

Debes dar al usuario la opción de seleccionar un puerto y no preestablecerlo.

Lo digo por ésto que sucede cuando no se tienen puertos serie virtuales o físicos.


Al menos el programa ya tiene la depuración sobre ese error.​


----------



## analogico (Abr 24, 2016)

Meta dijo:


> Son ejecutables, no necesita tener instalado Visual Studio.


no y tampoco necesito tener el codigo fuente


asi que estaba añadiendo un combobox que liste los puertos

lo primero es añadir el combobox 

luego  la variable con el nombre del puerto

```
private string elpuerto;
```

ahora  en el load



```
void Form1Load(object sender, EventArgs e)
		{
			 // combobox puertos.
            string[] ports = SerialPort.GetPortNames();
foreach(string port in ports)
            {
	this.ComboPorts.Items.Add(port)   ;
             
            }
//esto es solo para  seleccionar el primer puerto disponible es mejorde otra manera 
this.ComboPorts.SelectedIndex=0;
	
		}
```


y por ultimo ubicamosdonde se abre el puertoy una linea mas arriba



```
{
					this.serialPort1.PortName=elpuerto; //esta es la linea
					this.serialPort1.Open();
				}
```

ahora no tengo el arduino para probarlo asi que nose pruebenlo ustedes
la seleccion del puerto necesita mas trabajo


----------



## Meta (Abr 25, 2016)

Buenos días:

Antes que nada, muchas gracias por vuestra colaboración. No olvidar que estos programas es peor que alfa, gracias a ustedes se resolverá. Quiero hacer muchos programas de ejemplos, de menos a más, no todo relleno y bien completo de golpe en algunos aspectos.

El tema de elegir puertos con comobox y demás configuraciones lo tengo hecho en este ejemplo que puedes ver aquí.

Primero me interesa el funcionamiento del programa en general, luego se pule y se depura los errores posibles.

D@rkbytes:
Corregido. Ahora te pregunta el número de puerto, eliges un número, por ejemplo, el 25 y pulsas Enter.



@analogico:
Lo tengo preparado a parte solo la configuración del puerto y detección de puertos instalados. Pon y quitar el USB de Arduino para que veas como detecta el puerto serie.



Abajo, me da problemas a la hora de cerrar la aplicación o programa, por eso dejo por defecto el puerto COM4. Por ahora. Si quiere que lo deje por defecto en otro puerto y prueban, me lo dicen y les pongo por defecto el puerto COM que desees. 



Aquí abajo haciendo prueba sobre los colores si van a usar un sensor de temperatura o para otra cosa que se les ocurra. Este ejemplo, no necesita Arduino. Por supuesto, se puede añadircon Arduino.



Pueden descargar los tres programas aquí abajo, prueban y comentan su impresión, sugerencias e ideas.

Saludos.


----------



## analogico (Abr 25, 2016)

y si el puerto por defecto se configura desde un archivo de texto

solo el puerto por que ese es lo unico que cambia
por que cuando haces el programa los otros parametros ya vienen predefinidos


----------



## Meta (Abr 25, 2016)

Hola:

El problema que me da es esta interfaz.
Ver el archivo adjunto 142909

Ya que al cerrar el programa, se queda bloqueado. Aunque cierre el puerto que está abierto, mientras recibe muchos datos de Arduino, se bloquea, no cierra como es debido.

Tendré que porgramar Arduino que si pulso un botón de cerrar, envía un comando que le indique desde la interfaz hacia Arduino que deje de fucnionar la entrada analógica o entre tantos datos que se colapsa.

Otra cosa que no se, si por cada entrada de datos que entra durante 24 horas se podrá colgar. Debo borrar lo viejo y actualizar lo nuevo, espero que se entienda lo que quiero decir.

Gracias por las sugerencias, cuanta más mejor.


----------



## analogico (Abr 25, 2016)

Meta dijo:


> Hola:
> 
> El problema que me da es esta interfaz.
> Ver el archivo adjunto 142909
> ...



eso es por que el programa se deberia hacer con hilos


pero prueba añadiendo esto en el load 

```
Control.CheckForIllegalCrossThreadCalls = false;
```
si no, entonces  hilos


----------



## Meta (Abr 25, 2016)

Hola:

Pues no, no funciona, se comporta como siempre.
https://msdn.microsoft.com/es-es/li...heckforillegalcrossthreadcalls(v=vs.100).aspx

Sigo investigando. 

Gracias por la idea.


----------



## analogico (Abr 25, 2016)

entonces prueba añadiendo un 

```
Application.DoEvents();
```
en el 
	
	



```
void actualizar
```

si todavia no funciona entonces  hilos
solo que 
con hilos pero eso es un poco mas complicado


----------



## analogico (Abr 26, 2016)

ahora   que recuerdo las pesas envian   datos 2 o 3 veces por segundo

si estas madando a la velocidad   del   arduino, eso son cientos de veces por segundo
entonces quizas tu programa se satura


----------



## Meta (Abr 26, 2016)

analogico dijo:


> ahora   que recuerdo las pesas envian   datos 2 o 3 veces por segundo
> 
> si estas madando a la velocidad   del   arduino, eso son cientos de veces por segundo
> entonces quizas tu programa se satura



Sí, el programa le entra estrés postraumático.

Estoy tan perdido que he preguntado en los foros oficiales de MSDN.

Ver enlace.

Sigo investigando...


----------



## analogico (Abr 26, 2016)

el 
	
	



```
Application.DoEvents();
```
tienen que ir en el  void actualizar   


y el           
	
	



```
Control.CheckForIllegalCrossThreadCalls = false;
```
 se supone que anula ese error


creo que el error es por que se pisa el codigo

ahora se me ocurre algo mas facil



```
if trabajando=false  

      Invoke(new EventHandler(Actualizar));


void actualizar()

trabajando=true

// hacer todo

trabajando = false
```


----------



## Meta (Abr 30, 2016)

Hola:

Ahora añadí un timer que lee a 1000 ms frente a los 100 ms que envía Arduino.

Se me cuelga a veces, antes era siempre.


```
using System;
using System.Collections.Generic;
using System.Windows.Forms;

using System.IO.Ports; // No olvidar.
using System.IO;

namespace Arduino_In_Analogico_prueba_01
{
    public partial class Form1 : Form
    {
        // Utilizaremos un string como buffer de recepción.
        string Recibidos;

        public Form1()
        {
            InitializeComponent();

            if (!serialPort1.IsOpen)
            {
                try
                {
                    serialPort1.Open();
                }
                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)
        {

            // Acumula los caracteres recibidos a nuestro 'buffer' (string).
            try
            {
                // Recibidos = serialPort1.ReadLine();
            }

            catch (IOException)
            {
                // Información adicional: La operación de E/S se anuló por una salida de subproceso o por una solicitud de aplicación.
                return;
            }

            catch(Exception)
            {
                return;
            }

            // Invocar o llamar al proceso de tramas.
            Invoke(new EventHandler(Actualizar));
        }


        // Como variables de clase
        private string[] Separador = new string[] { ",", "\r", "\n", "/n" };
        private List<string> Leo_Dato = new List<string>();

        // Procesar los datos recibidos en el bufer y extraer tramas completas.
        private void Actualizar(object sender, EventArgs e)
        {
            Recibidos = serialPort1.ReadLine();

            double Voltaje = 0;
            double Porcentaje = 0;

            // En el evento
            Leo_Dato.Clear();
            Leo_Dato.AddRange(Recibidos.Split(Separador, StringSplitOptions.RemoveEmptyEntries));

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


            try
            {
                label_Lectura_Potenciometro.Text = Leo_Dato[0].ToString();
            }

            catch (ArgumentOutOfRangeException)
            {
                //Información adicional: El índice estaba fuera del intervalo. Debe ser un valor no negativo e inferior al tamaño de la colección.
            }


            progressBar1.Value = Convert.ToInt32(Leo_Dato[0].ToString());
            double Dato_Voltaje = Convert.ToDouble(Leo_Dato[0]);
            double Dato_Porcentaje = Convert.ToDouble(Leo_Dato[0]);

            Voltaje = Dato_Voltaje * (5.00 / 1023.00);
            Porcentaje = Dato_Porcentaje * (100.00 / 1023.00);

            label_Voltio.Text = Voltaje.ToString("N2") + " V."; // N2 tiene dos decimales.
            label_Portentaje.Text = Porcentaje.ToString("N2") + " %";
        }

        private void Form1_FormClosing(object sender, FormClosingEventArgs e)
        {

            timer1.Stop();

            if (serialPort1.IsOpen) // ¿El puerto está abierto?
            {
                serialPort1.Close(); // Puerto cerrado.
            }
        }
    }
}
```

Debo modificarlo mejor antes de hacer el tutorial. Ya compré el servo motor pequeño para incluirlo en el tutorial.

Presisamente tengo este y funciona  a la primera.





Saludos.
Saludos.


----------



## analogico (Abr 30, 2016)

una pesima solucion
ahora viendo todo el codigo creo que es mejor que hagas lo que te propuse

pero en el    private void serialPort1_DataReceived
como nome confundo con las llaves lo hare en vb





```
'declara variable bandera  que indicara si esta trabajando
dim trabajando as boolean  =false ' se inicializa en no esta trabajando



 ' Al recibir datos.
        private sub serialPort1_DataReceived(object sender, SerialDataReceivedEventArgs e)

if trabajando = true then exit sub ' si todavia esta trabajando sale de la funcion sin hacer nada

trabajando= true '   declara que esta trabajando 

'codigo de recepcion
'llamar a la otra funcion
'etc


trabajando= false ' al terminar de hacer todo     cambia  a no esta trabajando false, 
end sub
```


----------



## Meta (May 1, 2016)

Hola:

Para no confundirse, pues usar este conversión de códigos.

http://converter.telerik.com/

Lo he intentado y no lo capto. Me funciona mejor como lo hice arriba. Quiero que me funcione perfecto, como un programa decente, nada de cosas raras.

Saludos.


----------



## D@rkbytes (May 1, 2016)

A ver, un programa decente ya a estas alturas, no debería ser del tipo consola.
Es lógico que un programa que recibe y envía datos en RS-232, se congele o no responda porque el protocolo y su correspondiente interpretación no son muy rápidos. Aún así usando su máximo de baudios permitidos.

Enfócate por lo que ya está hecho, comprobado que funciona, y mejorarás lo que quieres hacer.
Así sean GUIs en C++, C, Ensamblador de x bits, Basic, Pascal, Borland C, C#, etc.

Códigos y ejemplos sobre interfaces en RS-232, hay de sobra. Y muchas muy buenas. 

Hablar de dudas sobre interfaces RS-232 en éstos tiempos, ya no va.


----------



## Nestor2017 (May 1, 2016)

Si vas hacer una interfaz RS232 para controlar motores deberías aplicar un protocolo (podria ser MODBUS RTU) para manejar los errores debido a la interferencia producida por los motores.


----------



## analogico (May 1, 2016)

Meta dijo:


> Hola:
> 
> Para no confundirse, pues usar este conversión de códigos.
> 
> ...



no me funciona esa pagina, pero la idea es que ignore los nuevos datos hasta que haya terminado de procesar el dato antiguo

algo mas o menos asi
 y llama a la funcion actualizar() sin cosas raras 
la idea es que   el programa se espere hasta que ejecute todo
y luego cambie a trabajando= false  que indicara que esta libre para  procesar un nuevo dato

y tambien prueba el exe  directamente  ya que el emulador del ide no es lo suficentemente rapido



```
bool trabajando = false; ' variable  de bandera


// Al recibir datos.
private void serialPort1_DataReceived(object sender, SerialDataReceivedEventArgs e)
{
	if (trabajando == true)
		return;
	trabajando = true;

// Acumula los caracteres recibidos a nuestro 'buffer' (string).
	// Recibidos = serialPort1.ReadLine();

 ///aca el codigo que falta ReadLine

// llamar a la funcion
	            Actualizar();

	trabajando = false;
}
```


la verdad es que tu codigo esta muy complicado
te vuelvo a recomendar https://ingsistele.wordpress.com/2012/02/25/conectar-a-un-puerto-serie-com-usando-vb-net/ ylo pasas a c#


----------



## Meta (May 2, 2016)

D@rkbytes dijo:


> A ver, un programa decente ya a estas alturas, no debería ser del tipo consola.
> 
> *Haré los dos tipos y hasta WPF también. Me hace apetece hacerlo y hay usuarios que me lo han pedido que lo hiciera, porque en algunos centros de enseñansas así lo piden. La consola se usa más de lo que imaginas, por ejemplo, cuando aprendes a programar. Es más, hasta vale para curiosos.*
> 
> ...



*Dentro del mundo del microcontrolador y la electrónica, va demasiado y mucho. Lo que no va es hacer un dispositivo una empresa con RS-232, solo USB y otros protocolos. RS-232 no se le ingnora ni en su sombra*.

Hola @analogico:

Lo que cuentas es lo que intentaba hacer pero lo hice diferente, que es el código indicado atrás.

Voy a reescribir el código desde cero para que se entienda lo más básico, no usaré conversiones de porcentaje y de tensión en este caso. Este código también se cuelga al cerrar la aplicación.

Te lo muestro así ahora para que entiendas el concepto.


```
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 = "";
        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.
        }
    }
}
```
Sigo con ello.

Este código es más sencillo de entender.

Cuando tenga todo acabado mi idea del documento final en pdf, es hacer muchos ejemplos usando un solo lenguaje, como el C#, cuando todo funcione a por VB .net y V C++ .net.

Saludos.


----------



## Meta (May 28, 2016)

Hola:

He logrado en modo consola que no parpadee toda la pantalla, pero me falla la parte que al vovler a 0 la barra de progreso, es decir, al aumentar el valor hast alos 1023 en decimal, la barra de progreso progresa, al reducirlo a 0, la barra se queda donde está.

Ese es el problema que tengo ahora, tan pronto como pueda, lo estoy solucinoando.

Aquí el código como curiosidad. Código en modo consola C#.

```
using System;
using System.IO.Ports; // No olvidar.
using System.IO;

namespace Porcentaje_Barra_P_Serie_Consola_3_CS
{
    class Program
    {
        public static string Recibidos = "";
        public static double Resultado_Porcentaje = 0;
        public static double Resultado_Voltios = 0;
        public static double Mitad_barra = 0;


        static void Main(string[] args)
        {
            string COM = "";

            // Tamaño ventana consola.
            Console.WindowWidth = 55; // X.
            Console.WindowHeight = 15; // Y.
            Console.Title = "Serial Port C# - v.02"; // Título de la ventana.

            SerialPort Puerto_serie;

            // Crear un nuevo objeto SerialPort con la configuración predeterminada.
            Puerto_serie = new SerialPort();

            // Configuración.
            Console.Write(@"
Introduzca un número para seleccionar puerto COM.
Por ejemplo el 4, sería COM4.

Puerto: ");
            COM = Console.ReadLine(); // Escribir el número del puerto.
            Console.Clear();

            Puerto_serie.PortName = "COM" + COM; // Número del puerto serie.


            Puerto_serie.BaudRate = 115200; // Baudios.
            Puerto_serie.Parity = Parity.None; // Paridad.
            Puerto_serie.DataBits = 8; // Bits de datos.
            Puerto_serie.StopBits = StopBits.Two; // Bits de parada.
            Puerto_serie.Handshake = Handshake.None; // Control de flujo.

            // Establecer la lectura / escritura de los tiempos de espera.
            Puerto_serie.ReadTimeout = 500;
            Puerto_serie.WriteTimeout = 500;

            try
            {
                Puerto_serie.Open(); // Abrir el puerto serie.
            }

            catch (IOException)
            {
                Console.ForegroundColor = ConsoleColor.Red; // Texto en rojo.
                Console.CursorVisible = false;
                Console.SetCursorPosition(16, 6);
                Console.WriteLine(@"El puerto " + Puerto_serie.PortName + @" no existe
                o no lo encuentra.");
            }

            Puerto_serie.DataReceived += new SerialDataReceivedEventHandler(DataReceivedHandler);

            Console.Read();
            Puerto_serie.Close(); // Cerrar puerto.
        }

        private static void DataReceivedHandler(object sender, SerialDataReceivedEventArgs e)

        {

            try
            {
                SerialPort sp = (SerialPort)sender;
                Recibidos = sp.ReadExisting();
                //Console.Clear();

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

                int Variar_este_valor = Convert.ToInt32(Recibidos);

                Resultado_Porcentaje = Variar_este_valor * (100.00 / 1023.00);
                Resultado_Voltios = Variar_este_valor * (5.00 / 1023.00);

                
                Console.SetCursorPosition(0, 1);
                Console.Write("Datos recibidos: ");
                Console.SetCursorPosition(17, 1);
                Console.Write("    ");
                Console.SetCursorPosition(17, 1);
                Console.Write(Recibidos);

                
                Console.SetCursorPosition(0, 3);
                Console.Write("0 %                     50 %                   100 %");
                Console.SetCursorPosition(0, 4);
                Console.Write("┌────────────────────────┬───────────────────────┐");
                Console.ForegroundColor = ConsoleColor.Yellow;

                // Se dibide por dos la barra del porcentaje para que quepa decuadamente en la pantalla.
                Mitad_barra = Resultado_Porcentaje / 2;

                if (Mitad_barra > 50)
                {
                    Mitad_barra = 50;
                }

                // Borrado de barra de progreso para actualizar después su posición actual.
                Console.SetCursorPosition(0, 5);
                //Console.WriteLine("                                                  ");

                // Barra de progreso.
                for (int i = 1; i <= Mitad_barra; i++)
                {
                    Console.Write("█"); // Muestra ASCII 219 Dec y DB en Hex.
                }

                // Si sobre pasa 100, muestra # al final de la barra del porcentaje de color rojo.
                if (Resultado_Porcentaje >= 100)
                {
                    Console.ForegroundColor = ConsoleColor.Red;
                    Console.Write("#");
                }

                Console.ForegroundColor = ConsoleColor.Gray; // Vuelve al color gris.

                // Línea 7.
                Console.SetCursorPosition(0, 7);
                Console.Write("Porcentaje: ");
                Console.SetCursorPosition(12, 7);
                Console.Write("            ");
                Console.SetCursorPosition(12, 7);
                Console.Write(Resultado_Porcentaje.ToString("N0") + " %.");

                // Línea 8.
                Console.SetCursorPosition(0, 8);
                Console.Write("Voltios: ");
                Console.SetCursorPosition(12, 8);
                Console.Write("            ");
                Console.SetCursorPosition(12, 8);
                Console.Write(Resultado_Voltios.ToString("N2") + " V.");

            }

            catch (FormatException)
            {
                // Console.WriteLine("La cadena de entrada no tiene el formato correcto.");
            }
        }
    }
}
```


----------

