Problemi attachInterrupt sleep ATmega328P

Ciao a tutti,
sto cercando di far risvegliare dal sonno profondo una scheda basata su Arduino UNO con Bluetooth integrato. Sto utilizzando il codice suggerito dal produttore, la scheda si sveglia ma non restituisce il valore misurato dal sensore, invia solo 0. Potete aiutarmi a capire dove sto sbagliando? grazie

#include <avr/sleep.h>      //libreria risparmio energetico
#include <avr/wdt.h>
#include <avr/power.h>
#include <avr/interrupt.h>

int var = 5;    //variabile che memorizza il valore letto dal sensore
int sveglia = 0;

const byte interruptPin = 2;

void wakeup(){
  sleep_disable();
  delay(2000);
}

void lowpower(){
 ADCSRA &= ~(1<<ADEN);/*turn off ADC*/
 TWCR &= ~(1<<TWEN);/* turn off TWI*/
 delay(10);
 set_sleep_mode(SLEEP_MODE_PWR_DOWN);/*set sleep mode to power down mode*/
 sleep_enable();/*enable sleep mode */
 MCUCR |= (1<<BODS|1<<BODSE);
 MCUCR = MCUCR & (~(1<<BODSE)) | (1<<BODS);
 sleep_cpu();/*enter sleep mode */
}

void setup(){
  Serial.begin(115200);
  pinMode(5,INPUT);    //dati in INPUT dal pin5, legge il sensore
  attachInterrupt(digitalPinToInterrupt(interruptPin), wakeup, CHANGE);
  /* set interrupt method to trigger D2 to voltage change, callback function is wakeup( ), which means awake functions of the chip 328p*/
  lowpower();
}

void loop(){
  while(Serial.available()) {
    sveglia = Serial.read();
  }
  delay(2000);
  var = digitalRead(5);     //leggi il dato del sensore
  delay(1000);
  Serial.write(var);
  Serial.flush();
  delay(1000); 

  lowpower();
  delay(2000);
}

Che sensore? con la digitalRead sul pin 5 i soli possibili valori restituiti sono 0 (anche detto LOW) e 1 (anche detto HIGH)
Se devi leggere un sensore (Es. DHT22, DS18B20, ecc.) devi usare l'apposita libreria (se esiste) o leggere il sensore come raccomandato dal produttore del sensore stesso.

E' un sensore digitale (questo) che funziona perfettamente. I problemi sono nati ora che sto cercando di attivare il risparmio energetico...

Il problema lo riscontri immediatamente al primo ripristino dal low power o al primo giro funziona e dal secondo "risveglio" in poi non funziona più?

Con questo codice non ho problemi:

int var = 5;    //variabile che memorizza il valore letto

void setup(){
  Serial.begin(115200);
  pinMode(5,INPUT);    //dati in INPUT dal pin5, legge il sensore
}

void loop(){
  var = digitalRead(5);
  delay(100);
  Serial.write(var);
  delay(1000); 
}

Ma appena carico il codice con lo sleep restituisce solo 0 dal primo ripristino dal lowpower. Credevo fosse un problema di tempo e ho inserito Serial.flush, ma ancora non riesco ad ottenere il valore coretto.

Dalle foto mi sembra che la breakout board sia completamente passiva (immagino un semplice partitore resistivo), quindi non vedo perché non debba funzionare anche dopo il resume dalla modalità sleep.

Purtroppo non ho mai fatto una cosa simile quindi non so consigliarti, ma "a naso" al tuo posto mi concentrerei più che altro sulla funzione lowpower() come attivi la modalità sleep.

Hai già provato a guardare QUI? Mi sembra che dicano cose leggermente diverse da quanto fai nel tuo codice.

