Attiny85 problemi sleep mode [Risolto]

Salve a tutti ,
è da poco che ho iniziato a cimentarmi con questi chip, attualmente sto utilizzando un digispark con attiny85 su un'applicazione , sto avendo problemi con la gestione dello sleep mode in quanto il dispositivo è collegato ad una batteria , considerate che per far partire in immediato il programma (eliminazione dei 5-6 secondi allo startup), recuperare spazio sulla memoria ed abbassare l'assorbimento ho eliminando tutte le resistenze / led / zener non necessari e di conseguenza anche il boot , la programmazione è effettuata tramite ISP , in questa configurazione sto avendo problemi, il programma inserito lavora correttamente e si comporta in modo impeccabile, peccato che una volta attivato lo sleep mode al risveglio non lavora correttamente e non gestisce più la programmazione , è da considerare che dopo il tempo programmato torna a gestire correttamente lo sleep disattivandosi se premo il pulsante!!!!
Ho notato che ogni volta che premo il pulsante mi si accende anche il led sulla porta 0, questo comportamento non deve accadere, sembra quasi che la configurazpme dell' Interrupt sulla funzione di sleep abbia effettuato qualche modifica sugli ingressi

ho notato che una volta risvegliato il programma non viene eseguito da dove è stata abilitato lo sleep ma ricomincia d'accapo in basso tralcio del codice, iniialmente con il boot il programma si inizializza correttamente e il tutto funziona correttamente, considerate che anche con il boot il chip dopo lo sleep viene resettato riniziando dall'inizio, mi sono accorto di questo comportamento in quanto accendo / spengo un led allo startup

in basso riporto un pezzo di programma dove c'è il richiamo alla routine, non ho inserito la parte dei menu in quanto il listato è molto lungo , il risveglio è gestito da un pulsante e da come ho capito non gestisce piu' il modo sincrono e nel loop non vengono gestite le condizioni inserite con gli ingressi/uscite

aspetto fiducioso vostro parere

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

int led = 0;
int rele = 1;
int ok = 2;
int c = 0;
int puls = 4;
int set = 3;
int controllo = 0;
int conta = 0;
int contas = 0;
int t_ciclo;
int long t_ciclo_c;
int ok1; // contatore
int menu = 0;
int men = 0;
int c_setup = 0;
int cont; // contatore
int cont1; // contator
int  t_ciclo_com;
long int  t_ciclo_comp;
int puls1; // contatore
int set1;
int x = 1;
int cicli;
int inciclo = 0;
unsigned long int timer;
unsigned long int timer1;

