Codigo que funcionaba hace unos dìas, ahora no. SOLUCIONADO

Hola, Buenos dìas a todos:

Hoy les molesto pues tengo un còdigo que hace un par de semanas me funcionaba perfectamente, pero ahora no me funciona, a pesar de que compila sin errores, no funciona.

Se trata de uno de los ejercicios planteados en un libro de pràcticas de Arduino, por el que estoy preparàndome.

El còdigo es muy simple, se trata de enviar la palabra "encender" por el monitor serial para encender el Led asociado al pin 13 de la placa Arduino, sin embargo, cuando escribo "apagar", se debe apagar el Led.

Descarto desde ya la placa, (Arduino UNO R3), ya que siendo el led del pin-13 On-Board, no hay ningùn circuito conectado.

Tambièn he probado otros còdigos y funciona. Realmente, no logro entender que puede estar pasando, estoy utilizando la misma placa en el mismo ordenador de siempre....

Me gustarìa, si alguno ha tenido una experiencia similar, me diera alguna idea o sugerencia. Le dejo el còdigo màs abajo.

Les agradezco de antemano vuestra atenciòn y les deseo buenos dìas y buen trabajo!!!!

/*---------------------------------------------------
   Escritura Serial (variante)
   --------------------------------------------------
   Consiste en escribir "encender"  por la consola serial del ordenador
   para encender el led, si escribo "apagar", se debe apagar el led que estarà en el
   pin 13
*/

//-----------------------------------------------------
//Declarar puertos de entrada y salida, variables, etc.
//-----------------------------------------------------
int led = 13;               //declaro que el led estarà conectado al pin 13
boolean encendido = false;  //declaro una bandera "encendido" que inicializo como false=led apagado
String leer;                //declaro la cadena donde se almacena la palabra

//------------------------------------
//Funciòn principal o de configuraciòn
//------------------------------------

void setup()
{
  Serial.begin (9600);        //inicializo la comunicaciòn serial a 9600 baudios
  pinMode (led, OUTPUT);      //inicializo el pin led=13 como salida
}

//--------------------
//Funciòn cìclica
//--------------------

void loop()
{

  leer = Serial.readString();                         //mando a leer lo que hay escrito en la consola serial
  Serial.println(leer);                               //lo escribo para verlo en la consola serial
  if ( (leer == "encender") && (encendido == false) ) //pregunto si la letra es "encender" y si el led estaba apagado
  {
    digitalWrite (led, HIGH);                         //si se cumplen las dos condiciones entonces enciendo el led
    encendido = true;                                 //cambio la bandera encendido a verdadero
  }
  else if ( (leer == "apagar") && (encendido == true) ) //pregunto si escribio "apagar" con el led encendido
  {
    digitalWrite(led, LOW);                            //si se cumplen las dos condiciones, apago el led
    encendido = false;                                 //y vuelvo a cambiar la bandera y pongo encendido como falso
  }

}

// Fin del programa

Hola compañero,

veamos el hecho que no funcione puede ser.......

  • Instalación de un programa en el PC que haya "tocado" los drivers. Pero según me dices, están bien porque otros ejemplos te han funcionado

  • Cambio en la velocidad de transmisión de datos, que por algún motivo, haya cambiado (¿actualizaciones?).... no se

  • A veces a los SO (Sistemas Operativos) les da por "fastidiarse" si se conectan otros aparatos al puerto USB o bien conectamos el Arduino a otro USB.... es posible que lo interprete como otro tipo de dispositivo.

.....

Por ahora se me ocurre eso.... No se si alguien más puede aportar algo......

Hola KIKOIGO:

Gracias por responder. Si que es raro realmente lo que està sucediendo.

En cuanto a lo que dices, no he instalado nada nuevo en el ordenador de reciente, que yo recuerde.....Win10 puede hacer lo que se le antoje sin decirnos nada.

A ver si esto pudiera ser: hace unos dìas copiè todos los ejercicios que tengo realizados para otra carpeta diferente, con el objetivo de liberar espacio en "Mis Documentos", donde, por definiciòn està la carpeta creada por Arduino, pero al ver que, para salvar nuevos còdigos, la volvìa a crear, regresè los que habìa trasladado de nuevo hacia èsta.

Pudiera ser?, no sè, pues otros ejemplos que tambièn movì, funcionan!!!

