Temporizador de encendido de leds

ArduMyth:

void luz( int  *arr ) {

bool val = digitalRead(arr[0]);
  if(arr[2] != val && millis() >= arr[5] + 150) { //debounce
      arr[2] = val; //valor como pulsador
      if(! arr[2] ) {
        arr[3]  = ! arr[3] ; //valor como interruptor
        if( arr[3] ) {
            arr[4] = millis() ;
        }else{
            Serial. println("El led del pin "+String(arr[1]) +" ha estado encendido " + String(millis() - arr[4]) +" milisegundos");
        }
      }
      arr[5] = millis() ; //reiniciar tiempo debounce
  }
  digitalWrite(arr[1], arr[3]) ; //apagar encender led
}

Muchas gracias pero una pregunta el arr es un array, pero para que el asterisco de aqui

void luz( int *arr )

y otra cosa,

DDRD =B11110010;

, esto es un pinMode, pero podrias explicarmelo, me quiero enterar de esto.

Lo que tu buscas esta en un ejemplo: dentro de la IDE de Arduino, BlinkWithoutDelay.

Ahi mero esta o te recomiendo que le des una buscada en google con;

Nick, Gammon, Millis, blink, without, delay

Saludos.

-Alex.

AlexLPD:
Lo que tu buscas esta en un ejemplo: dentro de la IDE de Arduino, BlinkWithoutDelay.

Eso lo se pero no consigo implementarlo pero consegui que se apague cuando conteo llega a 6000, pero no consigo que se repita de nuevo cuando pulso, solo puedo cuando lo reinicio.
Yo hago que cuando llega a mas de 6000 apague el led y resetee la variable conteo, lo hace porque lo comprobe pero no vuelve a contar al darle al boton. No se si es por las variables de estado o salida, el codigo lo dejo para que lo veais:

#define boton 2
int led = 6;
int leds = 3;

int estado = 0;
int estadoAN = 0;
int salida = 0;
int salidaAN;

unsigned long conteo;
unsigned long tempOn = 6000;


void setup() {
  // put your setup code here, to run once:
  pinMode(boton, INPUT_PULLUP);
  pinMode(led, OUTPUT);
  pinMode(leds, OUTPUT);
  Serial.begin(9600);
}

void loop() {
  // put your main code here, to run repeatedly:
  estado = digitalRead(boton);

  if((estado == 1)&&(estadoAN == 0)){
    salida = 1 - salida;
  }

  estadoAN = estado;

  if(salida == 0){
    digitalWrite(led, HIGH);
    digitalWrite(leds, HIGH);
    conteo = millis();
    if ((conteo >= tempOn)){
      digitalWrite(led, LOW);
      digitalWrite(leds, LOW);
      conteo = 0;
      salida = 1 - salida;
    }else{
      digitalWrite(led, HIGH);
      digitalWrite(leds, HIGH);
    }
  }
  else{
    digitalWrite(led, LOW);
    digitalWrite(leds, LOW);
  }
  
}

ArduMyth:

unsigned int

btnA[6] ={2,6,0,0,0,0},
btnB[6] ={3,7,0,0,0,0} ;

void setup() {
  Serial.begin(9600);
  DDRD =B11110010; //Pin 2 y 3 como INPUT
}

void loop() {
  luz(btnA) ; //usando punteros
  luz(btnB) ;
}

void luz( int  *arr ) {
  bool val = digitalRead(arr[0]);
  if(arr[2] != val && millis() >= arr[5] + 150) { //debounce
      arr[2] = val; //valor como pulsador
      if(! arr[2] ) {
        arr[3]  = ! arr[3] ; //valor como interruptor
        if( arr[3] ) {
            arr[4] = millis() ;
        }else{
            Serial. println("El led del pin "+String(arr[1]) +" ha estado encendido " + String(millis() - arr[4]) +" milisegundos");
        }
      }
      arr[5] = millis() ; //reiniciar tiempo debounce
  }
  digitalWrite(arr[1], arr[3]) ; //apagar encender led
}

Ya intente estudiar tu codigo, pero me cuesta entenderlo incluso con comentarios, yo deje una respuesta con mi codigo, ya consegui que se apague a llegar a 6000, pero no consigo que vuelva ha hacerlo.

