Prueben este ejemplo y me cuentan sus experiencias - Encender Led

Hola compañerOs:

Aquí probando Arduino UNO r3 con el Monitor serie del propio Arduino IDE 2.0.3.

Suelo hacer que hago pruebas de crear mi propio interfaz para encender o apagar un Led de ejemplo, el típico Led 13 de Arduino UNO enviando comandos llamado Luz_ON y el otro comando Luz_OFF desde el Monitor serie.

Tiene que estar conectado físicamente por USB Arduino UNO. Siempre y cuando uses este código de Arduino, lo que hace es recibir comandos desde el puerto serie y apaga o enciende el Led 13 como dije antes.

Código de Arduino:
C:
const byte Led = 13;   // Declaramos la variable pin del Led.
char caracter;
String comando;

void setup()
{
  pinMode(Led, OUTPUT);  // Inicializa el pin del LED como salida:
  Serial.begin(115200);     // Puerto serie 115200 baudios.
}

void loop()
{
  /*
    Voy leyendo carácter a carácter lo que se recibe por el canal serie
    (mientras llegue algún dato allí), 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. El delay 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í.
  */

  // Si le llega el mensaje Luz_ON.
  if (comando.equals("Luz_ON") == true)
  {
    digitalWrite(Led, HIGH); // Enciende el Led 13.
    Serial.write("ON - Led encendido.");    // Envía este mensaje a C++.
  }

  // Si le llega el mensaje Luz_ON.
  if (comando.equals("Luz_OFF") == true)
  {
    digitalWrite(Led, LOW); // Apaga el Led 13.
    Serial.write("OFF - Led apagado. ");  // Envía este mensaje a C++.
  }

  // Limpiamos la cadena para volver a recibir el siguiente comando.
  comando = "";
}

Para aquellas personas que no quiera instalar emuladores como el Proteus para hacer pruebas de este tipo o no dispone Arduino UNO en este momento, hice un programa similar que exactamente lo mismo del código de Arduino indicado arriba.

Pueden descargar el archivo hecho con C# que hace de emulador de Arduino UNO, solo encender y apagar Led 13, recibe y envía órdenes del comando. Responde como si estuviese Arduino conectado físicamente.

Deben tener puertos series virtuales.

Versiones compiladas del .net 4.5.2, 4.7.2 y 4.8 solo para Windows.
Versiones compiladas del .net 6.0 y 7.0 para Windows, Mac y Linux.

Así nadie se queda sin probar nada.
 

Adjuntos

  • Emulador.zip
    394.8 KB · Visitas: 2
Última edición por un moderador:
Funciona pero. . . . recomendaría usar startsWith en lugar de equals, no es que no puedas usarlo así, es solo que tienes que cambiar la consola a No Line Ending porque tienes el fin de línea en medio invalidando la comparación. O le agregas el \r\n al final, realmente depende de como lo implementes. ¿cuál era la duda en sí?
 
Última edición:
Buenas compañero.

Este código, tal cual como lo vez, es sacado de un libro Arduino.

Puedes poner un buen ejemplo completo. En cuanto al \r\n, si el autor del libro no lo ha incluido, porque no es necesario.

Otra gente opinan, que hasta "comando", mejor borrarlo en cada if.

Por ejemplo:
C:
  // Si le llega el mensaje Luz_ON.
  if (comando.equals("Luz_ON") == true)
  {
    digitalWrite(Led, HIGH); // Enciende el Led 13.
    Serial.write("ON - Led encendido.");    // Envía este mensaje a C++.
      comando = "";
  }

  // Si le llega el mensaje Luz_ON.
  if (comando.equals("Luz_OFF") == true)
  {
    digitalWrite(Led, LOW); // Apaga el Led 13.
    Serial.write("OFF - Led apagado. ");  // Envía este mensaje a C++.
      comando = "";
  }

Si quieren el código fuente de C#, se los puedo pasar.

Gracias por comentar.
 
Última edición:
Funciona pero. . . . recomendaría usar startsWith en lugar de equals, no es que no puedas usarlo así, es solo que tienes que cambiar la consola a No Line Ending porque tienes el fin de línea en medio invalidando la comparación. O le agregas el \r\n al final, realmente depende de como lo implementes. ¿cuál era la duda en sí?
Sobre startsWitch y endWitch. Vete a saber el motivo por el cual en su libro no lo hizo.


Parece que es mejor lo que dices para hacer el código más eficiente.
 
Hola @DJT3:

Hace años he comprobado las ventajas y desventajas o diferencias entre #define y const en el cual te parece mejor #define y a mi const. Como no tenía las cosas claras hace años, pues me puse a buscar información y veo que todavía la gente se informa de esto. En general, Arduino recomiendo usar const.

Ver enlace que es bueno que se lea todo al detalle.