Ahora me dì un salto a casa en la hora de almuerzo, y probè otro parecido y no me funiona tampoco.....que tienen en comun?... bueno ambos còdigos usan: Serial.readString();

No se si esto arroje luz al problema, yo mas que nada veo obscuridad, luego de esta segunda prueba.

Espero que otros colegas puedan aportar algo.

Gracias a todos.

Haz una prueba,

Crea un sketch nuevo en blanco y haz un copia pega del codigo, a ver si así funciona, a veces el sketch por lo que sea se corrompe y hace cosas raras.

OK Danicap:

Voy a probar a hacer eso que sugieres, lo copio y lo pego en uno en blanco.....Si no funciona, y visto que no hay tanto que teclear, lo reescribo todo de nuevo y veremos.

Les tendrè al tanto.

Muchas gracias!!

A mi no me gusta algo, pero es por trabajar correctamente según intento hacerlo siempre.
Aporte el cambio que creo necesario.
Los cambios de encendido == true por simplemente encendido no son importantes.
Solo me parece redundante ponerlo y por eso yo no los pongo.
lo mismo encendido == false por !encendido.

void loop()
{
  if (Serial.available()>0) {
	  leer = Serial.readString();                         //mando a leer lo que hay escrito en la consola serial
	  Serial.println(leer);                               //lo escribo para verlo en la consola serial
	  if ( leer == "encender" && !encendido ) //pregunto si la letra es "encender" y si el led estaba apagado
	  {
	    digitalWrite (led, HIGH);                         //si se cumplen las dos condiciones entonces enciendo el led
	    encendido = true;                                 //cambio la bandera encendido a verdadero
	  }
	  
	  if ( leer == "apagar" && encendido ) //pregunto si escribio "apagar" con el led encendido
	  {
	    digitalWrite(led, LOW);                            //si se cumplen las dos condiciones, apago el led
	    encendido = false;                                 //y vuelvo a cambiar la bandera y pongo encendido como falso
	  }
  }

}

// Fin del programa

Gracias Surbyte:

Tomo nota de tu consejo, lo tendrè en cuenta, al principio no entendì bien, pero cuando vì tu còdigo me quedò mas claro, esta noche lo voy a probar y les cuento.

De todas formas queda el misterio del porquè antes funcionaba y ahora no. Aparte de la redundancia que señalas, no veo errores en un còdigo tan simple.

Esperamos a ver si con las sugerencias que han aportado ustedes se resuelve, sino esperar a ver si otros tienen mas ideas.

Otra vez gracias,
Saludos,
Juan Carlos