void setup () {
 cicli = EEPROM.read(0); // leggi le variabili nella eeprom , se vuote scrivi i valori in default
 t_ciclo = EEPROM.read (2);
 t_ciclo_com = EEPROM.read (4);
 if (cicli < 1 || cicli > 30) { //cicli 1-30
   EEPROM.write(0, 1);
 }
 if (t_ciclo < 3 || t_ciclo > 50) { //tempo  0.3-5 secondi
   EEPROM.write(2, 3);
 }
 if (t_ciclo_com < 1 || t_ciclo_com > 30 ) { //ritardo ciclo comp 10s- 5 minuti
   EEPROM.write(4, 1) ;
 }
 pinMode (led, OUTPUT);
 pinMode (rele, OUTPUT);
 pinMode (puls, INPUT);
 digitalWrite(puls, HIGH);
 pinMode (set, INPUT);
 pinMode (ok, INPUT);
 digitalWrite (rele, LOW);
 puls1 = digitalRead (puls);
 digitalWrite (led, HIGH);
 delay (300);
 set1 = digitalRead (set);
 digitalWrite (led, LOW);
 delay (500);
 t_ciclo_comp = t_ciclo_com * 10000;
 t_ciclo_c = t_ciclo * 100;
}
void loop() {
 if (set1 == LOW && x == 1) { //vai al menu programmazione se viene premuto il tasto prog allo startup
   digitalWrite (led, HIGH);
   delay (1000);
   digitalWrite (led, LOW);
   delay (500);
   //digitalWrite (rele, HIGH);
   timer1 = millis() ;
   x = 0;
   c_setup = 1;
   menu_s() ;
 }
 if (c_setup == 1) {
   menu_s() ;
 }
 ok1 = digitalRead(ok);
 puls1 = digitalRead (puls);
 if (ok1 == LOW) {
   cont = 1;
 }
 if (ok1 == HIGH && cont == 1 && inciclo == 1) {
   conta++;
   cont = 0;
   inciclo = 0;
   delay (200);
   digitalWrite (led, HIGH);
   digitalWrite (rele, HIGH);
   delay (700);
   digitalWrite (led, LOW);
   digitalWrite (rele, LOW);
 }
 if (conta == cicli) {
   // Riporta la variabile a 0
   digitalWrite (rele, HIGH);
   digitalWrite (led, HIGH);
   delay (t_ciclo_comp);
   digitalWrite (rele, LOW);
   digitalWrite (led, LOW);
   conta = 0;
   cont = 0;
   x = 0;
 }
 if (puls1 == HIGH) {
   timer = millis();
   inciclo = 0;
 }
 if ((millis() - timer) > t_ciclo_c && puls1 == LOW) {
   inciclo = 1;
   timer1 = millis();
 }
 if (millis() - timer1 > 900000) { // power saving 15 minuti
   enterSleep();
   timer1 = millis();
 }
}
void enterSleep() {
 GIMSK |= _BV(PCIE);                     // Enable Pin Change  
 PCMSK |= _BV(PCINT4);                   // Use PB4 as interrupt pin
 ADCSRA &= ~_BV(ADEN);                              // ADC off
 set_sleep_mode(SLEEP_MODE_PWR_DOWN);    // replaces above statement  
 sleep_enable();                         // Sets the Sleep Enable bit in the MCUCR Register (SE BIT)
 sei();                                  // Enable interrupts
 sleep_cpu();                            // sleep
 cli();                                  // Disable interrupts
 GIMSK &= ~(1<<PCIE);                    // Disable Pin Change Interrupts
 PCMSK &= ~_BV(PCINT4);                  // Turn off PB4 as interrupt pin
 sleep_disable(); 
 ADCSRA |= _BV(ADEN);                    // ADC on
 sei();    // Enable interrupt

 
}
ISR(PCINT_vect) {
}

void memoria() {
 EEPROM.write (0, cicli);
 EEPROM.write (2, t_ciclo);
 EEPROM.write (4, t_ciclo_com);
 delay(100);
 men = 1;
 c_setup = 0;
 menu = 0;
 t_ciclo_comp = t_ciclo_com * 10000;
 t_ciclo_c = t_ciclo * 100;
}

void menu_s() {.....}
void menu_1() {.....}
void menu_2() {.....}
void menu_3() {.....}

Buongiorno,

prima di tutto, essendo il tuo primo post, nel rispetto del regolamento (… punto 13, primo capoverso), ti chiedo cortesemente di presentarti IN QUESTO THREAD (spiegando bene quali conoscenze hai di elettronica e di programmazione ... possibilmente evitando di scrivere solo una riga di saluto) e di leggere con MOLTA attenzione il su citato REGOLAMENTO ...

.. dopo di che, in conformità al suddetto regolamento, punto 7, devi editare il tuo post qui sopra (quindi NON scrivendo un nuovo post, ma utilizzando il bottone More -> Modify che si trova in basso a destra del tuo post) e racchiudere il codice all'interno dei tag CODE (... sono quelli che in edit inserisce il bottone con icona fatta così: </>, tutto a sinistra). Grazie.

Guglielmo

Ciao Ragazzi, c'è qualche anima buona che mi può dare qualche dritta in merito?

aspetto fiducioso

Non ho capito esattamente tutta la spiegazione, comunque..

Hai provato una configurazione minima del programma, ossia togliere tutto e lasciare solo lo sleep per assicurarti che riparta effettivamente da capo una volta uscito dallo sleep?

Ho provato ad alleggerire il codice ma il comportamento è sempre lo stesso,

#include <avr/sleep.h>


int led = 0;
int rele = 1;
int ok = 2;
int puls = 4;
int set = 3;
int conta = 0;
int t_ciclo=1;
int long t_ciclo_c;
int ok1; // contatore
int cont; // contatore
int  t_ciclo_com=1;
long int  t_ciclo_comp=1;
int puls1; // contatore
int set1;
int x = 1;
int cicli=3;
int inciclo = 0;
unsigned long int timer;
unsigned long int timer1;

