none
Modificar este código sacado del ejemplo MSDN RRS feed

  • Pregunta

  • Hola:

    Tengo este código sacado en este enlace.

    using System;
    using System.IO.Ports;
    
    class PortDataReceived
    {
        public static void Main()
        {
            SerialPort mySerialPort = new SerialPort("COM1");
    
            mySerialPort.BaudRate = 9600;
            mySerialPort.Parity = Parity.None;
            mySerialPort.StopBits = StopBits.One;
            mySerialPort.DataBits = 8;
            mySerialPort.Handshake = Handshake.None;
            mySerialPort.RtsEnable = true;
    
            mySerialPort.DataReceived += new SerialDataReceivedEventHandler(DataReceivedHandler);
    
            mySerialPort.Open();
    
            Console.WriteLine("Press any key to continue...");
            Console.WriteLine();
            Console.ReadKey();
            mySerialPort.Close();
        }
    
        private static void DataReceivedHandler(
                            object sender,
                            SerialDataReceivedEventArgs e)
        {
            SerialPort sp = (SerialPort)sender;
            string indata = sp.ReadExisting();
            Console.WriteLine("Data Received:");
            Console.Write(indata);
        }
    }


    https://msdn.microsoft.com/es-es/library/system.io.ports.serialport.datareceived%28v=vs.110%29.aspx?f=255&MSPPError=-2147217396


    Quiero añadirle algo como este código de abajo y no me sale.

                    int cantidadBytes = int.Parse(indata);
                    byte[] datosArray = new byte[cantidadBytes];
    
                    Console.WriteLine(datosArray);
    
                    switch (indata)
                    {
                        case "A1":
                            Thread.Sleep(100); // Retardo.
                            byte[] miBuffer = Encoding.ASCII.GetBytes("OK1"); // Codificación ASCII.
                            sp.Write(miBuffer, 0, miBuffer.Length); // Envía OK1 al puerto serie.
                            break;
    
                        case "A2":
                            Thread.Sleep(100); // Retardo.
                            byte[] miBuffer2 = Encoding.ASCII.GetBytes("OK2"); // Codificación ASCII.
                            sp.Write(miBuffer2, 0, miBuffer2.Length); // Envía OK2 al puerto serie.
                            break;
    
                        default:
                            // Código si no es A1 ni A2.
                            break;
                    }


    El el puerto me llegua un dato, ejemplo "A1", se tiene que ejecutar el switch. Como "A1" es un string. Lo malo que se me almacena en la variable tipo int llamado cantidadBytes.

    ¿Existe algún truco para ejecutar A1 de alguna forma?

    Recibo por el puerto serie el primer dato que es un número, por ejemplo 17729. Este número es el tamaño de un array en este caso se llama datosArray. Por supuesto que primero este valor en este caso 17729 se almacena en la variable cantidadBytes.

    Saludos.


    http://electronica-pic.blogspot.com


    • Editado Metaconta sábado, 4 de febrero de 2017 2:57
    sábado, 4 de febrero de 2017 1:50

