Contador de tiempo

Buenas a todos, mi objetivo como bien indico es que se muestre un determinado texto y luego pasado ese tiempo cambie a otro y así sucesivamente hasta que llegue al final. Como es un ejercicio más grande he empezado a hacer el contador de tiempo por separado con un led (a fin de cuentas es igual).

int cont=0;

void setup() {
  pinMode(3,OUTPUT);
  pinMode(4,INPUT);

}

void loop() {
  for(cont=0; cont<=5; cont++) {
    if(digitalRead(4) == HIGH) { 
      digitalWrite(3, HIGH);      
  }
  if(cont>5 && cont<=10) {
    digitalWrite(3,LOW);

  if(cont>10 && cont<=15) {
    digitalWrite(3,HIGH);
  }
  }
  }
}

El problema que siempre se queda encendido no va cambiando. ¿Alguna idea?.
Saludos.

Esta es la razón por la que va mal, como colocas las llaves desorganizadas no ves donde terminan y crees que esta bien pero no es asi. Mira como esta tu código

void loop() {

  for(cont=0; cont<=5; cont++) {
      if(digitalRead(4) == HIGH) { 
        digitalWrite(3, HIGH);      
      }
      if (cont>5 && cont<=10) {
          digitalWrite(3,LOW);

          if (cont>10 && cont<=15) {
              digitalWrite(3,HIGH);
          }
      }
  }
}

Esto