void setup () {
  pinMode (led, OUTPUT);
  pinMode (rele, OUTPUT);
  pinMode (puls, INPUT);
  digitalWrite(puls, HIGH);
  pinMode (set, INPUT);
  pinMode (ok, INPUT);
  digitalWrite (rele, LOW);
  puls1 = digitalRead (puls);
  digitalWrite (led, HIGH);
  delay (300);
  set1 = digitalRead (set);
  digitalWrite (led, LOW);
  delay (500);
  t_ciclo_comp = t_ciclo_com * 10000;
  t_ciclo_c = t_ciclo * 100;
}
void loop() {
  ok1 = digitalRead(ok);
  puls1 = digitalRead (puls);
  if (ok1 == LOW) {
    cont = 1;
  }
  if (ok1 == HIGH && cont == 1 && inciclo == 1) {
    conta++;
    cont = 0;
    inciclo = 0;
    delay (200);
    digitalWrite (led, HIGH);
    digitalWrite (rele, HIGH);
    delay (700);
    digitalWrite (led, LOW);
    digitalWrite (rele, LOW);
  }
  if (conta == cicli) {
    // Riporta la variabile a 0
    digitalWrite (rele, HIGH);
    digitalWrite (led, HIGH);
    delay (t_ciclo_comp);
    digitalWrite (rele, LOW);
    digitalWrite (led, LOW);
    conta = 0;
    cont = 0;
    x = 0;
  }
  if (puls1 == HIGH) {
    timer = millis();
    inciclo = 0;
  }
  if ((millis() - timer) > t_ciclo_c && puls1 == LOW) {
    inciclo = 1;
    timer1 = millis();
  }
  if (millis() - timer1 > 30000) { // power saving 30 secondi
    enterSleep();
    timer1 = millis();
  }
}
void enterSleep() {
  GIMSK |= _BV(PCIE);                     // Enable Pin Change Interrupts
  PCMSK |= _BV(PCINT4);                   // Use PB3 as interrupt pin
  ADCSRA &= ~_BV(ADEN);                              // ADC off
  set_sleep_mode(SLEEP_MODE_PWR_DOWN);    // replaces above statement  
  sleep_enable();                         // Sets the Sleep Enable bit in the MCUCR Register (SE BIT)
  sei();                                  // Enable interrupts
  sleep_cpu();                            // sleep
  cli();                                  // Disable interrupts
  GIMSK &= ~(1<<PCIE);                    // Disable Pin Change Interrupts
  PCMSK &= ~_BV(PCINT4);                  // Turn off PB3 as interrupt pin
  sleep_disable(); 
  ADCSRA |= _BV(ADEN);                    // ADC on
  sei();    // Enable interrupt
  
}
ISR(PCINT_vect) {
}

No io intendo togliere tutto, non solo alleggerirlo, lascia solo lo sleep e il setup. Il led lo accendi non solo nel setup e può essere che tu finisca in qualche if senza accorgetene, anche se non mi sembra questo il caso. Io farei comunque una prova

#include <avr/sleep.h>


int led = 0;
int rele = 1;
int ok = 2;
int puls = 4;
int set = 3;
int conta = 0;
int t_ciclo=1;
int long t_ciclo_c;
int ok1; // contatore
int cont; // contatore
int  t_ciclo_com=1;
long int  t_ciclo_comp=1;
int puls1; // contatore
int set1;
int x = 1;
int cicli=3;
int inciclo = 0;
unsigned long int timer = 0;
unsigned long int timer1 = 0;