Shadoaru, no tengo nada claro qué pretendes hacer y cómo. ¿Para qué un botón y dos LED? ¿Cual es tu propósito final? ¿Cómo quieres que actúe el sistema ante los posibles rebotes del pulsador? ¿Qué ha de pasar si "se juega" con el pulsador? ¿Y si siempre está pulsado? Si no tengo bien claro qué es lo que quieres hacer, tal vez no te pueda ayudar tanto como quisiera. Para encontrar una solución a un problema, primero se ha de saber en qué consiste el problema.

Como ejemplo, para ver si te da alguna idea de cómo hacer lo que quieres, te pongo el código que enciende durante 6 segundos un LED desde el momento en que se pone a nivel bajo el pin del botón (se supone que cuando se presiona se pone a nivel bajo la entrada). No se tiene en cuenta para nada el posible "efecto rebote" del pulsador ya que sólo se enciende el LED y se empieza a contar los seis segundos si este previamente estaba apagado. Si el LED ya estaba encendido no tiene en cuenta el estado del pulsador. No importa si el pulsador se suelta y vuelve a apretar durante los seis segundos, no afectará al tiempo en que esté encendido el LED. Sólo si en el instante en que se completan los seis segundos el botón se encuentra pulsado, el LED se apagará durante un instante inapreciable para nosotros y volverá a encenderse durante otros seis segundos.

const byte PIN_BOTON = 2; // Pin al que está conectado el botón. El otro lado del botón ha de estar a GND
const byte PIN_LED = 6;   // Pin al que se conecta el LED

const unsigned long TIEMPO_ENCENDIDO = 6000;  // Tiempo en milisegundos que permanecerá encendido el LED

bool encendido = false;           // Variable que nos indicará si el LED está encendido
unsigned long instanteEncendido;  // Variable que guardará el valor de millis() cuando se encendió el LED por última vez


void setup() {
  pinMode(PIN_BOTON, INPUT_PULLUP);
  pinMode(PIN_LED, OUTPUT);
}

void loop() {
  // Verificamos si está pulsado el botón y el LED no está encendido
  if ((digitalRead(PIN_BOTON) == LOW) && (encendido == false)) {
    instanteEncendido = millis(); // Guardamos el instante en que encendemos el LED
    digitalWrite(PIN_LED, HIGH);  // Encendemos el led
    encendido = true;             // Indicamos que el LED está encendido
  }

  // Verificamos si el LED está encendido y ha transcurrido el tiempo que ha de estar encendido
  if ((encendido == true) && ((millis() - instanteEncendido) >= TIEMPO_ENCENDIDO)) {
    digitalWrite(PIN_LED, LOW);  // Apagamos el LED
    encendido = false;           // Indicamos que el LED no está encendido
  }
}

Fíjate que con la variable encendido controlamos si hacemos algo con respecto al estado del botón o con el tiempo transcurrido. Y para saber cuanto tiempo lleva encendido lo que hacemos es guardar en instanteEncendido el valor de millis() cuando lo hemos encendido y luego restamos ese valor a millis() para calcular cuanto lleva encendido y saber si ya ha transcurrido el tiempo que deseamos.

IgnoranteAbsoluto, ese codigo lo repetí muchas veces en c#, claramente cambiando cosas, no se como no se me ocurrio, sera del tiempo que ya no programo, pero lo que me dijiste, veras, yo quiero que un boton controle 2 leds, que cuente indenpendiente al otro cuente ese tiempo tambien, por ejemplo, le doy al boton y me enciende el led 6 segundos, pero al darle otra vez empieze a contar el tiempo del otro led independientemente al otro, pero como dije, con un unico boton

No aclaras cosas como qué pasa si ya todos los LEDs están encendidos y continuamos dándole al botón. Ni tampoco qué ha de hacer si le damos una vez, se enciende el primero, esperamos a que se apague y le volvemos a dar al botón. ¿Se ha encender el segundo, que es el que "le tocaba", o ha de volver a empezar por el primero? Así que como no aclaras cómo ha de funcionar, y aprovechando que han de estar encendidos siempre el mismo tiempo cada uno por separado, he asumido que se han de encender uno detrás de otro y si ya están todos encendidos ha de esperar a que se apague "el que le toca" para que haga caso del botón.

