[RISOLTO] Modalità sleep e uso del monitor seriale

Salve a tutti,
è un bel pò che non riesco a risolvere un problema, e nonostante stia cercando soluzioni in rete non riesco a venirne a capo.
Ho la necessità di mettere un ATMega standalone (che funge da datalogger) in modalità sleep e di trasferire via radio i dati ad una scheda arduino. La modalità sleep l’ho già implementata, grazie alle spiegazioni di Leonardo milani trovate qui:
http://www.leonardomiliani.com/2013/impariamo-ad-usare-il-watchdog-2/.

Ho anche inserito nello stesso codice la parte necessaria a registrare su una SD Card le informazioni del datalogger.
Il tutto (modalità sleep + registraz. su sd card) funziona bene, ma se cerco di visualizzare la stessa stringa usata per la SDcard sul Serial Monitor ottengo solo qualche carattere random strano.

Chiaramente la disponibilità della stringa sulla seriale sarebbe propedeutica al suo invio tramite il modulo radio.

Spero che possiate aiutarmi, sono ancora un principiante, ma spero di imparare presto! :wink:

Allego il codice che sto usando

#include <SD.h>      
#include <avr/wdt.h>
#include <avr/sleep.h>
#include <avr/power.h>
const byte LED13 = 13;
byte ledStatus = 1;
volatile unsigned int counter = 0;
volatile byte flag = 0;
File dataFile;
const int chipSelect = 10;

int buzz = 8;   
int led = 9;    


void setup()
{
  Serial.begin(9600);  // Apre la comunicazione seriale e attende l'apertura della porta:

  pinMode(7, OUTPUT);       

  pinMode(buzz, OUTPUT);
  pinMode(led, OUTPUT); 
  pinMode(10, OUTPUT);      // Assicurarsi che il chip select di default sia settato ad Output, anche se non se ne fa uso.

  if(SD.exists("DATALOG.TXT"))
  {
    //  Serial.println("File found");
  }
  else
  {
    dataFile = SD.open("datalog.txt", FILE_WRITE);  // Apertura del File Datalog, Solo un file alla volta può essere aperto.
    dataFile.close();
  }

  //  Wire.begin();

  MCUSR = 0;      //resetta il registro di stato della MCU
  wdt_disable();  //disattiva il watchdog

  setWdt();       //imposta il watchdog
 
  set_sleep_mode(SLEEP_MODE_PWR_DOWN);  //imposta lo sleep

}

void loop()
{
  power_all_disable();
  sleep_mode();             // attivazione sleep
  power_all_enable();
  if (flag) {
    wdt_disable();
    counter = 0;
    flag = 0;

    String dataString = "";

    digitalWrite(7, HIGH);
    digitalWrite(led, HIGH);
    delay(500);    

    int Hum1 = analogRead(A3);

    dataString += String(Hum1); 
    digitalWrite(7, LOW);
    digitalWrite(led, LOW);

    dataString += "   ";
    delay(500); 


    dataFile = SD.open("datalog.txt", FILE_WRITE);  // Apertura del File Datalog, Solo un file alla volta può essere aperto. 

    if (dataFile)
    {                                     // Se il file è disponibile allora scrivi su di esso
      dataFile.println(dataString);       // Inserisco su una nuova linea la stringa con i dati dell'ultimo ciclo di letture
      dataFile.close();                   // Chiudo il File
    }


//  ----------------------------
    Serial.println(dataString);         // DOVREBBE VISUALIZZARE LA STRINGA SUL MONITOR SERIALE
//  ----------------------------


    ledStatus ^= 1; //cambio lo stato al led
    digitalWrite(LED13, ledStatus);
    setWdt(); //reimposta il watchdog

  }
}

void setWdt() {
  SREG &= ~(1<<SREG_I); //disattiva tutti gli interrupt
  //imposta il registro del watchdog
  WDTCSR |= ((1<<WDCE) | (1<<WDE));
  //imposta la modalità "interrupt" ed il timeout ad 1 secondo
  WDTCSR = ((1<<WDIE)| (1<<WDP2) | (1<<WDP1)); 
  SREG |= (1<<SREG_I); //riattiviamo gli interrupt globali
}
ISR(WDT_vect) {
  if (++counter >= 10) { //impostare qui il numero di timeout (secondi)
    flag = 1;
  }
}

Domanda stupida: hai impostato il monitor seriale alla stessa velocità del tuo sketch (9600 bps)?

Si, certamente. Tanto più che se elimino la riga di attivazione del sonno, il monitor seriale funziona perfettamente. Questa cosa mi sta facendo diventare pazzo... davvero comincio a pensare di utilizzare un altro protocollo per i moduli radio. Per esempio lo stesso che usa la sd card sarebbe possibile?

Mi spiacerebbe molto però abbandonare la seriale solo per non aver capito qualcosa.

I dati dalla seriale non escono subito al Serial.print. Prima vengono messi in un buffer software, poi da qui un interrupt li spedisce al buffer seriale, byte per byte, finché non sono stati trasmessi tutti.

Se metti in sleep il chip prima che i dati siano stati spediti tutti, puoi avere dei problemi. prova usando il metodo flush della seriale, per aspettare la fine materiale della trasmissione: http://arduino.cc/en/Serial/Flush

Mille grazie LEO!!!! XD XD XD Era proprio quel comando che dovevo usare! Ho provato ad aggiungere subito dopo la serial.print un Serial.flush(); Prima di mandare in sleep il microcontrollore, ora il codice attende che tutti i dati siano riportati nel serial monitor. Avevo notato quel comando in un manuale in pdf ma evidentemente non era aggiornato alla versione di Arduino 1.0 infatti in passato il comando serviva svuotare il buffer dei dati in entrata.

Ancora grazie infinite!

Nell'IDE pre 1.0 (fino alla versione 0023) effettivamente flush() svuotare il buffer seriale. Dalla 1.0 in poi lo hanno cambiato completamente ed ora si mette in attesa che il buffer sia vuoto. Mi fa piacere che tu abbia risolto ;)