void setup () {
  pinMode (led, OUTPUT);
  pinMode (rele, OUTPUT);
  pinMode (puls, INPUT);
  digitalWrite(puls, HIGH);
  pinMode (set, INPUT);
  pinMode (ok, INPUT);
  digitalWrite (rele, LOW);
  puls1 = digitalRead (puls);
  digitalWrite (led, HIGH);
  delay (300);
  set1 = digitalRead (set);
  digitalWrite (led, LOW);
  delay (500);
  t_ciclo_comp = t_ciclo_com * 10000;
  t_ciclo_c = t_ciclo * 100;
}
void loop() {

  if (millis() - timer1 > 2000) { // power saving 2 secondi
    enterSleep();
    timer1 = millis();
  }
}
void enterSleep() {
  GIMSK |= _BV(PCIE);                     // Enable Pin Change Interrupts
  PCMSK |= _BV(PCINT4);                   // Use PB3 as interrupt pin
  ADCSRA &= ~_BV(ADEN);                              // ADC off
  set_sleep_mode(SLEEP_MODE_PWR_DOWN);    // replaces above statement  
  sleep_enable();                         // Sets the Sleep Enable bit in the MCUCR Register (SE BIT)
  sei();                                  // Enable interrupts
  sleep_cpu();                            // sleep
  cli();                                  // Disable interrupts
  GIMSK &= ~(1<<PCIE);                    // Disable Pin Change Interrupts
  PCMSK &= ~_BV(PCINT4);                  // Turn off PB3 as interrupt pin
  sleep_disable();
  ADCSRA |= _BV(ADEN);                    // ADC on
  sei();    // Enable interrupt
  
}
ISR(PCINT_vect) {
}

Salve a tutti, oggi ho provato la nuova configurazione , ho eliminato la maggior parte degli if e ho lasciato solo due impostazioni da utilizzare con due tasti diversi, alla pressione di ognuno si attivano dei lampeggi dei led, mi serve per capire cosa stanno facendo e se rispondono correttamente, da prove effettuate dopo lo sleep mi viene sempre riavvitato il codice , me ne accorgo dai tre lampeggi, sembra che la configurazione dell'interruput abbia cambiato modo di lavorare del pulsante e successivamente non viene più ripristinata, in basso il codice, il secondo tasto dopo lo sleep lavora normalmente e mi attiva la sequenza di accensione led

//test sleep 


#include <avr/sleep.h>

int led = 0;
int rele = 1;
int ok = 2;
int puls = 4;
int conta = 0;
int t_ciclo=1;
int long t_ciclo_c;
int ok1; // contatore
int cont; // contatore
int puls1; // contatore
int set1;
int x = 1;
int cicli=3;
int inciclo = 0;
unsigned long int timer;
unsigned long int timer1;

void setup () {
  pinMode (led, OUTPUT);
  pinMode (rele, OUTPUT);
  pinMode (puls, INPUT);
  digitalWrite(puls, HIGH);
  pinMode (ok, INPUT);
  digitalWrite (rele, LOW);
  puls1 = digitalRead (puls);
  digitalWrite (led, HIGH);
  delay (200);
  digitalWrite (led, LOW);
  delay (200);
  digitalWrite (led, HIGH);
  delay (200);
  digitalWrite (led, LOW);
  delay (200);
  digitalWrite (led, HIGH);
  delay (200);
  digitalWrite (led, LOW);
  delay (200);
  t_ciclo_comp = t_ciclo_com * 10000;
  t_ciclo_c = t_ciclo * 100;
}
void loop() {
  ok1 = digitalRead(ok);
  puls1 = digitalRead (puls);
  if (ok1 == LOW) {
    digitalWrite (led, HIGH);
    digitalWrite (rele, HIGH);
    delay (1000);
    digitalWrite (led, LOW);
    digitalWrite (rele, LOW);
  }
  if ( puls1 == LOW) {
   digitalWrite (led, HIGH);
   digitalWrite (rele, HIGH);
  delay (300);
  digitalWrite (led, LOW);
  digitalWrite (rele, LOW);
  delay (500);
     digitalWrite (led, HIGH);
     digitalWrite (rele, HIGH);
  delay (300);
  digitalWrite (led, LOW);
  digitalWrite (rele, LOW);
  delay (500);
    timer1 = millis();
  }
  if (millis() - timer1 > 30000) { // power saving 30 secondi
    enterSleep();
    timer1 = millis();
  }
}
void enterSleep() {
  GIMSK |= _BV(PCIE);                     // Enable Pin Change Interrupts
  PCMSK |= _BV(PCINT4);                   // Use PB3 as interrupt pin
  ADCSRA &= ~_BV(ADEN);                              // ADC off
  set_sleep_mode(SLEEP_MODE_PWR_DOWN);    // replaces above statement  
  sleep_enable();                         // Sets the Sleep Enable bit in the MCUCR Register (SE BIT)
  sei();                                  // Enable interrupts
  sleep_cpu();                            // sleep
  cli();                                  // Disable interrupts
  GIMSK &= ~(1<<PCIE);                    // Disable Pin Change Interrupts
  PCMSK &= ~_BV(PCINT4);                  // Turn off PB3 as interrupt pin
  sleep_disable(); 
  ADCSRA |= _BV(ADEN);                    // ADC on
  sei();    // Enable interrupt
  
}
ISR(PCINT_vect) {
}

