[RISOLTO] Scrittura su SD salta bytes

Salve a tutti,
dopo aver perso ore ed ore a testare codice e a ricercare topics sul Forum, ovviamente senza successo, chiedo aiuto e chiarimenti.
Si tratta di un datalogger classico di dati GPS a 1 Hz. Il problema è che "ogni tanto" salta la scrittura di qualche carattere sulla memoria SD. Ecco un estratto del file. In nero la scrittura corretta, in blu quella memorizzata male.


123114.000,4530.7600,N,00903.6611,E,6.06,270614,g2,6,581,3470
123115.000,4530.7595,N,00903.6588,E,4.58,270614,g2,6,581,3470
123116.000,4530.7594,N,00903.6574,E,2.28,270614,g2,6,581,3470
123117.000,4530.7593,N,00903.6566,E,0.00,270614,g2,6,581,3470
123118.000,4530.7593,N,00903.6566,E,0.00,270614,g2,6,581,3470
3119.000,4530.7592,N,00903.6566,E,0.00,270614,g2,6,581,3470
123120.000,4530.7592,N,00903.6566,E,0.00,270614,g2,6,581,3470
123121.000,4530.7590,N,00903.6533,E,7.00,270614,g2,6,581,3470
123122.000,4530.7586,N,00903.6500,E,9.82,270614,g2,6,581,3470
123123.000,4530.7578,N,00903.6459,E,10.97,270614,g2,6,581,3470
123124.000,4530.7566,N,00903.6412,E,12.91,270614,g2,6,581,3470
...

23228.000,4530.6292,N,00902.5816,E,60.95,270614,g2,6,581,3470
23229.000,4530.6267,N,00902.5579,E,59.82,270614,g2,6,581,3470
3230.000,4530.6241,N,00902.5347,E,58.73,270614,g2,6,581,3470
3231.000,4530.6216,N,00902.5121,E,57.60,270614,g2,6,581,3470
3232.000,4530.6193,N,00902.4899,E,56.48,270614,g2,6,581,3470
3233.000,4530.6169,N,00902.4681,E,55.40,270614,g2,6,581,3470
3234.000,4530.6147,N,00902.4469,E,54.35,270614,g2,6,581,3470
3235.000,4530.6124,N,00902.4260,E,53.35,270614,g2,6,581,3470
...


Se reindirizzo l'output al monitor, non si verifica alcun problema.

Ho pensato che Arduino UNO avesse una velocità non adeguata e quindi ho provato ad utilizzare anche ChipKIT UNO 32, ma il comportamento è il medesimo.

Arduino UNO o CHIPKIT UNO 32
Shield SD con memoria 2GB
GPS seriale 9600 su Seriale1

Il codice seguente non produce l'output indicato sopra, ma di fatto genera il medesimo problema.

#include <SD.h>
#include <PString.h>


// On the Ethernet Shield, CS is pin 4. Note that even if it's not
// used as the CS pin, the hardware CS pin (10 on most Arduino boards,
// 53 on the Mega) must be left as an output or the SD library
// functions will not work.

// Default SD chip select for Uno and Mega type devices
const int chipSelect_SD_default = 10; // Change 10 to 53 for a Mega

// chipSelect_SD can be changed if you do not use default CS pin
const int chipSelect_SD = chipSelect_SD_default;


char buffer [200];
PString dataString (buffer,sizeof(buffer));

File dataFile;

void setup()
{
  Serial.begin(9600);
  Serial.print("Initializing SD card...");
  Serial1.begin(9600);

  // Make sure the default chip select pin is set to so that
  // shields that have a device that use the default CS pin
  // that are connected to the SPI bus do not hold drive bus
  
  pinMode(chipSelect_SD_default, OUTPUT);
  digitalWrite(chipSelect_SD_default, HIGH);

  pinMode(chipSelect_SD, OUTPUT);
  digitalWrite(chipSelect_SD, HIGH);


  // see if the card is present and can be initialized:
  if (!SD.begin(chipSelect_SD)) {
    Serial.println("Card failed, or not present");
    // don't do anything more:
    return;
  }
  Serial.println("card initialized.");
  
  dataFile = SD.open("datalog.txt", FILE_WRITE);
  if (!dataFile) {
    Serial.println("error opening datalog.txt");
    return;
  }
  dataFile.close();
    
  
}