A la hora de ver a la gente hacer programas de Arduino, se puede hacer de varias maneras. Hay personas que usan esta forma.

Edito:
Me olvidé comentar que las constantes, se escribe en mayúsculas.

C++:
const byte BOTON1 = 1;
const byte BOTON2 = 2;
const byte BOTON3 = 3;

Si te topas con una variable de una palabra, para tener buenas prácticas de programación, se escribe así con todas las letras de las variables en minúsculas.

C++:
byte boton = 4;

Si incluye varias palabra en la misma variable se escribe o expresa así: Primera letra en minúsculas y las demás palabras en mayúsculas, así entiendes una frase en la variable.

C++:
byte esteEsMiBoton = 4;

Si es una constante, una sola palabra se escribe con mayúscula así:

C++:
const byte BOTON = 4;

Si es una frase de esta forma:

C++:
cont byte ESTE_ES_MI_BOTON = 4;

Está claro que const gasta memoria RAM, mejor dejarlo en la memoria Flash.
C++:
const PROGMEM byte LuzFondo = 10;

Si incluyes textos tanto para enviar al puerto serie o llevarlo a un LCD, de esta manera se queda en la RAM.
C++:
lcd.print("Nombre de Reles:    ");

Mejor dejarla en la Flash como indica abajo, poniendo la F().
C++:
lcd.print(F("Nombre de Reles:    "));

Hay muchos problemas hoy en día sobre si la constante es una variable o no. Variable se llama así proque su valor varía, constante const mucho no lo llaman variable porque su valor no varía.

Saludos.
 
Última edición:
Me olvidé, pongo el código fuente de C# modo consola.

C#:
using System;
using System.IO.Ports;
using System.IO;
using System.Text;

namespace Emulador_Puerto_Serie_Arduino_02
{
    internal class Program
    {
        static string comando;
        static SerialPort Puerto_serie;
        static string COM = "";
        static void Main(string[] args)
        {
            
            string titulo = "Emulador Arduino. Beta v0.2";

            //StringComparer comparaString = StringComparer.OrdinalIgnoreCase;
            //Thread readThread = new Thread(Leer);

            #region Configuración ventana.
            // Título de la ventana.
            Console.Title = titulo;

            // Tamaño de la ventana, x, y, o ancho y alto.
            const byte ANCHO_X = 80, ALTO_Y = 20;
            Console.SetWindowSize(ANCHO_X, ALTO_Y);

            // Color de fondo.
            Console.BackgroundColor = ConsoleColor.Black;

            // Color de las letras.
            Console.ForegroundColor = ConsoleColor.Green;

            // Limpiar pantalla y dejarlo todo en color de fondo.
            Console.Clear();

            // Visible el cursor.
            Console.CursorVisible = true;
            #endregion

            #region Configuración puerto serie.
            // Crear un nuevo objeto SerialPort con la configuración predeterminada.
            Puerto_serie = new SerialPort();

            // Codificar a UTF-8 para que se vean bien las tildes, ñ y otros caracteres.
            Puerto_serie.Encoding = Encoding.UTF8;

            // Obtenga una lista de nombres de puertos serie.
            string[] puertos = SerialPort.GetPortNames();

            Console.WriteLine("Se encontraron los siguientes puertos series:");

            // Muestre el nombre de cada puerto en la consola.
            foreach (string puerto in puertos)
            {
                Console.WriteLine(puerto);
            }

            // 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(); // Limpiar pantalla.

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

            // Configuración del puerto serie.
            Puerto_serie.BaudRate = 115200;
            Puerto_serie.Parity = Parity.None;
            Puerto_serie.StopBits = StopBits.One;
            Puerto_serie.DataBits = 8;
            Puerto_serie.Handshake = Handshake.None;
            Puerto_serie.RtsEnable = true;

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

            // Muestra otra vez título de la ventana más el puerto asignado.
            Console.Title = titulo + " - COM: " + COM;

            // Comprueba si puede abrir el puerto serie.
            try
            {
                Puerto_serie.Open(); // Abrir el puerto serie.
            }

            // En caso que diera algún error como que no encuentra el puerto seleccionado
            // muestra una excepción.
            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.
                Environment.Exit(1); // Salir de la aplicación.
            }

            // Se ha denegado el acceso al puerto.
            catch (UnauthorizedAccessException)
            {
                Console.ForegroundColor = ConsoleColor.Red; // Texto en rojo.
                Console.CursorVisible = false;
                Console.SetCursorPosition(16, 6);
                Console.WriteLine(@"Se ha denegado el acceso al puerto " + Puerto_serie.PortName +
                                "" +
                                "\nPuede estar el puerto escogido en uso.\n" +
                                "Elija un puerto diferente o desactiva el que está en uso.");
                Console.ReadKey();   // Pulse cualquier tecla.
                Environment.Exit(1); // Salir de la aplicación.
            }
            #endregion