el gran cambio GRAN es este

 if (Serial.available()>0) {

nunca olvides usarlo.

Gracias Surbyte:

Es una gran duda que tengo desde mis inicios, pues en muchos còdigos que he visto "por ahì" no lo ponen, de hecho en este libro que estoy siguiendo no lo utilizan nunca.
No sè por què, serà que hasta ahora no he tenido còdigos complejos, y que funcionan sin el available.
Creo que voy a tomar nota y ponerlo siempre.

A propòsito de mi problema, he pensado reinstalar de nuevoe el IDE, desde el sitio oficial, a lo mejor se resuelve asì el problema, que creen ustedes?

Otra vez gracias,

Hola de nuevo a todos:

Sigo con el problema. A pesar de que hice todas las sugerencias que me aportaron ustedes, como son:

-incluir siempre el serial.available
-comparar el flag con encendido o !encendido
-teclear de nuevo todo el còdigo...

Hecho todo esto y sigue sin funcionar...!??!??

Les dejo el còdigo, esta vez les pido a quien tenga algo de tiempo, que lo suba a su tarjeta Arduino y ver si les corre, no necesitan nada de circuiterìa pues usa el pin 13 de arduino.....

A ver si a ustedes les funciona...

Gracias

/*ESCRITURA SERIAL
   Variante con sugerencias del foro arduino en español.
   Se trata de escribir "encender" por la consola serial del pc
   para encender el led on-board del pin 13, sin embargo al llegar la palabra
   "apagar" el led debe apagarse.
   Sugerencias del foro:
      -incluir siempre el serial.available
      -comparar el flag con encendido o !encendido
      -teclear de nuevo todo el còdigo
*/

int led = 13;              //declaro que usarè el pin 13 de arduino
boolean encendido = false; //declaro una bandera "encendido" que inicializo como apagada
String leer;               //declaro la cadena donde se almacena la palabra escrita


void setup()
{
  Serial.begin(9600);      //inicializo la comunicaciòn serial a 9600 baudios
  pinMode(13, OUTPUT);     //inicializo el pin 13 como salida
}

void loop()
{
  if (Serial.available() > 0)            //si llega algùn dato por la consola serial...
  {
    leer = Serial.readString();          //mando a leer lo que hay en el monitor serial
    Serial.println(leer);                 //lo escribo para verlo en pantalla del monitor
    if (leer == "encender" && !encendido) //pregunto si la palabra es "encendido" y la bandera es falso
    {
      digitalWrite(led, HIGH);             //si se cumplen ambas condiciones, enciendo el led
      encendido = true;                    //activo la bandera
    }
    else if (leer == "apagar" && encendido) //si no, pregunto entonces si llega "apagar" y estaba encendido
    {
      digitalWrite(led, LOW);               // si se cumple, apago el led
      encendido = false;                    //apago la bandera
    }
  }
}

Hola colegas:

Una muestra de que la placa Arduino funciona es el hecho que hice una variante al còdigo anterior y en vez de leer una cadena o "string" le mando a leer una variable del tipo "char".... de manera que si llega una "e" se enciende el led, y si llega una "a" lo apaga.

Y este si funciona, por lo que descarto la placa. El problema està en el còdigo que lee el "String"

Alguna otra sugerencia.....yo necesito leer una palabra, de aquì que insista en usar "String"

Gracias a todos

Saludos,
Juan Carlos

Bueno me animaste a descubrir que ocurre y esto es lo que ocurre.
Serial.readString() lee todo, incluidos CR y LF los caracteres de Retorno de Carro CR y Line Feed LF
Asi que jamás va a funcionar a menos que comparas encender con leer menos dos caracteres.

Esto si funciona en mi caso, usando Termite como terminal Serie.

void loop()
{

  if (Serial.available()>0) {
      leer = Serial.readStringUntil('\r');                        //mando a leer lo que hay escrito en la consola serial
      Serial.println(leer);  
      Serial.println(leer.length());                             //lo escribo para verlo en la consola serial
      if (leer == "encender" && !encendido)               //pregunto si la letra es "encender" y si el led estaba apagado
      {
        digitalWrite (led, HIGH);                         //si se cumplen las dos condiciones entonces enciendo el led
        encendido = true;                                 //cambio la bandera encendido a verdadero
      }
      if (leer == "apagar" && encendido)                  //pregunto si escribio "apagar" con el led encendido
      {
        digitalWrite(led, LOW);                            //si se cumplen las dos condiciones, apago el led
        encendido = false;                                 //y vuelvo a cambiar la bandera y pongo encendido como falso
      }
  }
} // Fin del programa

Es muy dependiente del programa terminal que uses.
Con el IDE no lo probé pero con Sublime Text y su Terminal no funciona, pero si con Termite (programa para visualizar info serial.).

Serial.readString() lee todo, incluidos CR y LF los caracteres de Retorno de Carro CR y Line Feed LF

El CR y LF sienmpre dando problemas jeje.

A parte de lo que comenta surbyte también puedes leer caracter a caracter y concatenarlos en un string, así no te cogerá el CR ni el LF.

Saludos!

Hola Buenos dìas Danicap:

Puedes explicar mejor como leo caracter a caracter?? no es eso precisamente lo que hace la funciòn String?? leer todos los caracteres hasta el retorno del carro? Puedieras ilustrarme mejor esto, quizàs sea la soluciòn.

Yo uso el monitor serial propio de Arduino (el botòn de arriba a la derecha), No tengo Termite ni el otro que menciona Surbyte. Esos los verè màs adelante.

Cualquier otra sugerecia...?
Y si reinstalo el IDE...?? se resolverà el problema?? recuerden que el programa funcionaba hace un par de semanas.

Gracias a todos

Buenos dìas Surbyte:

Entiendo lo que planteas, aunque no tengo esos terminales que comentas. Los estudiarè.

Debo precisar una cosa, luego de haber incluìdo el "serial.available", el programa "lee" lo que hay en el monitor serial perfectamente, de hecho lo "escribe" y lo veo de nuevo en el monitor serial. De ahi que la parte de la lectura funciona.

Hasta ahi todo ok.

El problema està en que no enciende el led cuando se escribe "encender"....tampoco "apagar" surtirà efecto...jejeje..

Creo que esta aclaraciòn es importante.

Gracias a todos

Puedes explicar mejor como leo caracter a caracter?? no es eso precisamente lo que hace la funciòn String?? leer todos los caracteres hasta el retorno del carro? Puedieras ilustrarme mejor esto, quizàs sea la soluciòn.

Si mira, la diferencia es que leyendo caracter a caracter no leeras el retorno de carro ni el salto de linea.
Yo lo hago de la siguiente forma:

String cadena = "";
if (Serial.available()>0)
{
     char c = Serial.read();
     cadena.concat(c);
}

En cadena tendrás ya toda la cadena de caracteres que le pases por el serial

El problema està en que no enciende el led cuando se escribe "encender"....tampoco "apagar" surtirà efecto...jejeje..

lo que surbyte comenta es que tendrias que comparar algo del estilo, no sé si esto se puede hacer exactamente así, que confirme surbyte que lo sabrá mejor.

if (leer == "encender\r\n")
if (leer == "apagar\r\n")

No supe expresar la alternativa de Danicap

if (leer == "encender\r\n")

if (leer == "apagar\r\n")

muy buen aporte.
Tampoco conocía
Serial.readStringUntil('\r');
asi que pasa a mi conocimiento. Por eso digo que todos los días se aprende algo nuevo.

Programa Termite version 3.3 - complete setup (294 KiB)
Es muy liviano, y muy facil de usar. Si lo tienes ocupando el puerto e intentas subir un sketch dara ERROR el IDE porque el puerto COM esta tomado por Termite.
Simplemente lo apagas o bien tiene una opcion en la barra que ves PUERTO VELOCIDAD EN BAUDS etc y le das click y queda desactivado.

Hola a Todos!:

Finalmente resuelto el problema!!!

Gracias a todas las sugerencias de ustedes pude ir mejorando mi còdigo hasta llevarlo a hacer lo que se esperaba.

Pero la soluciòn definitiva fue la de incluir la instucciòn:

leer = Serial.readStringUntil('\r');

Esta, unida a las otras que habìamos visto ayer hicieron que el programa estè funcionando al 100%

Quiero agradecer sobre todo a Surbyte y a Danicap, pues sin sus sugerencias no hubiera sacado adelante el programa

Tambien a los 138 "readers" por tomarse su tiempo. Ahora les dejo el còdigo como està funcionando.

Parafraseando a Surbyte: "...que todos los dìas se aprende algo nuevo"

Muchas gracias y buen trabajo!!!!

/*ESCRITURA SERIAL
   Variante con sugerencias del foro arduino en español.
   Se trata de escribir "encender" por la consola serial del pc
   para encender el led on-board del pin 13, sin embargo al llegar la palabra
   "apagar" el led debe apagarse.
   Sugerencias del foro:
      -incluir siempre el serial.available
      -comparar el flag con encendido o !encendido
      -teclear de nuevo todo el còdigo
  Rev.1: Otra sugerencia del forum:
      -usar "Serial.readStringUntil('\r')>>>>>SOLUCION DEL PROBLEMA
*/

int led = 13;              //declaro que usarè el pin 13 de arduino
boolean encendido = false; //declaro una bandera "encendido" que inicializo como apagada
String leer;               //declaro la cadena donde se almacena la palabra escrita


void setup()
{
  Serial.begin(9600);      //inicializo la comunicaciòn serial a 9600 baudios
  pinMode(13, OUTPUT);     //inicializo el pin 13 como salida
}

void loop()
{
  if (Serial.available() > 0)            //si llega algùn dato por la consola serial...
  {
    leer = Serial.readStringUntil('\r');  //mando a leer lo que hay en el monitor serial HASTA "return"
    Serial.println(leer);                 //lo escribo para verlo en pantalla del monitor
    if (leer == "encender" && !encendido) //pregunto si la palabra es "encendido" y la bandera es falso
    {
      digitalWrite(led, HIGH);             //si se cumplen ambas condiciones, enciendo el led
      encendido = true;                    //activo la bandera
    }
    else if (leer == "apagar" && encendido) //si no, pregunto entonces si llega "apagar" y estaba encendido
    {
      digitalWrite(led, LOW);               // si se cumple, apago el led
      encendido = false;                    //apago la bandera
    }
  }
}