Yo habría usado clases, pero no quiero "liarlo" más con conceptos que no controla mucha gente (ver cómo se haría en el enlace que puse en mi primer comentario de este post). Así que me he limitado a usar una estructura para contener los datos de cada LED y crear un array de dicha estructura para "trabajar" con todos ellos. En el ejemplo he puesto sólo dos LEDs, pero si se desea se pueden añadir fácilmente más LEDs a controlar, con sólo añadir más elementos al array leds[] en su definición.

Tampoco he usado funciones miembro de la estructura (ya para eso habría hecho una clase y punto) sino que uso dos funciones para "tratar" los LEDs. Una es loopLed() que se encarga de controlar el tiempo que lleva encendido cada LED para apagarlo cuando deba. La otra es encenderLed() que controla si el LED está apagado o encendido para no "encenderlo" si ya lo está, a la vez que retorna 1 o 0 para que incremente o no el índice que controla cual va a ser el siguiente LED del array que se tiene que encender (cuando esté apagado).

En el loop() principal controlo el pulsador y sus posibles rebotes. Para ello digamos que uso una pequeña máquina de estados que controla si está "apagado", "encendido" o en "transición" para apagarse. Si está "apagado" en cuanto lo detecte pulsado pasa a "encendido" y trata de encender el LED pertinente. Si en ese momento hay rebotes, no importa, ya que pasa a "transición" y antes de llegar a "apagado" volverá a el estado "encendido" si finalmente se deja pulsado. Si el tiempo que está en "transición" es el suficiente (está sin pulsar el tiempo estipulado por TIEMPO_ANTI_REBOTE) pasará finalmente a "apagado". Sólo cuando pasa de "apagado" a "encendido" es cuando "manda la orden" de encender el LED, mientras que el paso de "transición" a "encendido" no hace nada (así es como nos libramos de un posible "efecto rebote").

La variable que controla cual es el siguiente LED a encender, indiceLedActual, se incrementa si el LED que se ha de encender estaba apagado. Y, para "volver" a cero cuando sobrepasa el último elemento del array, se le asigna el resto de la división entre el número de elementos del array leds[]. Si, por ejemplo, fueran 3 elementos el valor debería de estar entre 0 y 2. El resto de dividir 0 entre 3 es 0, el de 1 entre 3 es 1, el de 2 entre 3 es 2, el resto de dividir 3 entre 3 es 0 (con lo que "volvemos al principio"). El operador del resto de la división es %

Como puedes observar, no hay ningún delay(), sólo algún que otro millis(). Y el programa no se queda "bloqueado" en ningún bucle de gran duración o infinito.

Espero que esto te oriente y te de ideas de cómo hacer lo que deseas.

Aquí tienes el código:

const byte PIN_BOTON = 2; // Pin al que está conectado el botón. El otro lado del botón ha de estar a GND
const byte PIN_LED_1 = 3;   // Pin al que se conecta el LED
const byte PIN_LED_2 = 6;   // Pin al que se conecta el LED

const unsigned long TIEMPO_ANTI_REBOTE = 150; // Tiempo en milisegundos que ha de permanecer el pulsador inactivo para que filtre los posibles rebotes
const unsigned long TIEMPO_ENCENDIDO = 6000;  // Tiempo en milisegundos que permanecerá encendido el LED

struct led_t {
    byte pin;
    bool encendido;                   // Controla si el LED está encendido
    unsigned long instanteEncendido;  // Guarda el valor de millis() cuando se encendió el LED por última vez
};

led_t leds[] = {                // Definimos un array con tantos LEDs como se quiera controlar
    {PIN_LED_1, false, 0},      // Siempre ha de inicializar con false
    {PIN_LED_2, false, 0}
};

const byte CANTIDAD_LEDS = sizeof(leds) / sizeof(leds[0]);  // Esto calcula la constante con el número de elementos del array

enum estadoPulsador_t {     // Estados para controlar los posibles rebotes del pulsador
    ESTADO_REPOSO,          // Cuando no está pulsado
    ESTADO_PULSADO,         // Cuando está pulsado
    ESTADO_TRANSICION       // Cuando no está pulsado pero aún no ha pasado el tiempo para evitar el posible efecto rebote
};