if (cont>5 && cont<=10) {
          digitalWrite(3,LOW);

No se ejecuta jamás ya que estas dentro de un for() que va de 0 a 5, cuando se da la condición cont>5 dentro del for? Nunca

Y lo mismo con

          if (cont>10 && cont<=15) {
              digitalWrite(3,HIGH);
          }

Que además resultar estar dentro del anterior if, asi que menos que menos.

Además tu código no tiene un retardo como para ver de que hablas, asi que esto ocurrirá tan rápido que no aprecias nada.

No se que tiene que ver tu lectura de la entrada en toda la idea por eso no te propongo nada pero con mostrarte los errores tienes algo.
Además agrega un delay(1000); al final para ver los cambios.
Usa Serial.println(“Carteles indicativos”); para ir viendo los cambios y entendiendo que pasa.

Ya esta arreglado, todo funciona perfecto.

int cont=0;

void setup() {
  pinMode(2,OUTPUT);
  pinMode(3,OUTPUT);
}

void loop() {
  for(cont=0; cont<=15; cont++) {
    delay(1000);
    
    if(cont>=0 && cont<=5) {
      digitalWrite(2,HIGH);
      digitalWrite(3,LOW);
      delay(500);
      }
      
    if(cont>5 && cont<=10) {
      digitalWrite(2,LOW);
      digitalWrite(3,HIGH);
      delay(500);
      }
      
    if(cont>10 && cont<=15) {
      digitalWrite(2,HIGH);
      digitalWrite(3,HIGH);
      delay(500);
      }
  }
}

Gracias por la ayuda Surbyte.

:confused: ¿No les marea usar tantos if if if…? ¿Será que soy un maníatico tras años programando?
Bueno lo normal es que en programación si repites líneas estás escribiendo de más y puedes usar funciones u otra forma de planteamiento para quitarlo.

Es como si yo repitiese esto…
Es como si yo repitiese esto…
Es como si yo repitiese esto…

Si lo que buscas es programar unos leds en un orden, puedes establecerlo en un array. Con tu permiso Tygrecor te muestro otra forma de hacerlo. Si no te gusta al menos ves otra manera con menos líneas :grin: (Menos líneas si quitas los comentarios) :grin:

  • Sin variables globales
  • Uso del operador Mod para evitar los if

Ejemplo:

void setup() {
  pinMode(2,OUTPUT);
  pinMode(3,OUTPUT);
}

void loop() {
  //pasando de variables globales :)
  boolean steps[] = {true, false, true};
  byte index = 0;
  
  for( byte cont=0; cont<=15; cont++) {
    
    if( cont % 5 ) { //Usamos mod porque no es cuestion de ir poniendo mil if...
      digitalWrite(2,steps[index]);
      digitalWrite(3, !steps[index]);
      index = (index > 2) ? 0 : index+1; 
      
      //Nótese que si pusieramos index >= 2 nunca se encenderían ambos leds a la vez.
      //Siendo un índice mayor de la longitud del array va a retornar un false.
      //De esta forma alternamos los pasos y conseguimos de forma fácil: 
      // 1. Led encendido, Led apagado.
      // 2. Led apagado, Led encendido.
      // 3. Led encendido, Led encendido.
      
      delay(500);
    }    
  }
}

Igual tampoco haría esto así. No me gusta el for + delays teniendo la función millis() o librerías de timers, nunca usaría algo que provocase una interrupción en todo mi código salvo que específicamente buscase eso.

Por si no se entendió mi comentario o el planteamiento, si cambias la línea

index = (index > 2) ? 0 : index+1;

Por

index = (index == 2) ? 0 : index+1;

O

index = (index >= 2) ? 0 : index+1;

Comprobarás que las luces nunca se encienden a la vez, sino que se alternan.
Sé que es un planteamiento raro jugar con las posiciones que no existen de un array para un patrón led, pero era un ejemplo de reducción de líneas manteniendo tu orden de encendido.

El tema es el orden del array y la negación del pin 3
digitalWrite(3, !steps[index]);

Hola Tygrecor

Para enriquecer el panorama, y dentro de tu idea, ahi te va otra posibilidad:

void setup()
{
  pinMode(2,OUTPUT);
  pinMode(3,OUTPUT);
}

void loop()
{
  for(int cont=0; cont<=15; cont++)
  {
   
    if(cont<6)
    {
      digitalWrite(2,HIGH);
      digitalWrite(3,LOW);
    }
     
    else if(cont<11)
    {
      digitalWrite(2,LOW);
      digitalWrite(3,HIGH);
    }
     
    else if(cont>10)
    {
      digitalWrite(2,HIGH);
      digitalWrite(3,HIGH);
    }
    delay(1000);
  }
}

Si no vas a seguir un patrón muy largo en plan codificar luces para un árbol de navidad y sólo son estos pocos pasos puedes reducirlo a:

void setup(){
  pinMode(2,OUTPUT);
  pinMode(3,OUTPUT);
}

void loop(){
  for(byte cont=0; cont<=15; cont++){
    delay(1000);
    digitalWrite(2, (cont<6 || cont>10) ? HIGH : LOW);
    digitalWrite(3, (cont>5 || cont>10) ? HIGH : LOW);
    delay(500);
  }
}

Teniendo en cuenta que quieres un timer para mostrar textos cada X ¿Has mirado Timers? Así te quitas de encima las pruebas con los leds.

A mí me gusta la primera librería que sale en el listado, la de RBD::Timer, pero hay muchas: Library Timing (Playground)

@Tygrecor:

Se te va a quedar optimizado a tope.
Y hay mas,… si no quieres pasarte el bucle entero haciendo “digitalWrite()”, lo cual es innecesario, te propongo esta pequeña modificacion:

void setup()
{
    pinMode(2,OUTPUT);
    pinMode(3,OUTPUT);
}

void loop()
{
    for(byte cont=0; cont<=15; cont++)
    {
  
        if(cont==5)   // o el valor que necesites
        {
            digitalWrite(2,HIGH);
            digitalWrite(3,LOW);
        }
    
        else if(cont==10)   // idem
        {
             digitalWrite(2,LOW);
             digitalWrite(3,HIGH);
         }
    
         else if(cont==15)   // idem
         {
             digitalWrite(2,HIGH);
             digitalWrite(3,HIGH);
         }
         delay(1000);
     }
}

Esto contribuye a obtener un codigo mas eficiente (se pueden hacer mas retoques).
Por otro lado salvo algun caso muy especial, creo que con un solo delay() seria suficiente.

Naturalmente sin perder de vista que es solo un programita de ejemplo.

Alfaville:
Se te va a quedar optimizado a tope.
Y hay mas,... si no quieres pasarte el bucle entero haciendo "digitalWrite()", lo cual es innecesario, te propongo esta pequeña modificacion:
[...]

¿Es posible que te equivocases al poner el código? Porque en ese ejemplo repites la misma cantidad de veces el digitalWrite() que Tygrecor.

Un saludo.

Gracias a todos muchachos la verdad que estamos aquí para aprender y para mejorar. La verdad que algunos están muy optimizados. Ahora estoy intentando añadir un pulsador para que arranque y así impedir que nada más que conectarlo empiece a funcionar.
Tal como está ahora me sirve y está cojonudo gracias por las optimizaciones, pero quiero rizar un poco el rizo. En cuanto lo tenga lo subiré para compartirlo con todos.

Miralo con calma Arduinito,...

Saludos

Julio48, pon tu duda aparte, no en el hilo de Tygrecor, que nada tiene que ver con lo tuyo.
Yo no soy un moderador para ejercer como tal, pero al inicio del foro tienes las normas del mismo. Échale un ojo por encima. No pongas tus dudas en la dudas de otros porque si no formamos un caos.

Alfaville:
Miralo con calma Arduinito,...

Saludos

Lo miro y lo remiro y sólo veo que los if pasan de estar en un rango a ser cuando sean igual a un valor.
Puedo estar espeso que por mi tierra ya vamos empezando con las primeras partes del carnaval y tengo la mente en otro lado...

Bromas aparte, enserio que no veo donde has dejado de usar menos digitalwrite. Aunque no pasa nada, pero ya me traba porque lo reviso y yo sigo contando los mismos :stuck_out_tongue:

Alfaville y Arduinito:
Vuestros respectivos códigos están más que optimizados. De hecho, si compiláis ambos veréis que se dan la mano tanto en tamaño de código como de ram utilizada.
Código de Arduinito:

El sketch usa 1,658 bytes (0.7%) del espacio de almacenamiento. El máximo es 253,952 bytes.
Las variables globales usan 9 bytes (0.1%) de la memoria dinámica, dejando 8,183 bytes para variables locales. EL máximo es 8,192 bytes.

Código de Alfaville:

El sketch usa 1,658 bytes (0.7%) del espacio de almacenamiento. El máximo es 253,952 bytes.
Las variables globales usan 9 bytes (0.1%) de la memoria dinámica, dejando 8,183 bytes para variables locales. EL máximo es 8,192 bytes.

Lo que hace el código de Alfaville a mayores es evitar escribir el puerto si no es para cambiar de estado; aunque tampoco pasa nada por escribir el puerto con el mismo valor que tenía.

Por no hablar de que según Tygrecor la finalidad última del codigo será medir unos tiempos de encendido/apagado, y para ello lo más seguro es que no se haga mediante ese sistema de bucle, sino con delay o millis.

Gracias por la puntualizacion noter.

Al final hablamos de filigranas pero si sirven para aprender o ver nuevos enfoques a los problemas, se da por bien empleado.

Saludos

Alfaville:
Gracias por la puntualizacion noter.

Al final hablamos de filigranas pero si sirven para aprender o ver nuevos enfoques a los problemas, se da por bien empleado.

Saludos

Totalmente de acuerdo, son ejemplos de como hacerlo y hay muchas formas, pero no creo que quitar líneas u optimizar código sean filigranas. Quizás en Arduino no sea tan importante o quizás unos bytes de memoria no cambien nada, pero aparte de mi titulación llevo años programando y estoy cansado de corregir lo que hacen otras empresas cuando llegan clientes con consultas de SQL que tardan 1 minuto, webs lentas, código en PHP con fallos y miles de líneas que se hacen en una sola...
Digamos que en la vida de a pie la "filigrana" hace que tu cajero de banco no tarde 10 minutos en sacar tu dinero...

Es más, en el poco tiempo que llevo con Arduino (semanas) me he tirado de los pelos por como se programa. Conozco C++, C#, PHP, asp, aspx, los vb hasta los .net, javascript, actionscript, java, nodejs, angular, ruby y paso de seguir contando... Y sí, sin duda en Arduino la gente escribe mil líneas porque Arduino lo pasa a binario :slight_smile: y les da igual. O será que es más divertido hacer esto:

  • repetir...
  • lo vuelvo a repetir...
  • y lo repito de nuevo

ZzzZzz.

De todas formas aquí estaríamos entrando en un Offtopic que nada tiene que ver con la duda del hilo, pero he visto un mal hábito en la manera de programar del foro en español en comparación al inglés. ¿De media en los tutoriales en castellano cuantas variables globales se usan pudiendo quitarlas o ser locales dentro de un void? Es raro ver además un "volatile"

Si hasta he visto declarar un contador de un for como global y declaralo como entero cuando va de 0 a 5 :(:(:frowning:
Lo típico... mientras funcione da igual... Luego resulta que un cúmulo de variables (memoria) y mil líneas a procesar en proyectos grandes pasan de milisegundos a segundos...y ya eso no mola en la vida real :slight_smile:

Arduinito:
Totalmente de acuerdo, son ejemplos de como hacerlo y hay muchas formas, pero no creo que quitar líneas u optimizar código sean filigranas.

Por supuesto que no. Pero como dije, ambas optimizaciones daban el mismo resultado de tamaño de código de programa y de ocupación de RAM. La única "mejora" que introducía Alfaville era para evitar reescribir el HIGH o LOW en el puerto cuando ya se encuentra en dicho estado; lo que dicho sea de paso, tampoco afecta en nada al funcionamiento del programa. Desde ese punto de vista, sí podría considerarse un poco como "filigranas" el considerar mejor el código de Arduinito o el de Alfaville, pues ninguno de los dos supone una mejora sustancial ni en tamaño de código compilado, ni en rendimiento.

Arduinito:
Quizás en Arduino no sea tan importante o quizás unos bytes de memoria no cambien nada...

En un programa tan sencillo no cobra demasiada importancia; pero en programas más complejos... Estamos hablando de un sistema de 8 bits con una memoria minúsculos. Tú me dirás si no es importante :s.

Arduinito:
De todas formas aquí estaríamos entrando en un Offtopic que nada tiene que ver con la duda del hilo, pero he visto un mal hábito en la manera de programar del foro en español en comparación al inglés. ¿De media en los tutoriales en castellano cuantas variables globales se usan pudiendo quitarlas o ser locales dentro de un void? Es raro ver además un "volatile"

Ten en cuenta que la mayor parte de post que verás aparecer en este foro son de noobs que proponen códigos sencillos y a menudo totalmente lineales. Bastante tienen en muchas ocasiones con comprender modificaciones básicas sobre su código como para tirárselo entero por tierra e intentar explicarle el nuevo.
Lo habitual es que los que ya somos un poco más avanzados no nos prodiguemos en iniciar hilos porque normalmente tenemos cierta destreza y sobre todo la capacidad de "autoayuda". Eso me llevó a pensar que el usuario intermedio está un poco abandonado a su suerte, y por ello inicié un hilo en la sección de documentación, donde ir tratando (y discutiendo) precisamente eso: dirigir un poco hacia los buenos hábitos en programación (u otras áreas). De momento está aún "en pañales", pero está abierto precisamente a discutir (de buen rollo) e incluir consejos sobre cuestiones como ésta, así que si queréis departir sobre éste u otros temas similares, seréis bienvenidos.

Arduinito:
Julio48, pon tu duda aparte, no en el hilo de Tygrecor, que nada tiene que ver con lo tuyo.
Yo no soy un moderador para ejercer como tal, pero al inicio del foro tienes las normas del mismo. Échale un ojo por encima. No pongas tus dudas en la dudas de otros porque si no formamos un caos.

Perdon

Ya lo he conseguido completar, he añadido un pulsador para que inicie la secuencia y voilà. Me funciona perfecto así como bien dije comparto por aquí el código final para el que quiera lo pueda usar.

int cont;

void setup() {
  pinMode(2,OUTPUT);
  pinMode(3,OUTPUT);
  pinMode(4,INPUT);
}

void loop() {
  while(digitalRead(4) == LOW) {
    cont=0;
  }
  for(cont; cont<=15; cont++) {

    if(cont>=0 && cont<=5) {
      digitalWrite(2,HIGH);
      digitalWrite(3,LOW);
    }
      
    if(cont>5 && cont<=10) {
      digitalWrite(2,LOW);
      digitalWrite(3,HIGH);
    }
      
    if(cont>10 && cont<=15) {
      digitalWrite(2,HIGH);
      digitalWrite(3,HIGH);
    }
    delay(1000);
    if(cont==15) {
      cont=0;
    }
  }
}

Seguro que @Arduinito y @Alfaville saben optimizarlo para que se quede lo mejor posible, pero yo lo he hecho lo mejor que puedo con lo que se de programación.

Saludos y… Aprender juntos es mejor que solo :).