            while (true)
            {
                try
                {
                    comando = Puerto_serie.ReadLine();
                }
                catch (TimeoutException)
                {
                    // Se excedió el tiempo de espera de la operación.
                }

                if (comando == "Luz_ON")
                {
                    // Enciende el Led.
                    Console.ForegroundColor = ConsoleColor.Green;

                    Console.SetCursorPosition(0, 0);
                    Console.WriteLine("\u2588\u2588\u2588\u2588");
                    Console.WriteLine("\u2588\u2588\u2588\u2588");
                    Console.WriteLine("\u2588\u2588\u2588\u2588");
                    Console.SetCursorPosition(0, 4);
                    Console.WriteLine();
                    Console.Write("ON - Led encendido.");

                    // devuelve el resultado
                    Puerto_serie.WriteLine("ON - Led encendido. ");

                    // Limpiamos la cadena para volver a recibir el siguiente comando.
                    comando = "";
                }

                // Si le llega el mensaje Luz_OFF.
                if (comando == "Luz_OFF")
                {
                    // Apaga el Led.
                    Console.ForegroundColor = ConsoleColor.DarkGreen;

                    Console.SetCursorPosition(0, 0);
                    Console.WriteLine("\u2588\u2588\u2588\u2588");
                    Console.WriteLine("\u2588\u2588\u2588\u2588");
                    Console.WriteLine("\u2588\u2588\u2588\u2588");
                    Console.SetCursorPosition(0, 4);
                    Console.WriteLine();
                    Console.Write("OFF - Led encendido.");

                    // devuelve el resultado
                    Puerto_serie.WriteLine("OFF - Led apagado. ");

                    // Limpiamos la cadena para volver a recibir el siguiente comando.
                    comando = "";
                }
            }
        }
    }
}

Por cierto. En cuanto al código de Arduino. El que sepa hacerlo lo mejor posible el ejemplo del primer post, que lo haga y publique por aquí para sacar la mejor versión. Ya que lo quiero como estandar para hacer pruebas sobre enviar y recibir datos por el puerto.

Gracias.
 
Funciona pero. . . . recomendaría usar startsWith en lugar de equals, no es que no puedas usarlo así, es solo que tienes que cambiar la consola a No Line Ending porque tienes el fin de línea en medio invalidando la comparación. O le agregas el \r\n al final, realmente depende de como lo implementes. ¿cuál era la duda en sí?
A lo mejor con StartsWith y EndsWith se en la parte de transmisión y la parte de recepción sea la mejor opción como dices en vez de equal.

¿Por qué lo crees exactamente?

En Arduino.

En C# también lo incluyen.
Captura2.JPG

C#:
    public partial class Form1 : Form
    {
        public Form1()
        {
            InitializeComponent();
        }

        private void _StartsWith_Click(object sender, EventArgs e)
        {
            string cadena1 = textBox1.Text.Trim();
            string cadena2 = textBox2.Text.Trim();

            label_Resultado_StartsWith.Text = cadena1.StartsWith(cadena2).ToString();
        }

        private void _EndsWith_Click(object sender, EventArgs e)
        {
            string cadena3 = textBox3.Text.Trim();
            string cadena4 = textBox4.Text.Trim();

            label_Resultado_EndsWith.Text = cadena3.EndsWith(cadena4).ToString();
        }
    }
 
Si vas a usar comparativa completa y la cadena en el Arduino no tiene en consideración el carácter de nueva línea, puede dar error, en la transmisión en tal caso en lugar de usar Puerto_serie.WriteLine solo usa Puerto_serie.Write para no agregar el \n extra al final.
 
En cuanto al no agregar \r\n, o simplemente agregarlo, no da error. Da igual si lo agregas o no, funciona igualmente bien.

Todo el tema del StartsWith y EndsWith sea la parte de la interfaz como C# o en Arduino, funciona bien.

Como dice arriba, usar lo del StartsWith y EndsWith que Equal. A pesar que el libro se usa Equal, aquí en el foro aconsejan los With.

Terminaré haciendo ejemplos aquí haber que pasa. Si es tan eficiente como dicen.

C#:
// Variable.
string stringOne = "HTTP/1.1 200 OK";

if (stringOne.StartsWith("HTTP/"))
{
    Console.WriteLine("Got an OK from the server");
}

if (stringOne.Substring(9) == "200 OK")
{
    Console.WriteLine("Got an OK from the server");
}

// Pulse cualquier tecla para salir.
Console.ReadKey();

C++:
void setup() {
  Serial.begin(9600);

  String myString = "ArduinoGetStarted.com";
  String myString2 = ".com";

  if (myString.endsWith(myString2))
    Serial.println("The string is ended with .com");
  else
    Serial.println("The string is NOT ended with .com");
}

void loop() {
}
 
Última edición:
Atrás
Arriba