E' strano non ci vedo nulla di particolare, posso suggerirti di provare vari livelli di sleep evitando di disattivare el varie periferiche (ADC, I2C, ecc) lascia solo il codice minimo indispensabile e vediamo se ancora ti da il problema. Se ancora è errato il risultato allora alza il livello di sleep a qualcosa di meno "risparmioso" quando arrivi al codice che non ti da il problema analizziamo da cosa potrebbe dipendere, a regola la digitalread non dovrebbe essere errata, mi aspettavo un problema se effettuavi una lettura analogica (avendio spento l'adc).
L'altra cosa che puoi provare prima di cercare di smontare tutto il codice è quella di accedere direttamente al registro in memoria collagato al pin 5, elimini la digitalread e leggi il bit 5 di PORTD (se non erro è quello) e vedi che risultato ti da.
O ancora invece di usare la seriale per ottenere la risposta (l'inghippo potrebbe essere nascost li) definisciu un'altro pin (anche il 13 va bene avendo il led integrato) come output e fai una digitalWrite usando il valore restituito dalla digitalRead sul pin 5, se tutto funziona si accende il led se il sensore è a contatto dell'acqua, altrimenti resta spento. A quel punto riattivi lo sleep e vedi se alla riaccensione il led funziona (e il problema è nella seriale quindi) o se anche quello non va

Grazie per le indicazioni.

@docdoc ho provato a modificare il codice seguendo il link, ma non cambia il risultato.

@fabpolli ho provato i diversi livelli di sleep, ma niente. Ho quindi provato ad utilizzare solo l'interruttore, senza sleep, e sembra che il problema sia in questo passaggio. Con questo codice ottengo sempre e solo 160, e non riesco a capire il senso:

int interr = 1;

const byte interruptPin = 2;

void wakeup(){
  interr++;
}


void setup(){
  Serial.begin(115200);
  attachInterrupt(digitalPinToInterrupt(interruptPin), wakeup, CHANGE);
}

void loop(){
  Serial.write(interr);
  Serial.flush();
  delay(100); 
}

E' corretto? Che ne pensate? Vi ringrazio.

la dichiarazione della variabile non è consona...

You should declare as volatile any variables that you modify within the attached function. See the section on ISRs below for more information.

Grazie per le indicazioni. Dopo diverse prove questo è il codice funzionante, ma non riesco ad arrivare alla modalità sleep_down:

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

int var = 1; 
   
void wakeup(){
  sleep_disable();
  detachInterrupt(0);
}

void lowpower(){
  set_sleep_mode(SLEEP_MODE_IDLE);   
  sleep_enable();                     
  attachInterrupt(0, wakeup, CHANGE);
  sleep_mode();
}

void setup(){
  Serial.begin(115200);
  pinMode(5,INPUT);    //dati in INPUT dal pin5, legge il sensore
}


void loop(){
  var = digitalRead(5);
  delay(1000);
  Serial.write(var);
  Serial.flush(); 
  lowpower();
  delay(2000);
}

Come adattereste questo codice per poter inviare una lettura digitale dal sensore collegato al pin5 ? Ho provato in tutti i modi ma non trovo soluzione. Qualunque suggerimento, anche minimo, è di grande aiuto. Grazie!

void wakeup(){
  sleep_disable();
}

void lowpower(){
 ADCSRA &= ~(1<<ADEN);/*turn off ADC*/
 TWCR &= ~(1<<TWEN);/* turn off TWI*/
 delay(10);
 set_sleep_mode(SLEEP_MODE_PWR_DOWN);/*set sleep mode to power down mode*/
 sleep_enable();/*enable sleep mode */
 MCUCR |= (1<<BODS|1<<BODSE);
 MCUCR = MCUCR & (~(1<<BODSE)) | (1<<BODS);
 sleep_cpu();/*enter sleep mode */
}

void setup() {
 attachInterrupt(0, wakeup, CHANGE);
 /* set interrupt method to trigger D2 to voltage change, callback function is wakeup( ), which means awake functions of the chip 328p*/
 lowpower();
}


void loop() {
 lowpower();
 delay(2000);
}

inviarlo dove?
una volta che hai letto il sensore
con la lettura ci fai quello che vuoi
quello che avevi scritto più sopra... funziona

 var = digitalRead(5);
 // delay(1000);   // questo delay è inutile
  Serial.write(var);

Devo svegliare il BLuetooth e inviare il dato ad un altro bluetooth. Si, il codice scritto sopra funziona, ma quando provo a implementare il sleep.mode non invia niente. L’ultimo codice che ho pubblicato è quello suggerito dal produttore, ma non riesco a farlo funzionare.

Per svegliarlo invio questo dall’altra scheda (uguale):

Serial.write(HIGH);

ma non ricevo niente in risposta. Qualche suggerimento?

prova a studiarti questo Gammon Forum : Electronics : Microprocessors : Power saving techniques for microprocessors e a vedere se trovi qualche risposta...

Resto dell'idea che dovresti fare un progrmma di minima con pulsante e led e vedere se dopo lo slepp, quando arriva l'interrupt dal pulsante il led cambia stato da spento ad acceso e viceversa per ogni pressione di pulsante, sia che non sia in sleep che arduinop sia in sleep.
Comunque altra cosa se il pulsante è fisico proverei anche a mettere una bella pullup e userei anzi il FALLING anziché il CHANGE (o una pulldown e il RAISING) per vedere che non sia quello legato anche a un problema software

@Patrick_M grazie, ho provato mille combinazioni senza risultato.

@fabpolli grazie, ho provato a seguire il tuo suggerimento e ho impostato questi codici:

MASTER

int a = 1;
void setup(){
  Serial.begin(9600);
}

void loop(){
  Serial.write(a);
  delay(10000);
}

SLAVE

int a = 0;

void setup() {
  Serial.begin(9600);
  pinMode(LED_BUILTIN, OUTPUT);
}

void loop() {
  while(Serial.available()){
    a = Serial.read();
  }
  if (a = 1){
    digitalWrite(LED_BUILTIN, HIGH);     // turn the LED on (HIGH is the voltage level)
    delay(1000);                                  // wait for a second
    digitalWrite(LED_BUILTIN, LOW);    // turn the LED off by making the voltage LOW
    delay(1000);                                // wait for a second
    a = 0;
  }
}

Ho provato senza sleep. Purtroppo non funziona nemmeno questa soluzione, ho sbagliato qualcosa nei codici? Non ho pulsanti fisici per poter provare in altri modi....

Si:

if (a = 1)

è sbagliato ci va ==.
ma comunque non è quello che intendevo io, ovvero fai un piccolo programma nuovo (non modificare quello che hai ma fanne un'altro) dove la seriale proprio non la consideri, lasci solo la parte di gestione del pulsante e dello sleep, ad ogni pressione il codice accende o spegne il led sullo STESSO Arduino non inviandolo all'altro. Per verificare se il risveglio dallo sleep funziona correttamente, in tal caso il problema è nell'invio sulla seriale e lo si affronta poi, se invece non funziona allora il problema è nel codcie del risveglio dalla sleep

grazie.

Il problema è che il pulsante è gestito dal bluetooth, la seriale serve per inviare il segnale al pulsante...non saprei come farlo diversamente, non ho pulsanti fisici... l'unica cosa che mi viene in mente è utilizzare il sensore come input HIGH...potrebbe funzionare?

Visto il tuo sensore direi proprio di si, va HIGH quando l’acqua lo tocca, lo colleghi al pin di interrupt e sei a posto per la prova

Ho fatto la prova collegando il sensore digitale al pin D2 e funziona, il led si accende quando il sensore è a contatto con l’acqua! A questo punto il problema è nella comunicazione seriale? Il produttore indica che il chip bluetooth e la board sono collegati con il pin D2, come devo interpretarlo?

Questo è il codice/test Interrupt:

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

void wakeup(){
  sleep_disable();
}

void lowpower(){
  set_sleep_mode(SLEEP_MODE_PWR_DOWN);   //*set sleep mode to power down mode
  sleep_enable();                        //enable sleep mode
  sleep_cpu();
}

void setup() {
  pinMode(LED_BUILTIN, OUTPUT);
  attachInterrupt(0,wakeup,CHANGE); 
}

void loop() {
    digitalWrite(LED_BUILTIN, HIGH);   // turn the LED on (HIGH is the voltage level)
    delay(1000);                       // wait for a second
    digitalWrite(LED_BUILTIN, LOW);    // turn the LED off by making the voltage LOW
    delay(1000);                       // wait for a second

  lowpower();
  delay(500);
}