Todas las respuestas

  • using System;
    using System.IO.Ports;
    using System.Text;
    
    class PortDataReceived
    {
        enum ESTADOS { LEYENDOCANTIDAD, LEYENDOCODIGO,FIN}
        static ESTADOS estado = ESTADOS.LEYENDOCANTIDAD;
        static int cantidadBytes;
        static StringBuilder sb = new StringBuilder();
    
        public static void Main()
        {
            SerialPort mySerialPort = new SerialPort("COM1");
    
            mySerialPort.BaudRate = 9600;
            mySerialPort.Parity = Parity.None;
            mySerialPort.StopBits = StopBits.One;
            mySerialPort.DataBits = 8;
            mySerialPort.Handshake = Handshake.None;
            mySerialPort.RtsEnable = true;
    
            mySerialPort.DataReceived += new SerialDataReceivedEventHandler(DataReceivedHandler);
    
            mySerialPort.Open();
    
            Console.WriteLine("Press any key to continue...");
            Console.WriteLine();
            Console.ReadKey();
            mySerialPort.Close();
        }
    
        private static void DataReceivedHandler(
                            object sender,
                            SerialDataReceivedEventArgs e)
        {
            SerialPort sp = (SerialPort)sender;
            string indata = sp.ReadExisting();
     
            foreach (char item in indata)
            {
                switch(estado)
                {
                    case ESTADOS.LEYENDOCANTIDAD:
                        if (char.IsDigit(item))
                        {
                            sb.Append(item);
                        }
                        else if (item == 'A')
                        {
                            cantidadBytes = int.Parse(sb.ToString());
                            sb.Clear();
                            sb.Append(item);
                            Console.WriteLine(cantidadBytes);
                            estado = ESTADOS.LEYENDOCODIGO;
                        }
                        else
                        {
                            Console.WriteLine("error (caracter recibido: {0})", item);
                            estado = ESTADOS.FIN;
                        }
                        break;
    
                    case ESTADOS.LEYENDOCODIGO:
                        if (char.IsDigit(item))
                        {
                            sb.Append(item);
                            Console.WriteLine(sb.ToString());
                            estado = ESTADOS.FIN;
                        }
                        else
                        {
                            Console.WriteLine("error (caracter recibido: {0})", item);
                            estado = ESTADOS.FIN;
                        }
                        break;
    
                    case ESTADOS.FIN:
                        Console.WriteLine("listo");
                        break;
                }
            }
    
    
            Console.WriteLine("Data Received:");
            Console.Write(indata);
        }
    }

    Asume que la cadena recibida tiene esta forma    "12345A1"

    una serie de dígitos decimales, limitados por una A y seguido por un dígito.

    Voy a probar y te respondo como me fue. Tardaré un día porque domingo tengo ocupado.

    Gracias mi muy distinguido amigo.


    http://electronica-pic.blogspot.com

    sábado, 4 de febrero de 2017 23:16
  • Hola:

    Código de Arduino parcial donde están las imágenes, hay dos fotos, uno de 17729 y el otro de 2065. No hace falta leer mucho si no lo entiendes, te digo lo que hace y acabas rápido de entender.

    #include <LiquidCrystal.h>
    
    int estadoActual1 = 0;
    int estadoActual2 = 0;
    int estadoUltimo = 0;
    char caracter;
    String comando;
    int estadoActual3 = 0;
    int estadoActual4 = 0;
    int estadoUltimo2 = 0;
    
    // Foto del 2065 bytes.
    PROGMEM const unsigned char rawData2[] = {
      0x89, 0x50, 0x4E, 0x47, 0x0D, 0x0A, 0x1A, 0x0A, 0x00, 0x00, 0x00, 0x0D
    };
    
    // Foto del 17729 bytes.
    PROGMEM const unsigned char rawData[] = {
      0xFF, 0xD8, 0xFF, 0xE1, 0x00, 0x18, 0x45, 0x78, 0x69, 0x66, 0x00, 0x00
    };
    
    // Inicializa la librería con sus pines indicados.
    // RS, RW, Enable, D4, D5, D6, D7.
    LiquidCrystal lcd(8, NULL, 9, 4, 5, 6, 7);

    // Pin 10 para saber que es luz de fondo.
    // const byte LuzFondo = 10

    void setup()
    {
      pinMode(2, INPUT); // Entrada digital donde está el pulsador.
      pinMode(A1, INPUT); // Entrada como digital.

      // Baudios.
      Serial.begin(115200);

      // Formato de pantalla.
      lcd.begin(16, 2);
    }

    void enviarImagen1()
    {
      for (unsigned int i = 0; i < sizeof(rawData); i++)
        Serial.write(pgm_read_byte(&rawData[i]));
    }

    void enviarImagen2()
    {
      for (unsigned int j = 0; j < sizeof(rawData2); j++)
        Serial.write(pgm_read_byte(&rawData2[j]));
    }

    /*
      void enviarImagen()
      {
      for (unsigned int i = 0; i < sizeof(rawData); ) // El i++ de aquí se quita.
      {
        Serial.write(pgm_read_byte(&rawData[i]));
        lcd.setCursor(0, 0); // Posiciona el cursor donde quieras que se imprima la cantidad de bytes enviados.
        // Procura dejar un espacio de entre 5 y 8 caracteres según la cantidad de dígitos a representar.
        lcd.print(++i);
      }
      }
    */
    void loop()
    {
      estadoActual1 = digitalRead(2); // Leer entrada digital número 2.
      delay(10);
      estadoActual2 = digitalRead(2);

      if (estadoActual1 == estadoActual2)
      {
        if (estadoActual1 != estadoUltimo)
        {
          if (estadoActual1 == HIGH)
          {
            Serial.write("17729A1"); // 17729 + A1.
            //Serial.write("17729"); // Envía 5 Bytes que es la cantidad del archivo a C#.
            lcd.setCursor(0, 0);
            lcd.print("Enviado A1.");
          }
        }
      }

      estadoUltimo = estadoActual1;

      estadoActual3 = digitalRead(A1); // Leer entrada digital número 2.
      delay(10);
      estadoActual4 = digitalRead(A1);

      if (estadoActual3 == estadoActual4)
      {
        if (estadoActual3 != estadoUltimo2)
        {
          if (estadoActual3 == HIGH)
          {
            Serial.write("2065A2"); // 2065 + A2.
            //Serial.write("2065"); // Envía 4 Bytes que es la cantidad del archivo a C#.
            lcd.setCursor(0, 0);
            lcd.print("Enviado A2");
          }
        }
      }

      estadoUltimo2 = estadoActual3;

      /* Voy leyendo carácter a carácter lo que se recibe por el canal serie
          (mientras lelgue algún datoallí), y los voy concatenando uno tras otro
          en una cadena. En la práctica, si usamos el "Serial monitor" el bucle while
          acabará cuando pulsamos Enter. Eldelay es conveniente para no saturar el
          canal serie y que la concatenación se haga de forma ordenada.
      */

      while (Serial.available() > 0)
      {
        caracter = Serial.read();
        comando.concat(caracter);
        delay(10);
      }

      /* Una vez ya tengo la cadena "acabada", compruebo su valor y hago que
          la placa Arduino reacciones según sea este. Aquí podríamos hacer lo
          que quisiéramos: si el comando es "tal", enciende un Led,si es cual,
          mueve un motor... y así.
      */

      if (comando.equals("OK1") == true)
      {
        // Serial.write("17729"); // Tamaño del array.
        delay(100);
        enviarImagen1(); // Enviar imagen o foto hacia el puerto serie al PC.
        lcd.setCursor(0, 1); // Crusor segunda línea del LCD.
        lcd.print("Archivo: JPG    ");
      }

      if (comando.equals("OK2") == true)
      {
        //Serial.write("2065"); // Tamaño del array.
        delay(100);
        enviarImagen2(); // Enviar imagen o foto hacia el puerto serie al PC.
        lcd.setCursor(0, 1); // Crusor segunda línea del LCD.
        lcd.print("Archivo: PNG    ");
      }
      // Limpiamos la cadena pra vovler a recibir el siguiente comando.
      comando = "";
    }

    Hay dos botos en el ejecutable de este código en Arduino.

    Si pulsa un botón, por ejemplo, botón 2, desde el puerto serie envía hacia el PC y lo lee C# el valor 11729A1 en este caso.

    Cuando C# haya recibido este valor, 17729A1. C# envía a Arduino por el puerto serie este valor llamado OK1.

    Arduino lee OK1, sabe cual le corresponde, entonces, acto seguido, Arduino envia los bytes a recibir por el puerto serie a C#.

    Es una foto, en el cual, C# lo graba al disco duro. Ya esta parte hice un ejemplo que puedes ver aquí para que te hagas una idea de como guardar una imagen al ordenador o PC.

    using System;
    using System.Diagnostics;
    using System.IO;
    using System.IO.Ports;
    
    namespace Recibir_archivo_desde_Arduino_consola
    {
        class Program
        {
            static void Main(string[] args)
            {
                string COM = "";
    
                // Tamaño ventana consola.
                Console.WindowWidth = 55; // X. Ancho.
                Console.WindowHeight = 15; // Y. Alto.
                Console.Title = "Recoger foto desde Arduino y crearlo en el disco duro"; // Título de la ventana.
    
                // Crear un nuevo objeto SerialPort con la configuración predeterminada.
                SerialPort 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. 115200.
                Puerto_serie.Parity = Parity.None; // Paridad.
                Puerto_serie.DataBits = 8; // Bits de datos.
                Puerto_serie.StopBits = StopBits.One; // Bits de parada.
                Puerto_serie.Handshake = Handshake.None; // Control de flujo.
    
                // Establecer la lectura / escritura de los tiempos de espera.
                Puerto_serie.ReadTimeout = -1; // 500.
                Puerto_serie.WriteTimeout = -1; // 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.");
                    Console.ReadKey(); // Pulse cualquier tecla para salir.
                }
    
                catch (UnauthorizedAccessException e)
                {
                    Console.WriteLine(e);
                }
                Puerto_serie.DataReceived += new SerialDataReceivedEventHandler(DataReceivedHandler);
    
                Console.WriteLine("Esperando datos desde Arduino...");
                Console.Read();
                Puerto_serie.Close(); // Cerrar puerto.
            }
    
            private static void DataReceivedHandler(object sender, SerialDataReceivedEventArgs e)
    
            {
                try
                {
                    SerialPort sp = (SerialPort)sender;
                    int contador = 0;
                    byte[] datosArray = new byte[18000];
    
                    while (contador < datosArray.Length)
                    {
    
                        contador += sp.Read(datosArray, contador, datosArray.Length - contador);
    
                        Console.SetCursorPosition(10, 2);
                        Console.Write("Datos recibidos:  {0}", contador);
                        Console.WriteLine("                   ");
    
                        if (contador == 17729)
                        {
                            Console.WriteLine();
                            Console.WriteLine("Creando archivo al disco duro...");
                            File.WriteAllBytes("fotón.jpg", datosArray); // Crear archivo en el disco duro.
                            Console.WriteLine();
                            Console.WriteLine("Archivo creado. Ejecutando imagen.");
                            Process.Start("fotón.jpg"); // Ejecutar visualizador de imágenes.
                            Console.WriteLine();
                            Console.WriteLine("Imagen ejecutada.");
                            Console.WriteLine();
                            Console.ForegroundColor = ConsoleColor.Yellow; // Letras amarillas.
                            Console.WriteLine("FIN DE PROGRAMA.");
                            Console.ForegroundColor = ConsoleColor.Gray; // Letras grises otra vez.
                        }
                    }
                }
    
    
                catch (TimeoutException)
                {
                    //maybe increase ReadTimeout or something, use exponential backoff, your call
                }
    
                catch (IOException)
                {
                   // Console.WriteLine("La operación de E/S se anuló por una salida de subproceso o por una solicitud de aplicación.");
                }
            }
        }
    }

    Al ejecutar el programa me ejecuta bien. Pulso el botón de Arduino y me aparece esto abajo.

    Si vuelvo a pulsar me aparece esto otro abajo.

    ¿Alguna idea para continuar este proyectito?

    Saludos y muchas gracias Walter.


    http://electronica-pic.blogspot.com


    • Editado Metaconta lunes, 13 de marzo de 2017 7:55
    lunes, 13 de marzo de 2017 7:46
  • Hola de nuevo:

    Me funciona lo de crear la foto, pero ocurre cosas que no quiero, por ejemplo, me crea foto una y otra vez, es decir, que cada cierto tiempo le envía un OK1 a Arduino y responde recibiendo fotos, cada dos por tres y se me llena la pantalla de ella. Como que hice sin querer un bucle repetitivo sin fin.

    He modificado el código de C# y es este.

    using System;
    using System.Collections.Generic;
    using System.Linq;
    using System.Text;
    using System.Threading.Tasks;
    using System.IO.Ports; // No olvidar.
    using System.IO;
    using System.Diagnostics;
    
    namespace Recibir_archivo_desde_Arduino_consola_05
    {
        class Program
        {
            enum ESTADOS { LEYENDOCANTIDAD, LEYENDOCODIGO, FIN }
            static ESTADOS estado = ESTADOS.LEYENDOCANTIDAD;
            static int cantidadBytes;
            static StringBuilder sb = new StringBuilder();
    
            static void Main(string[] args)
            {
                Console.Title = "Título de la ventana.";
    
                SerialPort mySerialPort = new SerialPort("COM4");
    
                mySerialPort.BaudRate = 115200;
                mySerialPort.Parity = Parity.None;
                mySerialPort.StopBits = StopBits.One;
                mySerialPort.DataBits = 8;
                mySerialPort.Handshake = Handshake.None;
                mySerialPort.RtsEnable = true;
    
                mySerialPort.DataReceived += new SerialDataReceivedEventHandler(DataReceivedHandler);
    
                mySerialPort.Open();
    
                Console.WriteLine("Pulse cualquier tecla para salir...");
                Console.WriteLine();
                Console.ReadKey();
                mySerialPort.Close();
            }
    
            private static void DataReceivedHandler(object sender, SerialDataReceivedEventArgs e)
            {
                SerialPort sp = (SerialPort)sender;
                string indata = sp.ReadExisting();
    
                foreach (char item in indata)
                {
                    switch (estado)
                    {
                        case ESTADOS.LEYENDOCANTIDAD:
                            if (char.IsDigit(item))
                            {
                                sb.Append(item);
                            }
                            else if (item == 'A')
                            {
                                cantidadBytes = int.Parse(sb.ToString());
                                sb.Clear();
                                sb.Append(item);
                                Console.WriteLine("Tamaño: " + cantidadBytes + " Bytes.");
                                estado = ESTADOS.LEYENDOCODIGO;
                            }
                            else
                            {
                                Console.WriteLine("Error (Carácter recibido: {0})", item);
                                estado = ESTADOS.FIN;
                            }
                            break;
    
                        case ESTADOS.LEYENDOCODIGO:
                            if (char.IsDigit(item))
                            {
                                sb.Append(item);
                                Console.WriteLine("Foto: " + sb.ToString() + ".");
                                estado = ESTADOS.FIN;
                            }
                            else
                            {
                                Console.WriteLine("Error (Carácter recibido: {0})", item);
                                estado = ESTADOS.FIN;
                            }
                            break;
    
                        case ESTADOS.FIN:
                            // Console.WriteLine("Listo.");
                            bool verificado = true;
    
                            sp.Write("OK1");
    
    
    
                            if (verificado == true)
                            {
                                int contador = 0;
                                byte[] datosArray = new byte[cantidadBytes];
    
                                while (contador < datosArray.Length)
                                {
    
                                    contador += sp.Read(datosArray, contador, datosArray.Length - contador);
    
                                    Console.SetCursorPosition(10, 6);
                                    Console.Write("Datos recibidos:  {0}", contador);
                                    Console.WriteLine("                   ");
    
                                    if (contador == cantidadBytes)
                                    {
                                        Console.WriteLine();
                                        Console.WriteLine("Creando archivo al disco duro...");
                                        File.WriteAllBytes("fotón.jpg", datosArray); // Crear archivo en el disco duro.
                                        Console.WriteLine();
                                        Console.WriteLine("Archivo creado. Ejecutando imagen.");
                                        Process.Start("fotón.jpg"); // Ejecutar visualizador de imágenes.
                                        Console.WriteLine();
                                        Console.WriteLine("Imagen ejecutada.");
                                        Console.WriteLine();
                                        Console.ForegroundColor = ConsoleColor.Yellow; // Letras amarillas.
                                        Console.WriteLine("FIN DE PROGRAMA.");
                                        Console.ForegroundColor = ConsoleColor.Gray; // Letras grises otra vez.
                                    }
                                }
    
                                verificado = false;
                            }
    
                            break;
                    }
                }
    
                Console.WriteLine("Dato recibido:");
                Console.Write(indata);
            }
        }
    }
    

    ¿Alguna ayuda?

    Saludos.


    http://electronica-pic.blogspot.com

    lunes, 13 de marzo de 2017 8:59