AtTiny84 : Réactiver le MCU après un deep sleep

Bonjour,

J’essaie de réveiller un AtTiny par une interruption externe, mais cela fait des heures que je cherche…

L’interruption externe se fait par un Ds3231 (mais il pourrait se faire avec un bouton).

J’ai branché le SQLW du Ds3231 sur le pin physique 5 du AtTiny84 (qui devrait être le INT0 si je ne m’abuse).

Dans mon setup, j’ai les lignes :

pinMode(interruptPin, INPUT_PULLUP);
attachInterrupt(0, wake, FALLING);

Dans mon esprit, la valeur de interruptPin doit être 8.

Mais cela ne fonctionne pas…

Je pense qu’il me manque une “liaison” entre le pin 8 et INT0…

// https://www.youtube.com/watch?v=urLSDi7SD8M

#include <TinyWireM.h>
#include <ds3231.h>

#define Wire TinyWireM

volatile boolean interruptActive = false;

int pinLed1 = 7;
int pinLed2 = 0;
int interruptPin = 8;

struct ts t;

uint8_t wake_HOUR;
uint8_t wake_MINUTE;
uint8_t wake_SECOND;

void gotoSleep(void);

 void flash(int pinLed) {
  digitalWrite(pinLed, HIGH);   // turn the LED on (HIGH is the voltage level)
  delay(200);                       // wait for a second
  digitalWrite(pinLed, LOW);    // turn the LED off by making the voltage LOW
  delay(200);   
 }
 
void setup() {
//  Serial.begin(9600);
  pinMode(pinLed1, OUTPUT);
  pinMode(pinLed2, OUTPUT);
  pinMode(interruptPin, INPUT_PULLUP);
  
  Wire.begin();
  DS3231_init(DS3231_INTCN);
  flash(pinLed1);
  flash(pinLed2);

//   attachInterrupt(0, wake, FALLING);
   attachInterrupt(8, wake, FALLING);
  //Disable ADC - don't forget to flip back after waking up if using ADC in your application ADCSRA |= (1 << 7);
  ADCSRA &= ~(1 << 7);
  
  MCUCR |= (1<<4);
  MCUCR |= (1<<5);

}
 
void loop() {
  // put your main code here, to run repeatedly:
  DS3231_get(&t);

 if (interruptActive) {
  digitalWrite(pinLed1, HIGH);   // turn the LED on (HIGH is the voltage level)
  for (int i = 0;i < 10;i++) {
     flash(pinLed2);
  }
   digitalWrite(pinLed1, LOW);   // turn the LED on (HIGH is the voltage level)

  delay(1000);
 }
 interruptActive = false;
  gotoSleep();
}

void set_waketime(int minutes)
{
  DS3231_get(&t);

  wake_SECOND = t.sec + minutes; 
  wake_MINUTE = t.min;
  wake_HOUR   = t.hour;

  while (wake_SECOND > 60) {
     wake_MINUTE++;
     wake_SECOND-=60;
  }
  while (wake_MINUTE > 60) {
     wake_HOUR++;
     wake_MINUTE-=60;
  }
  if (wake_HOUR > 24) {
     wake_HOUR -= 24;
  }
}

void set_alarm1(void)
{
    // flags define what calendar component to be checked against the current time in order
    // to trigger the alarm - see datasheet
    // A1M1 (seconds) (0 to enable, 1 to disable)
    // A1M2 (minutes) (0 to enable, 1 to disable)
    // A1M3 (hour)    (0 to enable, 1 to disable) 
    // A1M4 (day)     (0 to enable, 1 to disable)
    // DY/DT          (dayofweek == 1/dayofmonth == 0)
    uint8_t flags[5] = { 0, 0, 0, 1, 1 };

    DS3231_clear_a1f();

    // set Alarm1
    DS3231_set_a1(wake_SECOND, wake_MINUTE, wake_HOUR, 0, flags);

    // activate Alarm1
    DS3231_set_creg(DS3231_INTCN | DS3231_A1IE);
}

void wake()
{
  digitalWrite(pinLed1, HIGH);
//  flash(pinLed2);
//  flash(pinLed2);
  // cancel sleep as a precaution
//  sleep_disable();

//----------ADCSRA |= (1 << 7);

  interruptActive = true;
  
  // precautionary while we do other stuff
//---  detachInterrupt(0);
  

}  // end of wake

void gotoSleep()
{ 
  delay(100);
  set_waketime(5);
  set_alarm1();

  //Disable ADC - don't forget to flip back after waking up if using ADC in your application ADCSRA |= (1 << 7);
  //--------------ADCSRA &= ~(1 << 7);
  
//  set_sleep_mode (SLEEP_MODE_PWR_DOWN);  
//  sleep_enable();

// Do not interrupt before we go to sleep, or the
// ISR will detach interrupts and we won't wake.
//  noInterrupts ();
  
 // will be called when pin D2 goes low  
//  attachInterrupt(0, wake, FALLING);
  // We are guaranteed that the sleep_cpu call will be done
  // as the processor executes the next instruction after
  // interrupts are turned on.
//  interrupts ();  // one cycle
 
   //BOD DISABLE - this must be called right before the __asm__ sleep instruction
   MCUCR = (MCUCR | (1 <<2)) | (1<<7); 
   MCUCR = (MCUCR &  ~(1 << 2)) | (1<<7);
  
__asm__ __volatile__("sleep");

}