void loop()
{
  
  // read from port 1, send to port 0:
  if (Serial1.available()) {
    
    int inByte = Serial1.read();
    Serial.print(char(inByte)); // echo su monitor dei caratteri che arrivano dalla seriale
    
    if (inByte!=10 && inByte!=13) {  //non memorizzare in dataString anche i caratteri di controllo
    
      
     
      dataString.print(char(inByte));
      
    
    
  } //if inbyte != 10, 13
  else // if inByte = 10, 13
  {
    
    if (inByte == 10) {
     
        dataFile = SD.open("datalog.txt", FILE_WRITE);
        if (!dataFile) {
          Serial.println("... File error");
          return;
        } 
        else
        {
          dataString.println();          // aggiungo alla stringa <CR> e <LF>
          dataFile.print(dataString);    // scrivo la stringa su SD
          Serial.println(" SD writing:... ");
          Serial.print(dataString);      // creo l'echo a monitor
          dataFile.close();              // assicurati che tutti i bytes siano stati scritti
          dataString.begin();            // resetta la stringa     
          Serial.println("  ... done!");
        } 
      
    } //if inByte = 10
  }
    
    
 } // if serial available
 
}

Qualche suggerimento?

Grazie!

Marco

Ti invitiamo a presentarti (dicci quali conoscenze hai di elettronica e di programmazione) qui: Presentazioni
e a leggere il regolamento: Regolamento

Ma da un certo momento sono tutte blu. Come dovrebbero essere le righe corrette?
Prima c'e' è possibile confrontarle con le nere, qui non si capisce come sarebbero i valori giusti.

Hello everyone,
after losing hours and hours to test code and search for topics on the Forum, obviously without success, I ask for help and clarification.
It is a traditional GPS data logger at 1 Hz. The problem is that "occasionally" skip writing some character on the memory card. Here's an excerpt of the file. In black writing correct, the blue one stored badly.

Hello everyone,
after losing hours and hours to test code and search for topics on the Forum, obviously without success, I ask for help and clarification.
It is a traditional GPS data logger at 1 Hz. The problem is that "occasionally" skip writing some character on the memory card. Here's an excerpt of the file. In black writing correct, the blue one stored badly.

http://forum.arduino.cc/index.php?topic=228549.0

Guardate questo post.
Assicurarsi di leggere il file README o si bruciano in tempo.

OK, vero, scusate... era talmente tanta la "disperazione" che per la fretta non ho osservato la netiquette dei forum...
Ho provveduto a presentarmi ... ed ho letto il regolamento.. giusta tiratina d'orecchi... me la merito tutta :stuck_out_tongue:
Ciao

nid69ita:
....
Ma da un certo momento sono tutte blu. Come dovrebbero essere le righe corrette?
Prima c'e' è possibile confrontarle con le nere, qui non si capisce come sarebbero i valori giusti.

Riportando i dati elaborati da un messaggio NMEA il formato è il medesimo. In nero come dovrebbe essere, in blu i bytes effettivamente scritti, in rosso quelli non scritti, mancanti che però sarebbero dovutio comparire.

123114.000,4530.7600,N,00903.6611,E,6.06,270614,g2,6,581,3470
123115.000,4530.7595,N,00903.6588,E,4.58,270614,g2,6,581,3470
123116.000,4530.7594,N,00903.6574,E,2.28,270614,g2,6,581,3470
123117.000,4530.7593,N,00903.6566,E,0.00,270614,g2,6,581,3470
123118.000,4530.7593,N,00903.6566,E,0.00,270614,g2,6,581,3470
123119.000,4530.7592,N,00903.6566,E,0.00,270614,g2,6,581,3470
123120.000,4530.7592,N,00903.6566,E,0.00,270614,g2,6,581,3470
123121.000,4530.7590,N,00903.6533,E,7.00,270614,g2,6,581,3470
123122.000,4530.7586,N,00903.6500,E,9.82,270614,g2,6,581,3470
123123.000,4530.7578,N,00903.6459,E,10.97,270614,g2,6,581,3470
123124.000,4530.7566,N,00903.6412,E,12.91,270614,g2,6,581,3470
...

123228.000,4530.6292,N,00902.5816,E,60.95,270614,g2,6,581,3470
123229.000,4530.6267,N,00902.5579,E,59.82,270614,g2,6,581,3470
123230.000,4530.6241,N,00902.5347,E,58.73,270614,g2,6,581,3470
123231.000,4530.6216,N,00902.5121,E,57.60,270614,g2,6,581,3470
123232.000,4530.6193,N,00902.4899,E,56.48,270614,g2,6,581,3470
123233.000,4530.6169,N,00902.4681,E,55.40,270614,g2,6,581,3470
123234.000,4530.6147,N,00902.4469,E,54.35,270614,g2,6,581,3470
123235.000,4530.6124,N,00902.4260,E,53.35,270614,g2,6,581,3470
...

Sembra quasi che nel trasferimento dei dati via SPI non si riesca a fare in tempo a scrivere dei bytes. Ma l'evento non è sistematico.

Hi Raschemmel, I had a look, it'll take some time to study. I'll do then reply and ask you for support if necessary.
Thank you
Bye

