Activar relé a intervalos - Operador ternario RESULETO

Buenas, y ante todo muchas gracias por los buenos ratos que me estais haciendo pasar aprendiendo...

Mi proyecto de arduino es hacer sonar unas campanas de un campanario, durante un tiempo determinado (por ejemplo 3 minutos) a en un intervalo concreto (por ejemplo 3 segundos).

Leyendo en el foro encontré varios ejemplos del tema campanas y campanarios: Campanas para mi Iglesia

Pero en estos se utiliza delay y mi intención és no hacer uso de ese recuso, como bien aconsejan los expertos.

Buscando en el foro general he encontrado este otro post:
Blink without delay for 2 different time intervals

En el hay el seguiente código:

#define LED_PIN 13
#define LED_ON 800       //milliseconds
#define LED_OFF 200

unsigned long ms;        //time from millis()
unsigned long msLast;    //last time the LED changed state
boolean ledState;        //current LED state

void setup(void)
{
    pinMode(LED_PIN, OUTPUT);
}

void loop(void)
{
    ms = millis();
    blinkLED();
}

void blinkLED(void)
{
    if (ms - msLast > (ledState ? LED_ON : LED_OFF)) {
        digitalWrite(LED_PIN, ledState = !ledState);
        msLast = ms;
    }
}

Que me sirve para lo que quiero. El problema es que no lo entiendo, y eso me vuelve loco...

Ahí va mi pregunta: que hace esta sentencia (ledState ? LED_ON : LED_OFF) y que relación guarda con la siguiente?

PD: si en lugar de darme la respuesta directamente me podéis indicar donde puedo descubrirlo por mi mismo os lo agradeceré, por aquello de enseñar a pescar en lugar de dar un pez. Gracias.

Edito ...

Tambien encontré este ejemplo, que hace lo mismo y funciona perfectamente, pero me parece mas elegante el codigo anterior, aunque no lo entienda...

/* Parpadeo sin delay()
Enciende y apaga un LED conectado a un pin digital sin utilizar la función delay(). Esto significa que otro código se puede ejecutar al mismo tiempo sin ser interrumpido por el código que controla el parpadeo del LED
Circuito: Un LED conectado entre el pin 13 y el pin GND.
Nota: en muchos Arduinos hay un LED en la placa conectado al pin 13, por lo que no sería necesario un LED externo para este ejemplo.
Creado en 2005 por David A. Mellis, modificado el 8/2/2010 por Paul Stoffregen.
Este ejemplo es de dominio público*/

// las constantes no cambian. Las usamos aquí para establecer los números de los pines.
int ledPin = 13;   // el número del pin conectado al LED

//  variables que cambiarán de valor.
int ledState = LOW;   // ledState se usará para establecer el estado del LED

long previousMillis = 0;   // almacenará la última vez que el estado del LED
//se actualizó

// la siguiente variable es del tipo long por que el tiempo medido en
// milisegundos supera rápidamente al número que puede ser almacenado en una
// variable del tipo int
long interval = 30000;   // intervalo del parpadeo (en milisegundos) 30 segundos

void setup()
{
// establece el pin digital como salida:
pinMode(ledPin, OUTPUT);
}

void loop()
{
// Aquí es donde pondríamos el código que debe ejecutarse durante todo el
// tiempo.

// Se comprobará si es el momento de parpadear el LED, esto es, si la
// diferencia entre el tiempo transcurrido y el tiempo en que parpadeó
// por última vez el LED es mayor que el intervalo que establecimos en
// la declaración de variables.

unsigned long currentMillis = millis();    // Se toma el tiempo actual

// se comprueba si el tiempo actual menos el tiempo en que el LED cambió
// de estado por última vez es mayor que el intervalo.
if (currentMillis - previousMillis > interval){

// Si se cumple la condición se guarda el nuevo tiempo
// en el que el LED cambia de estado
previousMillis = currentMillis;

// Y ahora cambiamos de estado el LED, si está encendido a
// apagado o viceversa.
if (ledState == LOW)
ledState = HIGH;
else
ledState = LOW;

// Hacemos que el contenido de la variable llegue al LED
digitalWrite(ledPin, ledState);

if(interval==30000)
{
 interval=3600000; //Paso el intervalo a una hora 60 minutos * 60 segundos * 1000 milisegundos
}
else
{
 interval=30000; // Paso el intervalo a 30 segundos30 segundos * 1000 milisegundos
}
}

}

Pues ve a Documentacion y tienes en Indice de temas tutoriales muchas referencias para entender milllis()

Gracias a los manuales que amablemente publicáis en documentación, entendí como funciona millis. Lo que no consigo encontrar, y de ahí mi pregunta es lo de "ledState ? LED_ON : LED_OFF". En los ejemplos de milis ahí iría el valor en milisegundos que establecemos para que se cumpla la sentencia IF, no llego a entender como se establece el valor en este caso.

Gracias por estar siempre ahí y contestar. Seguiré investigando y lo encontraré.

La instrucción ledState ? LED_ON : LED_OFF es el operador ternario de C, C++
A ? B : C
Consta de tres partes: una condición lógica (A) y dos valores (B y C).
Si la condición lógica (A) se evalua a TRUE devuelve el primer valor (B), si se evalua a FALSE el segundo (C).

Así que en función de lo que valga ledState devolverá dos valores diferentes, el tiempo que debe permanecer el led encendido o el tiempo que debe permanecer el led apagado.

Lo que pasa es que han metido todo el código a saco en una única línea, como si fuera un concurso de C ofuscado.

El IF está diciendo "calcula la diferencia entre el tiempo actual y el último tiempo guardado y compárala con el tiempo que debe estar encendido o apagado el led en función de la variable ledState" y si es mayor ejecuta lo de dentro de las llaves que es:

  • Invierte el valor de ledState (si es TRUE pasa a FALSE y si es FALSE pasa a TRUE)
  • Enciende o apaga el led, en función de lo que valga ledState
  • Actualiza la variable de "último tiempo gastado"

Gracias xblasco,

poniendo operador ternario en google me sale muchissima informacion que aclara el asunto. Acaba hacindo lo mismo que en el otro ojemplo pero con mucho menos código.

Aún que seas un newbie como yo, sabes mucho mas :wink: