Scrivo su SD ma il file è vuoto.

Lo sketch allegato, troppo lungo per essere incluso nel forum, è uno schema di datalogger e ha un problema di scrittura su SD.
Il test di scrittura crea il file ma dentro non c’è nulla. E’ vuoto, zero byte.
Ho provato a cambiare SD ma il risultato non cambia.
Se uso il programma di esempio ReadWrite funziona, trovo il file con il testo di esempio.
Uso la libreria SDfat ma anche con la libreria SD standard accade esattamente la stessa cosa. Ma la SDfat dovrebbe essere un aggiornamento della SD, secondo il suo autore.
Se elimino la parte dell’RTC DS1307, funziona.
Uso la libreria DS1307new, se la cambio con RTClib di Adafruit accade esattamente la stessa cosa. Inoltre la libreria Adafruit mi da una serie di 165 invece di data e ora, Ma questo l’ho scritto in un altro post http://forum.arduino.cc/index.php?topic=166715
Come ho scritto in un altro post (http://forum.arduino.cc/index.php?topic=165088.0), se è presente una piccola parte che ha a che fare con il Timer1, il programma va in reset anche se quella parte non viene attivata ancora prima di arrivare ad aprire il file oppure subito dopo averlo aperto.
Sembra un problema di RAM ma i controlli sulla RAM usata danno sempre oltre 700 byte liberi.

Lo sketch gira su Arduino UNO R3 con uno shield per il DS1307 e uno per la SD. Uso le librerie SDfat e DS1307new.
La libreria DS1307new è questa https://code.google.com/p/ds1307new/
La libreria SDfat è questa http://code.google.com/p/sdfatlib/downloads/list
Uso Arduino 1.0.4 dove l’unico cambiamento sta nella libreria java che fa la scansione delle seriali.

Il programma mostra un menù autoesplicativo (più o meno) sulla console seriale. Se premete 9 parte il test di scrittura su SD. Questo stampa su seriale la quantità di RAM subito dopo l’apertura del file e subito dopo la chiusura. Il quantitativo è sempre 897. I test K e k li ho eliminati anche se nel menù appaiono ancora. Qualsiasi comando non riconosciuto, ma anche il semplice invio, fa apparire il menù.

Questo è il codice estratto dallo sketch

void SDwriteTest(){
  Serial.println(F("SD write test1"));
  if (!card.init(SPI_HALF_SPEED, CHIPSELECT)) {
    Serial.println(F("SD init failed."));
    return;
  }
  Serial.println(F("opening"));
  if (!MioFile.open("test.txt", O_WRITE | O_CREAT | O_APPEND)) {
    sd.errorHalt("Failed");
  }
  Serial.println(freeRam());
  ciccio=MioFile.println(F("ProvaF"));
  Serial.println(ciccio, DEC);
  MioFile.close();
  Serial.println(freeRam());
  Serial.println(F("done!"));
}

Io credo lo stesso che sia un problema di RAM, se avessi un Mega farei subito la prova.
Credo anche che sto facendo qualche grossolano errore nel codice perché in giro vedo programmi ben più grossi di questo (ad esempio http://forum.arduino.cc/index.php?topic=132746.0) che non hanno affatto problemi di questo genere. Ecco il motivo per cui ho incluso tutto lo sketch.

Datalogger1_6.zip (2.82 KB)

//pinMode(4, OUTPUT);

hai fatto male a escluderla nel setup, ci va eccome e ci andrebbero anche

digitalWrite(4, 1);
pinMode(10, OUTPUT);
digitalWrite(10, 1);

Ma io non uso lo shield Ethernet! Comunque, fra le varie prove, mi ricordo di avere fatto anche questa.

Ricordo che la creazione del file avviene, solo che è vuoto.

Aggiungo le tue linee e provo.

Edit: niente da fare, sempre zero byte!!!

Grazie lo stesso!

un altra cosa....nell'inizializzazione della SD

Serial.print(F("\nInit SD card..."));
  if (!card.init(SPI_HALF_SPEED, CHIPSELECT)) {
    Serial.println(F("Init failed."));
    return;
  } 
  else {
    Serial.println(F("SD card present")); 
  }

CHIPSELECT lo hai dichiarato 10

#define CHIPSELECT 10  //4 on ethernet card

è il contrario 10 per la ethernet e 4 per la SD, la riga giusta è

if (!card.init(SPI_HALF_SPEED, 4)) {

Ripeto, uso uno shield dove il chipselect è sul 10. Non uso la Ethernet. Il commento in effetti non è chiarissimo per cui ti ha indotto in errore. Lo cambierò.

Aggiungo che gli shield non sono collegati direttamente alla UNO ma al Sensor Shield V5.

Può darsi che mi abbia tratto in inganno, quindi hai un arduino uno, uno shield sensor che credo abbia i pin in parallelo all' UNO, e come SD è uno shield solo sd o una scheda ethernet + sd?

Lo shield Sendor ha un header per la SD con i pin descritti nello sketch.

La SD sta su uno shield con un convertitore di tensione e alcuni condensatori e resistenze SMD. Lo shield con il programma ReadWrite e i collegamenti attuali funziona. Non penso ci siano problemi elettrici, anche se la storia del DS1307, che da me sta su un altro shield con una eeprom, la batteria e pochi altri componenti SMD, mi da da pensare.

Se dallo sketch elimini tutta la parte del DS1307, funziona.

Il mio sospetto principale sta in un errore grossolano nel codice che consuma memoria. O che ci sia una interferenza tra i due shield. Ho anche provato l'alimentazione a parte, non da USB ma il risultato è sempre stato lo stesso.

Edit: Usando la libreria tinyFAT http://henningkarlsen.com/electronics/library.php?id=37 funziona. Freeram mi da sempre 860 in tutte le fasi da apertura a chiusura file, quindi meno della SDfat, eppure funziona, almeno il test. Edit 2: ho scritto all'autore perché non c'è un modo chiaro per definire il pin per CS o SS. A me funziona perché la combinazione sarà giusta ma questo significa che se uso la Ethernet card non mi funzionerà.

x iscrizione

Sebbene cambiando libreria sembri che funzioni a me rimane il dubbio che nel codice ci siano errori grossolani che mi porranno altri problemi di memoria in futuro. La mia esperienza di C su microcontrollori è di pochi mesi, ho usato l'assembler su micro ST (l'ST6 e l'ST9 ma anni fa), basic e assembler su 68HC11 (TFX11, grande scheda!) e poi basic su PC insieme ad un po' di C e Delphi.

Probabilmente lo sai già...

Non è che ti sei dimenticato di formattare la SD con FAT16?

Non dovrebbe essere un problema di formattazione visto che, come ho già scritto, l'esempio ReadWrite funziona, il file viene creato ma è vuoto, se tolgo la libreria DS1307 funziona. Però hai fatto bene a ricordarmi della formattazione perché mi hai ricordato che manca una informazione che può essere utile.

Ho dimenticato di scrivere che la SD è da 256Mb. Ho però provato con SD da 2Gb ottenendo lo stesso risultato. E' però vero che non ho provato tutte le combinazioni possibili tra le prove che ho fatto.

Però il mio sospetto è di tipo software.

zoomx: Edit 2: ho scritto all'autore perché non c'è un modo chiaro per definire il pin per CS o SS. A me funziona perché la combinazione sarà giusta ma questo significa che se uso la Ethernet card non mi funzionerà.

Dal manualetto pdf accluso alla libreria: file.setSSpin(); da chiamare prima di file.initFAT()

E' vero, è l'ultima istruzione nel manualetto. Grazie nid69ita!!!

Devo riscrivergli e chiedere perdono!

Grazie ai chiarimenti di Lesto su Serial.flush() ne ho aggiunti un po' al test di scrittura

void SDwriteTest(){
  Serial.println(F("SD write test1"));
  Serial.flush();
  if (!card.init(SPI_HALF_SPEED, CHIPSELECT)) {
    Serial.println(F("SD init failed."));
    return;
  }
  Serial.println(F("opening"));
  Serial.flush();
  if (!MioFile.open("test.txt", O_WRITE | O_CREAT | O_APPEND)) {
    sd.errorHalt("Failed");
  }
  Serial.println(freeRam());
  Serial.flush();
  ciccio=MioFile.println(F("ProvaF"));
  Serial.println(ciccio, DEC);
  Serial.flush();
  MioFile.close();
  Serial.println(freeRam());
  Serial.println(F("done!"));
}

che mi stampa il seguente

SD write test1
opening
897
8
897
done!

dove 897 dovrebbe essere la RAM libera e 8 il numero dei byte scritti (http://arduino.cc/en/Reference/FilePrintln). Solo che il file viene creato ma continua ad essere desolatamente vuoto.

uhmmm... prova a modificare:

ciccio=MioFile.println(F("ProvaF"));

in

ciccio=MioFile.println("ProvaF");

comunque se togliendo qeulla libreria funziona, il problema o è la ram o è qualche cozzamento tipo timero o interrupt

edit: giusto per... prova con una MioFile.flush(); prima della close() :grin:

Si, ho fatto quella prova ed il risultato era il medesimo.

L'ho rifatta perché non si sa mai ed il risultato è che va in reset dopo la prima stampa di RAM libera, 891 per la cronaca.

SD write test1
opening
891
Setup

Setup viene stampato nella funzione omonima proprio per individuare eventuali reset.

Se uso la libreria tinyFAT invece sembra che il problema scompaia ma non riesco a capire perché la libreria standard mi dia questo problema. Si trattasse di una oscura libreria usata da solo 10 persone in tutto il mondo lo capirei ma questa è molto usata.... Anche il fatto che funzioni a metà è strano, il file viene creato per cui non si dovrebbe trattare di un problema di comunicazione. La memoria è fortemente sospettata ma quale errore può consumare 891 byte?

L'unica prova che non posso fare è di caricare lo sketch in un altro Arduino, magari questo ha problemi con la RAM, perché ne ho solo uno.

Per adesso andrò avanti cambiando libreria, poi cercherò di provare su un altro Arduino o magari sul Mega che sto aspettando.

E' arrivata la mega e ho fatto le prove: Libreria SD originale -> si inchioda subito dopo l'apertura del file, che quindi trovo vuoto ma non ho errore perché l'apertura mi restituisce 1, e mi va in reset. Non è un problema di memoria, stavolta i byte liberi sono oltre 6000. Libreria TinyFAT -> funziona ma manca delle utili funzioni della libreria originale come il trattamento delle stringhe.

se si inchioda subito a naso non hai attivato il giusto pin SS

Purtroppo no

#define CHIPSELECT 53  //MEGA!!!!

e nella funzione setup() ho

pinMode(CHIPSELECT, OUTPUT);
SD.begin(CHIPSELECT);

Ho ricontrollato perché non si sa mai. Per me rimane un mistero che però ho voglia di risolvere perché la libreria SD.h usa gli stream come la Serial.print per cui è più comoda. La TinyFAT curiosamente stampa solo con il Return e LineFeed obbligato per cui ho modificato la libreria per stampare senza il CR+LF.

Se ho novità le riporto qui.

puoi mettere un pò di Serial.print per capire dove si blocca la SD.h?