Yann9155:
cela fait des heures que je cherche…

Tu n’as pas non plus trouvé la bonne section pour poster ta demande : clique ici pour demander au modérateur de déplacer ton sujet…

Sujet mis à la bonne place…

Dans mon esprit, la valeur de interruptPin doit être 8.

En est-tu sûr ?

Ce que je vois partout c'est plutôt PA0 -> PCINT0

Bonjour,

Merci de la réponse. J'ai essayé la pin A0. Cela ne fonctionne pas.

A0 est PCINT0, alors que je je cherche l'activation de l'interrupt 0, qui est, d'après mes recherches, sur le PB2 (INT0). Qui est la pin physique 5 sur l'AtTiny84.

Pour moi, c'est bien la pin logique 8. J'ai testé de mettre cette pin en OUTPUT, digitalWrite(8, HIGH); allume la Led que j'y est mis dessus.

Avec le code :

int interruptPin = 8;
pinMode(interruptPin, INPUT_PULLUP);



attachInterrupt(0, wake, FALLING);

la procédure wake devrait être appellée au passage de High à Low du pin logique 8. Mais cela ne se fait pas....

Déjà que je n'ai plus bcp de cheveux, mais là, ça empire.... :slight_smile: :slight_smile: :slight_smile: :slight_smile:

Bon dev.

Yann

Je ne connais pas le correspondance entre pins AATINY84 et pins ARDUINO mais la fonction digitalPinToInterrupt() permet normalement de récupérer le N° d'interruption associé à une pin digitale.
Si tu lui passe 8 et qu'elle te retourne 0 tu es dans le vrai, si elle te retourne autre chose, tu as tort.

En effet je crains pour ta chevelure, car les interruptions sur attiny84 ça n'a pas l'air simple. Tu devrais tester ceci

Yann9155:
Bonjour,

Merci de la réponse. J'ai essayé la pin A0. Cela ne fonctionne pas.

A0 est PCINT0, alors que je je cherche l'activation de l'interrupt 0, qui est, d'après mes recherches, sur le PB2 (INT0). Qui est la pin physique 5 sur l'AtTiny84.

Pour moi, c'est bien la pin logique 8. J'ai testé de mettre cette pin en OUTPUT, digitalWrite(8, HIGH); allume la Led que j'y est mis dessus.

Avec le code :

int interruptPin = 8;

pinMode(interruptPin, INPUT_PULLUP);

attachInterrupt(0, wake, FALLING);




la procédure wake devrait être appellée au passage de High à Low du pin logique 8. Mais cela ne se fait pas....

Déjà que je n'ai plus bcp de cheveux, mais là, ça empire.... :) :) :) :) 

Bon dev.

Yann

Bonsoir
tu utilise quoi avec l'IDE pour gerer l'attiny ?
le support attiny de D.A Mellis ?

@Artouste

tu utilise quoi avec l'IDE pour gerer l'attiny ?
le support attiny de D.A Mellis ?

OUI, Version 1.0.2

Yann9155:
@Artouste

tu utilise quoi avec l'IDE pour gerer l'attiny ?
le support attiny de D.A Mellis ?

OUI, Version 1.0.2

Bonjour
je joue assez rarement avec les attiny , mais je me souviens que j'avais eu des problémes d'interrupt avec ce support (Mellis) il n'est pas/plus maintenu.
En ce qui me concerne j'avais réglé mon probléme en passant sur çà
qui est/semble bien maintenu

:slight_smile: :slight_smile: :slight_smile: :slight_smile: :slight_smile:

MERCI A TOUS!!!

J’ai trouvé… Et il me reste qq cheveux.

C’est une bête ligne de code qui manquait…

Je pensais que c’était l’interruption elle-même qui devait “réveiller” le Tiny…

En fait, dans la procédure du sleep, le Tiny va au dodo et va se réveiller à la même instruction.

La dernière instruction avant le sleep doit donc être l’instruction pour le faire sortir du mode de veille.

En gros, ma procédure de mise en veille est (j’ai ajouté l’avant-dernière ligne) :

void gotoSleep()
{ 
  delay(100);
  set_waketime(5);
  set_alarm1();

  noInterrupts ();
  
  // will be called when pin PB2 goes low  
  attachInterrupt(0, wake, FALLING);

  // We are guaranteed that the sleep_cpu call will be done
  // as the processor executes the next instruction after
  // interrupts are turned on.
  
  interrupts ();  // one cycle
 
   //BOD DISABLE - this must be called right before the __asm__ sleep instruction
   MCUCR = (MCUCR | (1 <<2)) | (1<<7); 
   MCUCR = (MCUCR &  ~(1 << 2)) | (1<<7);

   sleep_disable();  
   __asm__ __volatile__("sleep");
}

Merci encore à tous. Perso j’ai bien avancé sur l’AtTiny, le RTC DS3231, la mise en veille et les interruptions. A charge de revanche.

Bon Dev

Yann