Risparmio energetico con watchdog e risveglio seriale

Buonasera,
Sto utilizzando in uno sketch il watchdog per addormentare Arduino ogni 4 secondi, eseguire il loop e se non deve irrigare il semenzaio si riaddormenta...fin qui nessun problema. Per la comunicazione ad Arduino ho scelto la seriale tramite un bluetooth visto che si troverà in una scatola stagna nel tetto. Ora, vorrei capire innanzitutto se è possibile fargli capire ad arduino:
Se c'è un dispositivo che sta tentando di connettersi allora resta sveglio fin quando si scollega..altrimenti continua il loop fino a quando si invoca la funzione di addormentamento etc...

Per ora utilizzo la modalità più profonda del sonno, ovvero la SLEEP_MODE_PWR_DOWN
Ma non conosco e non trovo online cosa disabilitano le altre modalità di risparmio energetico:
SLEEP_MODE_IDLE
SLEEP_MODE_ADC
SLEEP_MODE_PWR_SAVE
SLEEP_MODE_STANDBY

e nello specifico

Buongiorno,
Ti ringrazio Brunello ho visto il link che mi hai inviato (l'ideale per la mia richiesta) e ti ringrazio molto. Vorrei tornare un attimo al mio sketch..
Utilizzando questo codice:

//Appena lo sketch arriva al void enterSleep(void) allora dorme per 4 secondi.
#include <avr/sleep.h>
#include <avr/power.h>
#include <avr/wdt.h>
volatile int watchdog = 1;
int led = 13;
int contatore = 0;
void setup()
{
  Serial.begin(9600);
  pinMode(led, OUTPUT);
  MCUSR &= ~(1 << WDRF); //AZZERA IL FLAG DI RESET
  WDTCSR |= 1 << WDCE | 1 << WDE; //ATTIVA LA MODALITA' DI MODIFICA DEI REGISTRI (DISPONIBILE SOLO PER I PROSSIMI 4 CICLI DI CLOCK!)
  //WDTCSR = 1 << WDP0 | 1 << WDP3; //PRESCALEER A 8 SECONDI
  WDTCSR = 0 << WDP0 | 1 << WDP3; //PRESCALER A 4 SECONDI
  WDTCSR |= _BV(WDIE); //MODO: INTERRUPT
}
int stato = LOW;
void loop()
{
  if (watchdog == 1)
  {
    Serial.println("fra 5 secondi dorme..");
    delay(3000);
    Serial.println("fra 2 secondi dorme..");
    delay(2000);
    Serial.println("sta dormendo..");
    watchdog = 0;
    enterSleep();
  }
}
ISR(WDT_vect)
{
  if (watchdog == 0)
  {
    watchdog = 1;
  }
}
void enterSleep(void)
{
  set_sleep_mode(SLEEP_MODE_PWR_DOWN);
  sleep_enable(); // abilita riposo
  sleep_mode();   // attiva riposo
  sleep_disable(); //disabilita riposo
  power_all_enable();
}

ogni 5 secondi (il tempo di un loop) si addormenta per 4 secondi utilizzando il timer del watchdog. Questi sono i consumi rilevati da un amperometro:

Componenti
Arduino + HC-05
Sveglio: 67-68mA
Addormentato: 60-61mA

Componenti
Solo Arduino
Sveglio: 29.5mA
Addormentato: 22mA

Non torna secondo me...utilizzando il sonno più profondo, dovrebbe esserci un consumo di uA invece c'è una differenza di soli 7-8mA...come mai?

P.S: stessa cosa succede con il link che hai inviato seguendo il codice per il risveglio in seriale ovvero:

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

const byte AWAKE_LED = 8;
const byte GREEN_LED = 9;
const unsigned long WAIT_TIME = 5000;

ISR (PCINT2_vect)
{
  // handle pin change interrupt for D0 to D7 here
}  // end of PCINT2_vect

void setup() 
{
  pinMode (GREEN_LED, OUTPUT);
  pinMode (AWAKE_LED, OUTPUT);
  digitalWrite (AWAKE_LED, HIGH);
  Serial.begin (9600);
} // end of setup

unsigned long lastSleep;

void loop() 
{
  if (millis () - lastSleep >= WAIT_TIME)
  {
    lastSleep = millis ();

    noInterrupts ();

    byte old_ADCSRA = ADCSRA;
    // disable ADC
    ADCSRA = 0;  
    // pin change interrupt (example for D0)
    PCMSK2 |= bit (PCINT16); // want pin 0
    PCIFR  |= bit (PCIF2);   // clear any outstanding interrupts
    PCICR  |= bit (PCIE2);   // enable pin change interrupts for D0 to D7

    set_sleep_mode (SLEEP_MODE_PWR_DOWN);  
    power_adc_disable();
    power_spi_disable();
    power_timer0_disable();
    power_timer1_disable();
    power_timer2_disable();
    power_twi_disable();

    UCSR0B &= ~bit (RXEN0);  // disable receiver
    UCSR0B &= ~bit (TXEN0);  // disable transmitter

    sleep_enable();
    digitalWrite (AWAKE_LED, LOW);
    interrupts ();
    sleep_cpu ();      
    digitalWrite (AWAKE_LED, HIGH);
    sleep_disable();
    power_all_enable();

    ADCSRA = old_ADCSRA;
    PCICR  &= ~bit (PCIE2);   // disable pin change interrupts for D0 to D7
    UCSR0B |= bit (RXEN0);  // enable receiver
    UCSR0B |= bit (TXEN0);  // enable transmitter
  }  // end of time to sleep

  if (Serial.available () > 0)
  {
    byte flashes = Serial.read () - '0';
    if (flashes > 0 && flashes < 10)
      {
      // flash LED x times 
      for (byte i = 0; i < flashes; i++)
        {
        digitalWrite (GREEN_LED, HIGH);
        delay (200);  
        digitalWrite (GREEN_LED, LOW);
        delay (200);  
        }
      }        
  }  // end of if

}  // end of loop

Fare quello che stai facendo su una scheda Arduino NON ha alcun senso ...
... il consumo della MCU, rispetto a quello di tutto ciò che c'è sulla scheda è irrisorio e quindi il risparmio è praticamente nullo.

Quelle cose si fanno su circuiti progettati ad hoc (es. uno standalone) dove si toglie tutto il superfluo e si spengono tutti i device non necessari.

Se proprio vuoi usare una scheda standard già fatta, puoi usare gli Arduno Pro Mini, meglio se a 3.3V, tagliando anche via il LED power così da avere veramente solo il minimo indispensabile (... niente LED, niente regolatori, niente USB, ecc. ecc.)

Guglielmo

Riguardo all' HC-05, dovrebbe consumare circa 30-40mA durante il Pairing e scendere a circa 8mA dopo che si ' accoppiato.
Tu rilevi valori un po' più alti perchè sicuramente lo colleghi al 5V.

Buonasera,
Pensavo che la modalità risparmio energetico riguardasse l'intera scheda Arduino, detto questo, mi viene un dubbio pensando alla risposta di Brunello ovvero: utilizzando un atmega standalone, collegato un bluetooth a 3.3V, avrei un consumo in pairing di 30-40mA e quando accoppiato a 8mA? Non è possibile ridurre ancora di più il consumo del modulo Bluetooth? Magari in ATmode c'è un comando per il risparmio energetico ..

avrei un consumo in pairing di 30-40mA e quando accoppiato a 8mA?

Questo è quello che dichiarano, ma non l'ho mai controllato

Non è possibile ridurre ancora di più il consumo del modulo Bluetooth? Magari in ATmode c'è un comando per il risparmio energetico ..

Non mi risulta che si possa mettere l' HC-05 in stanby e oltretutto, visto che vuoi risvegliare il Micro con la seriale se l'HC-05 fosse appunto disabilitato non potresti farlo.

Grazie Brunello, l'unica maniera sembra risolversi con un semplice interruttore sull'alimentazione dell'HC-05

piccola domanda per gpb: utilizzando QUESTA scheda pro mini..posso scegliere tra 5V e 3.3V? Sul retro della scheda sembrano esserci tutti e due le alimentazioni..(ovviamente non si appplicano i 5V su 3.3V non essendoci regolatori).
E poi, quant'è la differenza tra un atmega-standalone e una scheda pro mini (tagliando pure il led di accensione) in termini di consumo energetico?

Per chi vuole il massimo del risparmio energetico deve optare comunque a un MCU standalone?

... decidi se vuoi lavorare a 5V o a 3.3V (scelta consigliata per chi cerca bassi consumi) e prendi una Pro Mini SOLO per quella tensione (quelle a 5V vanno a 16 MHz, quelle a 3.3V vanno a 8MHz) ed elimina il LED e l'eventuale regolatore per i 5V.

Tra una di queste e lo standalone NON c'è praticamente alcuna differenza dato che sulle Pro Mini a voltaggio fisso c'è veramente SOLO il minimo indispensabile (... come detto, NO regolatori, NO LED, NO interfaccia USB, ecc.).

Guglielmo

Ok gpb, adesso ho capito.

Ultima domanda..mettiamo l'ipotesi di avere una stazione meteorologica con pluviometro, bmp180, sht31, bluetooth, anemometro, misurazioni di qualità ambientali etc..
Se tutti questi sensori vanno alimentati e pilotati dall' MCU, una volta che quest'ultimo è addormentato.. i sensori comunque stanno consumando energia perché non vanno in standby..e allora, il consumo è irrisorio oppure è possibile ottimizzare il consumo dei sensori via software? Non ha molto senso mettere un interruttore manuale che stacchi i sensori quando proprio la stazione meteorologica ogni 15-20min dovrebbe rilevare i dati..

Se lasci i sensori attivi inutile mettere in sleep la MCU ...
... devi usare un pin per controllare un MOSFET con cui accendi e spegni, all occorrenza, i devices.

Vai in sleep profondo, ti fai svegliare dal watchdog ogni X sec. vedi se la somma dei secondi passati ha raggiuto i 15 minuti, se no, ti riaddormenti; se si accendi i devices, aspetti il tempo necessario per il loro stabilizzarsi, li leggi, li rispegni e rivai in sleep.

Guglielmo

Ok, se ho capito bene basta utilizzare un MOSFET Logic
Level se si usano tensioni differenti a 5V come per esempio sensori a 3.3V..basta collegare in parallelo ogni carico nel caso di questa foto:
In parallelo alla lampada giusto?

Positivo del carico all'alimentazione e negativo al drain

una stazione meteorologica con pluviometro, bmp180, sht31, bluetooth, anemometro, misurazioni di qualità ambientali etc..

Esatto, puoi mettere il Micro in Sleep e disattivare l'alimentazione delle periferiche, con un Mosfet, e ridurre quindi drasticamente i consumi.
Però con il risveglio dallo Sleep in un modo un pò diverso di quanto suggerito da Guglielmo, dato che il Pluviometro deve rimanere comunque attivo

Uhm..sempre attivo perché? Si potrebbe mettere un ciclo while e finché il pluviometro rileva acqua allora non esce dal ciclo..in caso contrario continua fin quando a fine loop non c'è il richiamo ad addormentarsi, o sbaglio?
Non ho mai usato un pluviometro quindi non so se si possa fare come detto

Un pluviometro non è altro che un "bilancino" che quando è pieno d'acqua si abbassa, si svuota e contemporaneamente chiude un contatto .
Con il Micro rilevi appunto la chiusura di detto contatto e la frequenza con cui si chiude ti dice quanta pioggia c'è stata.

Ora, tu devi comunque rilevare la chiusura del contatto, anche mentre il Micro è in Sleep e lo puoi fare in un modo simile a quello che hai usato per risvegliarlo da un input della seriale.
Non puoi fare come dici tu, visto che non sai a che frequenza si chiude il contatto e potrebbe bensissimo venire un acquazzone nei 15 minuti che il Micro stà dormendo

Premesso che mi interessa approfondire perché ho in progetto una stazione meteorologica a pannello solare, se andiamo OT possiamo tranquillamente chiudere e quando avrò il materiale mi documenteró..
Detto questo, se entro nelle linee di comportamento di questo forum, posso dire che se uso due MOSFET dove in un uno applico tutti gli altri sensori e nell'altro il pluviometro, impostando il watchdog a 4 o 8 secondi, quando si risveglia Arduino, controlla se piove, se si entra in while fin quando non piove più, se no controlla se sono passati 15 minuti e così se la condizione è vera si attiva il secondo MOSFET quindi si alimentano gli altri sensori, si legge, memorizza e addormenta di nuovo l'MCU..
Ammesso che si possa fare, ci sarà il problema che non rileva altri dati se piove...

Immagino che il pluviometro utilizzi un interrupt

Tosto, eh !!
Quando si chiude il contatto reed del pluviometro, quanto potra' durare questo stato ? 100 mS..
Se tu risvegli il Micro ogni 4/8 secondi, come fai a capire se il contatto si è chiuso ? Mica rimane nello stato di chiuso finche non lo leggi

Quindi si usa un interrupt e il micro sta acceso finché non piove, poi, se non piove si accende ogni 15 minuti con il watchdog...

... neanche io ho mai usato un "pluviometro", ma, se come descritto, invia degli impulsi all'oscillare di un "bilancino", mi sembra abbastanza semplice unire le due tecniche di risveglio:

a) watchdog con tempi lunghi nelle situazioni normali (... massimo di economia dell'energia)

b) interrupt generato dal pluviometro. Risveglio della sola MCU (non di tutti gli altri devices), incremento di un contatore, sleep. Poi al prossimo risveglio da watchdog si controlla il contatore e si sa quanti impulsi sono arrivati dal pluviometro.

Ovviamente, l'unica cosa che NON si può spegnere ... è il pluviometro (... del quale non conosco gli assorbimenti, ma, da come descritto, non credo siano un gran che), per tutto il resto, vale quanto detto prima.

Guglielmo