estadoPulsador_t estadoPulsador = ESTADO_REPOSO;    // Variable que controla los estados del botón
unsigned long instanteInicioTransicion;             // Variable para controlar el tiempo de del rebote del botón
byte indiceLedActual = 0;                           // Índice que controla cual será el próximo LED a encender

// Esta función se ha de llamar frecuentemente para que controle el tiempo que están los LEDs encendidos (sin bloquear)
void loopLed(led_t &led) {
    // Verificamos si el LED está encendido y ha transcurrido el tiempo que ha de estar encendido
    if ((led.encendido == true) && ((millis() - led.instanteEncendido) >= TIEMPO_ENCENDIDO)) {
        digitalWrite(led.pin, LOW);  // Apagamos el LED
        led.encendido = false;       // Indicamos que el LED no está encendido
    }
}

// Para encender el LED se llama a esta función.
// Si el LED ya estaba encendido no hace nada y retorna 0 para que no incremente el índice.
// Si enciende el LED retorna 1 para que incremente el índice que controla el próximo LED a encender
byte encenderLed(led_t &led) {
    if (led.encendido) {
        // Si el LED ya está encendido, habrá que esperar a que se apague
        return 0;
    }
    led.instanteEncendido = millis(); // Guardamos el instante en que encendemos el LED
    digitalWrite(led.pin, HIGH);      // Encendemos el led
    led.encendido = true;             // Indicamos que el LED está encendido
    return 1;                         // Pasa al siguiente LED
}

void setup() {
    pinMode(PIN_BOTON, INPUT_PULLUP);
    for (byte i = 0; i < CANTIDAD_LEDS; i++) { // Con este bucle configuramos como salida el pin de todos los LEDs
        pinMode(leds[i].pin, OUTPUT);
    }
}

void loop() {
    // Controlamos el botón
    if (digitalRead(PIN_BOTON) == LOW) {
        // En este instante el botón está pulsado
        if (estadoPulsador == ESTADO_REPOSO) {
            // Hasta ahora no estaba pulsado
            estadoPulsador = ESTADO_PULSADO;    // Ahora está pulsado

            // Se llama a la funcíón para encender el LED "actual".
            // Si ya estaba encendido retornará 0 y no incrementa indiceLedActual.
            // Si estaba apagado enciende el LED, retorna 1 e incrementa indiceLedActual.
            // Para que "vuelva" a 0 cuando se "apunta" más allá del último LED,
            // se le asigna el resto de la división de (indiceLedActual + encenderLed()) entre CANTIDAD_LEDS
            indiceLedActual = (indiceLedActual + encenderLed(leds[indiceLedActual])) % CANTIDAD_LEDS;
        }
        else if (estadoPulsador == ESTADO_TRANSICION) {
            // Se encontraba en medio de la transición (un posible rebote) así que lo "mantiene" pulsado y no hace nada con los LEDs
            estadoPulsador = ESTADO_PULSADO;
        }
    }
    else {
        // En este instante el botón no está pulsado
        if (estadoPulsador == ESTADO_PULSADO) {
            // Hasta ahora el botón estaba pulsado, con lo que a partir de este instante comienza "la transición"
            estadoPulsador = ESTADO_TRANSICION;
            instanteInicioTransicion = millis();    // Guardamos el instante en que comienza la transición para controlar el tiempo
        }
        else if (estadoPulsador == ESTADO_TRANSICION) {
            // Hasta ahora el botón ha estado sin pulsar durante la trancisión
            // Verifiamos si ha transcurrido el tiempo "sin rebotes"
            if ((millis() - instanteInicioTransicion) >= TIEMPO_ANTI_REBOTE) {
                // Como ha transcurrido el tiempo de transición sin rebotes, pasamos al estado de "reposo"
                estadoPulsador = ESTADO_REPOSO;
            }
        }
    }

    // Con este bulce controlamos el tiempo que ha de estar encendido todos los LEDs
    for (byte i = 0; i < CANTIDAD_LEDS; i++) {
        loopLed(leds[i]);
    }
}

Te respondo el ultimo mensaje IgnoranteAbsoluto, aun me queda por aprender, muchas gracias, me tengo que enterarde esto, pero lo que me preguntaste fueron varias preguntas, como por ejemplo que pasa si le doy al boton cuando todos los leds estan encendidos, pus no pasa nada. Pero tambien de cual led se enciende eso es aleatorio