ho provato ad effettuare altre prove, da come ho capito non mi elabora questo codice (in basso) e viene effettuato un reset con la configurazione del pin non modificata, stranamente ogni volta che premo il pulsante della porta CINT4 si attiva un reset

  cli();                                // Disable interrupts
  GIMSK &= ~(1<<PCIE);                    // Disable Pin Change Interrupts
  PCMSK &= ~_BV(PCINT4);                  // Turn off PB3 as interrupt pin
  sleep_disable();
  ADCSRA |= _BV(ADEN);                    // ADC on
  sei();    // Enable interrupt

Salve ragazzi, finalmente dopo tante prove e ricerche su internet sono riuscito a risolvere il problema, adesso il codice non si resetta e si comporta come dovrebbe , ho dovuto inserire la funzione
ISR(BADISR_vect) {} , come potete vedere il reset del pin chage interrupt e suo azzeramento l'ho inserito in questa funzione e adesso lavora correttamente
grazie per l'aiuto

//test sleep

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

int led = 0;
int rele = 1;
int ok = 2;
int puls = 4;
int conta = 0;
int t_ciclo = 1;
int long t_ciclo_c;
int ok1; // contatore
int cont; // contatore
int puls1; // contatore
int set1;
int x = 1;
int cicli = 3;
int inciclo = 0;
unsigned long int timer;
unsigned long int timer1;
void setup () {
  pinMode (led, OUTPUT);
  pinMode (rele, OUTPUT);
  pinMode (puls, INPUT);
  digitalWrite(puls, HIGH);
  pinMode (ok, INPUT);
  digitalWrite (rele, LOW);
  puls1 = digitalRead (puls);
  digitalWrite (led, HIGH);
  delay (200);
  digitalWrite (led, LOW);
  delay (200);
  digitalWrite (led, HIGH);
  delay (200);
  digitalWrite (led, LOW);
  delay (200);
  digitalWrite (led, HIGH);
  delay (200);
  digitalWrite (led, LOW);
  delay (200);
}
void loop() {
  ok1 = digitalRead(ok);
  puls1 = digitalRead (puls);
  if (ok1 == LOW) {
    digitalWrite (led, HIGH);
    digitalWrite (rele, HIGH);
    delay (1000);
    digitalWrite (led, LOW);
    digitalWrite (rele, LOW);
  }
  if ( puls1 == LOW) {
    digitalWrite (led, HIGH);
    digitalWrite (rele, HIGH);
    delay (300);
    digitalWrite (led, LOW);
    digitalWrite (rele, LOW);
    delay (500);
    digitalWrite (led, HIGH);
    digitalWrite (rele, HIGH);
    delay (300);
    digitalWrite (led, LOW);
    digitalWrite (rele, LOW);
    delay (500);
    timer1 = millis();
  }
  if (millis() - timer1 > 30000) { // power saving 30 secondi
    enterSleep();
    timer1 = millis();
  }
}
void enterSleep() {
  GIMSK |= _BV(PCIE);                     // Enable Pin Change Interrupts
  PCMSK |= _BV(PCINT4);                   // Use PB3 as interrupt pin
  ADCSRA &= ~_BV(ADEN);                              // ADC off
  set_sleep_mode(SLEEP_MODE_PWR_DOWN);    // replaces above statement
  sleep_enable();                         // Sets the Sleep Enable bit in the MCUCR Register (SE BIT)
  sei();                              // Enable interrupts
  sleep_cpu();                            // sleep
  sleep_disable();
}
ISR(PCINT_vect) {
}
ISR(BADISR_vect) {
  cli();                                // Disable interrupts
  GIMSK &= ~(1<<PCIE);                    // Disable Pin Change Interrupts
  PCMSK &= ~_BV(PCINT4);                  // Turn off PB3 as interrupt pin
  sleep_disable();
  ADCSRA |= _BV(ADEN);                    // ADC on
  sei();    // Enable interrupt
}