Interrupción y conflicto con la función millis() para ATtiny85

Hola, me he encontrado con la problemática acerca de como no se puede utilizar la función de millis() en una interrupción, me gustaría pedir su ayuda para encontrar una solución o alternativa a este conflicto. El código funciona correctamente sin utilizar la función sleep() pero necesito poner a dormir el ATtiny85 para ahorrar energía.
El programa debe de esperar pulsaciones de 2 segundos para activar el Led por 1 segundo en ambos botones BTN1 y BTN2 pero en el botón 2 (BTN2) debe reconocer una pulsación corta y accionar por menos tiempo el mismo Led.
Espero me puedan apoyar con algún consejo o sugerencia, gracias.

#include <avr/sleep.h>
#include <avr/interrupt.h>

int BTN2 =2;
int BTN1 =1;
int Led = 0;


//Variables de estado de los botones
  int EST1=0;     
  int EST2=0; 

  boolean PLS1_LRG = 0;
  boolean PLS2_LRG = 0;

  //Cambio de estado del botón 2
  boolean EstadoPin = false;
  boolean AnteriorEstadoPin = false;
  
  //Vatiables de estado para el tiempo de la pulsación
  unsigned long T_Control=0;
  unsigned long T_Apagado = 500;
  unsigned long T_PLS1=0;
  unsigned long T_PLS2=0;

  
void setup() {

   pinMode(BTN2, INPUT);
   pinMode(BTN1, INPUT); 
   pinMode(Led, OUTPUT);
}

void lecturaBTN1(){
if(EST1 == HIGH && T_PLS1 == 0){
    T_PLS1 = millis();
  }
    if(T_PLS1 != 0){
    if(millis() - T_PLS1 > 2000){
      PLS1_LRG = 1;
        if(PLS1_LRG == 1){
          activaBTN1();
          PLS1_LRG = 0;
          T_PLS1 = 0;
        }
    }  
    if(millis() - T_PLS1 >= 500 && EST1 == LOW){
    T_PLS1 = 0;
    }
  }
}

void lecturaBTN2(){
if(EST2 == HIGH && T_PLS2 == 0){
    T_PLS2 = millis();
  }
    if(T_PLS2 != 0){
    if(millis() - T_PLS2 > 2000){
      PLS2_LRG = 1;
        if(PLS2_LRG == 1){
          activaBTN2();
          PLS2_LRG = 0;
          T_PLS2 = 0;
        }
    }  
    if(millis() - T_PLS2 >= 500 && EST2 == LOW){
    T_PLS2 = 0;
    }
  }
}

void activaBTN1(){
  digitalWrite(Led, HIGH);
  PLS1_LRG  = 0;
  delay(3000);
  digitalWrite(Led, LOW);
}

void activaBTN2(){
  digitalWrite(Led, HIGH);
  PLS2_LRG  = 0;
  delay(3000);
  digitalWrite(Led, LOW);
}


void sleep() {
    GIMSK |= _BV(PCIE);
    PCMSK |= _BV(PCINT1);
    PCMSK |= _BV(PCINT2);
    ADCSRA &= ~_BV(ADEN);                   // ADC desactivado
    set_sleep_mode(SLEEP_MODE_PWR_DOWN);    // Reemplaza la declaración anterior
    sleep_enable();                         // Establece el bit de habilitación de suspención en el registro MCUCR (SE BIT)
    sei();                                  // Habilita las interrupciones
    sleep_cpu();                            // Dormir
    cli();                                  // Desabilitar las interrupciones
    PCMSK &= ~_BV(PCINT1);                  // Apaga PB2 como pin de interrupción
    PCMSK &= ~_BV(PCINT2);                  // Apaga PB4 como pin de interrupción
    sleep_disable();                        // Borrar SE bit
    ADCSRA |= _BV(ADEN);                    // ADC activado
    sei();                                  // Habilita interrupciones
    } // sleep
    
 ISR(PCINT0_vect) {
  
}
        
void loop(){

  sleep(); // Si se comenta esta función el código se ejecuta correctamente
  
  EST1 = digitalRead(BTN1);
  EST2 = digitalRead(BTN2);
  
  if(AnteriorEstadoPin != EST2){
    T_Control = millis() + T_Apagado;
    digitalWrite(Led, HIGH);
  }
 AnteriorEstadoPin = EST2;
  if(millis() > T_Control){
    digitalWrite(Led, LOW);
    T_Control = 0;  
  }
  lecturaBTN1();
  lecturaBTN2();
}

Y tu problema es que cuando se pone a dormir no mantiene el tiempo millis() te cuento que si es el caso, la unica solución es que no apagas el timer asociado con millsi() en tu ATtiny85.
De lo contrario millis() se detiene.

SLEEP_MODE_PWR_DOWN detiene todo, incluido los timers, por eso deja de funcionar millis() que depende del timer0

Tienes que usar SLEEP_MODE_IDLE para que el timer0 siga funcionando.

Saludos

surbyte:
Y tu problema es que cuando se pone a dormir no mantiene el tiempo millis() te cuento que si es el caso, la unica solución es que no apagas el timer asociado con millsi() en tu ATtiny85.
De lo contrario millis() se detiene.

Muchas gracias por el consejo, intentaré utilizar SLEEP_MODE_IDLE para evitar que el timer no se apague.

gatul:
SLEEP_MODE_PWR_DOWN detiene todo, incluido los timers, por eso deja de funcionar millis() que depende del timer0

Tienes que usar SLEEP_MODE_IDLE para que el timer0 siga funcionando.

Saludos

Saludos, espero poder poner en práctica tu consejo, me parece lo mejor muchas gracias.
Cualquier cosa estaré comentando aquí mismo, ojalá me ayuden más adelante.

Moderador
Cuando respondas o citas un párrafo o solo menciona el nick pero no reproduzcas todo el post porque eso solo llena el post de exceso de información que ya se ha leído.
Entiendo que en otros foros se hace, pero acá pretendemos tener una lectura como si fuera de un libro, limpia.
Tienes dos post para editar.

This topic was automatically closed 120 days after the last reply. New replies are no longer allowed.