Take a look at this post about a guy writing a program to read CSV data from a power analyzer.
http://forum.arduino.cc/index.php?topic=262658.new;topicseen#new

The Power Analyzer link is in Reply#8 and an example of the received data is in Reply#11. The last post is a suggestion to save all the data in an array and then print it out but I don't know if that would work with a piece of equipment that is constantly sending data.

I have no problem about acquiring data from serial: GPS sends 1 Hz output data on serial port. Echoing on monitor there is no problem: all bytes are retrieved. Just when I write on SD card some bytes are missing. Now if we allow latency for 250ms and a data rate in writing of 300kb/s and I have to save in memory less than 100bytes per second, I have all the time! Nevertheless some bytes are missing. I'll try to buffer acquisition data and write it on SD card with a frequency of 0.2Hz.

Do you need to bring the CS LOW after you close the file ? (complete the write )

Veramente quello che stampi su Monitor Seriale è il singolo byte letto, mentre nella SD ci spari il testo messo nell'oggetto dataString di tipo PString. Quindi hai un passaggio in più di cui non siamo sicuri dell'esito.
Io intanto proverei a stampare su Serial Monitor la dataString prima di salvarla su SD.
Per essere sicuri che chi si perde i dati non sia quella libreria.

I don't know, I suppose (never verified) that library SD do it anyway. Must do it in code (scketch)? I'll Try.

nid69ita:
Veramente quello che stampi su Monitor Seriale è il singolo byte letto, mentre nella SD ci spari il testo messo nell'oggetto dataString di tipo PString. Quindi hai un passaggio in più di cui non siamo sicuri dell'esito.
Io intanto proverei a stampare su Serial Monitor la dataString prima di salvarla su SD.
Per essere sicuri che chi si perde i dati non sia quella libreria.

su serial monitor stampo sia il singolo byte sia la dataString e queste due risultano identiche!

          dataString.println();          // aggiungo alla stringa <CR> e <LF>
          dataFile.print(dataString);    // scrivo la stringa su SD
          Serial.println(" SD writing:... ");
          Serial.print(dataString);      // creo l'echo a monitor
          dataFile.close();              // assicurati che tutti i bytes siano stati scritti
          dataString.begin();            // resetta la stringa     
          Serial.println("  ... done!");

Ok, me l'ero perso quel pezzo. :smiley:

Non hai detto la cosa più importante.... questa sd dove si trova su uno sheld sd, su una ethernet, è originale?

Se non puoi risolvere il problema... AGGIRALO!
Prova a fare scrivere prima della stringa 3 o 4 tab.
Magari così non perdi dato utile nell'attesa che qualche genio non trova il modo di risolvere il problema.

Prova e fammi sapere se ti aiuta.

Ciao

Prova a mettere un leggero delay(20) dopo la scrittura su File, anzi subito dopo la close() del file.
Oppure invece della delay() usa la flush() dopo la scrittura.

La print() in generale ritorna anche il numero di byte scritti.
Prova a metterli in una variabile e verificare se corrispondono a quanti dovrebbe scriverne.

Poi, sei sicuro che la datafile.print() sia compatibile con la classe PString ?
Io scriverei direttamente buffer, tanto la PString scrive li sopra. Usi la classe per "stampare" in buffer e poi usi buffer per scrivere su file.

dataFile.print(buffer);  // al posto di dataFile.print(dataString);
  • Flush() l'ho già utilizzato ... ovviamente senza il risultato sperato
    il delay(20) lo provo subito
  • la Pstring può essere utilizzata come un qualsiasi char*. Il problema c'era anche prima quando non utilizzavo la libreria Pstring PString | Arduiniana

pablos:
Non hai detto la cosa più importante.... questa sd dove si trova su uno sheld sd, su una ethernet, è originale?

la SD si trova su uno shield itead

http://www.robot-italy.com/it/itead-stackable-sd-card-shield.html

hard_uino:
Se non puoi risolvere il problema... AGGIRALO!
Prova a fare scrivere prima della stringa 3 o 4 tab.
Magari così non perdi dato utile nell'attesa che qualche genio non trova il modo di risolvere il problema.

Prova e fammi sapere se ti aiuta.

Ciao

Sì l'ho già fatto: il numero massimo di caratteri che non mi scrive è inferiore alla decina... ma è decisamente inelegante. Siccome il file dovrà essere letto da terze parti e senza un parser, cercavo una soluzione definitiva al problema.
Grazie.
Ciao

Come dicevo la print() ti dice quanti caratteri ha scritto, la PString.length() ti dice il numero di caratteri,
prova a far verificare, quando salvi su file se i numeri coincidono. Non si sà mai...

Dal punto di vista HW, non è che puoi provare un'altra board SD ?
Quella board SD della Itead sei sicuro sia compatibile con i segnali 5V ?
(le stò pensando tutte !!! )