GPS Daten auf SD Karte Speichern

Moin zusammen,
ich benutzte einen Arduino Uno, das SD Shield von ITead und ein GPS Modul von Sparkfun und ich möchte die GPS Daten in einer bestimmten Formation auf der SD Karte speichern. Bisher bekomme ich das so hin dass ich die Rohdaten auf der SD Karte speichern kann. Ich habe auch ein Programm in der mir nur die GPS im Serial Monitor angezeigt werden.
Code für das SD Shield:

#include <SD.h>

const int chipSelect = 10;

void setup()
{
  Serial.begin(9600);
   while (!Serial) {
    ;
  }


  Serial.print("Initializing SD card...");
  pinMode(10, OUTPUT);
  
  if (!SD.begin(chipSelect)) {
    Serial.println("Card failed, or not present");
    return;
  }
  Serial.println("card initialized.");
}

void loop()
{
  String dataString = "";

//Anzahl der Sensoren
for (int analogPin = 3; analogPin < 4; analogPin++) {
    int sensor = analogRead(analogPin);
    dataString += String(sensor);
    if (analogPin < 2) {
      dataString += ","; 
    }
  }

  // open the file. note that only one file can be open at a time,
  // so you have to close this one before opening another.
  File dataFile = SD.open("datalog.txt", FILE_WRITE);

  // if the file is available, write to it:
  if (dataFile) {
    dataFile.println(dataString);
    dataFile.close();
    // print to the serial port too:
    Serial.println(dataString);
  }  
  // if the file isn't open, pop up an error:
  else {
    Serial.println("error opening datalog.txt");
  } 
}
//ENDE

Das hier ist das Programm für das GPS Modul

#include <SoftwareSerial.h>

SoftwareSerial gpsSerial(3,2); // RX, TX (TX not used)
const int sentenceSize = 80;

char sentence[sentenceSize];

void setup()
{
  Serial.begin(9600);
  gpsSerial.begin(9600);
}

void loop()
{
  static int i = 0;
  if (gpsSerial.available())
  {
    char ch = gpsSerial.read();
    if (ch != '\n' && i < sentenceSize)
    {
      sentence[i] = ch;
      i++;
    }
    else
    {
      char ch = gpsSerial.read();
     sentence[i] = '\0';
     i = 0;
     displayGPS();
    }
  }
}

void displayGPS()
{
  char field[20];
  getField(field, 0);
  if (strcmp(field, "$GPRMC") == 0)
  {
    Serial.print("Lat: ");
    getField(field, 3);  // number
    Serial.print(field);
    getField(field, 4); // N/S
    Serial.print(field);
    
    Serial.print(" Long: ");
    getField(field, 5);  // number
    Serial.print(field);
    getField(field, 6);  // E/W
    Serial.println(field);
  }
}

void getField(char* buffer, int index)
{
  int sentencePos = 0;
  int fieldPos = 0;
  int commaCount = 0;
  while (sentencePos < sentenceSize)
  {
    if (sentence[sentencePos] == ',')
    {
      commaCount ++;
      sentencePos ++;
    }
    if (commaCount == index)
    {
      buffer[fieldPos] = sentence[sentencePos];
      fieldPos ++;
    }
    sentencePos ++;
  }
  buffer[fieldPos] = '\0';
} 
//ENDE

Ich weiß das ich irgendwie die Formatierung aus den GPS Modul

void displayGPS()
{
  char field[20];
  getField(field, 0);
  if (strcmp(field, "$GPRMC") == 0)
  {
    Serial.print("Lat: ");
    getField(field, 3);  // number
    Serial.print(field);
    getField(field, 4); // N/S
    Serial.print(field);
    
    Serial.print(" Long: ");
    getField(field, 5);  // number
    Serial.print(field);
    getField(field, 6);  // E/W
    Serial.println(field);
  }
}

in mein SD Programm einfügen muss aber alles was ich bisher versucht habe hat leider nicht funktioniert. Ich hoffe Ihr könnt mir helfen.
BlackDice

Und wo ist das Problem, ein

Serial.println(dataString);

durch ein

dataFile.println(dataString);

zu ersetzen?

Am Ende machst Du doch genau das Gleiche, nur das Du statt auf eine serielle Schnittstelle mittels print() und println() auf ein Datenfile mit den gleichen Funktionen / Methoden schreibst.

Poste doch mal den Code bei dem Du versucht hast die beiden Dinge (SD-Karte und GPS) zu verbinden. Da kann man einfachsten helfen die Dinge zu verbinden.
Mario.

Danke für die Hilfe, es hat sich herausgestellt das ich nur die Rohdaten brauche ohne irgendeine Formation. Das ist jetzt mein neuer Code:

#include <SD.h>
#include <SoftwareSerial.h>
#include <string.h>

SoftwareSerial gps(3,4);
const int sd = 10;

void setup()
{
  Serial.begin(9600);
  
  Serial.print("Initializing SD card...");
  pinMode(10, OUTPUT);
  
  if (!SD.begin(sd)) {
    Serial.println("Card failed, or not present");
    return;
  }
  Serial.println("card initialized.");
}

void loop()
{
  String dataString = "";

  gps.begin(9600);
 
  dataString += gps.read();
  
  Serial.print(dataString);

  // open the file. note that only one file can be open at a time,
  // so you have to close this one before opening another.
  File dataFile = SD.open("datalog.txt", FILE_WRITE);

  // if the file is available, write to it:
  if (dataFile) {
    dataFile.println(dataString);
    dataFile.close();
    // print to the serial port too:
    Serial.println(dataString);
  }  
  // if the file isn't open, pop up an error:
  else {
    Serial.println("error opening datalog.txt");
  } 
}
//ENDE

Problem hierbei ist das ich nur 4 stellige Zahlen ausgegeben und gespeichert werden. Normalerweise müsste sowas raus kommen: $GPRMC,081836,A,3751.65,S,14507.36,E,000.0,360.0,130998,011.3,E*62

BlackDice:
Problem hierbei ist das ich nur 4 stellige Zahlen ausgegeben und gespeichert werden. Normalerweise müsste sowas raus kommen: $GPRMC,081836,A,3751.65,S,14507.36,E,000.0,360.0,130998,011.3,E*62

Das ist doch das Rohdatenformat vom GPS-Modul?

Ist das jetzt so uneinsichtig, dass die Aufbereitung der Bildschirmausgabe in der Funktion "displayGPS()" erfolgt und dass, wenn Du einfach nur die unveränderten Rohdaten haben möchtest, einfach nur das char-Array "sentence" ausgeben müßtest?

Zum Testen der Ausgabe des GPS-Moduls zunächst mal auf dem Serial-Monitor.

Und wenn es da stimmt, dann in einem modifizierten Sketch mit Abspeicherung auf SD Karte, wie Du es haben möchtest.

Dein Problem ist folgendes:

void loop()
{
  String dataString = "";

  gps.begin(9600);
 
  dataString += gps.read();
  
  Serial.print(dataString);

  // open the file. note that only one file can be open at a time,
  // so you have to close this one before opening another.
  File dataFile = SD.open("datalog.txt", FILE_WRITE); 
  ...

dataString += gps.read(); liest genau ein Byte aus der seriellen Verbindung und baut daraus einen String. Diesen String (mit einem Zeichen) gibst Du mittels Serial.print(dataString) (ohne Zeilenumbruch) auf der seriellen Konsole aus. Danach gibst Du aber den selben String (mit immer noch einem Zeichen) per dataFile.println(dataString); (also MIT ZEILENUMBRUCH) auf der SD-Karte aus.
Danach beginnt loop() von vorn. Dabei schreibt dein Serial.print() in jedem loop-Durchlauf einen weiteren gelesenen Buchstaben in die gleiche Zeile, während das dataFile.println() jedesmal eine neue Zeile anfängt.

Es sind noch mehr Probleme da:

  1. gps.read() liefert keinen Buchstaben, sondern eine Zahl ( int ) , die den Wert -1 hat, wenn keine Daten zu lesen sind. Dein erster Ansatz mit gps.available() war deutlich besser.

  2. Auf eine SD Karte wird immer ein ganzer Block ( 512 Byte ) geschrieben, auch wenn nur ein oder zwei Byte dazugekommen sind. Nach 100.000 mal schreiben kann man damit rechnen, dass der betreffende SD Block hinüber ist.
    Du solltest besser einen ganzen Datensatz sammeln und am Stück schreiben.

char c;
dataString += c; // sieht nur einfach aus, in Wirklichkeit bleibt dabei der vorige Inhalt von dataString als Leiche übrig ...

Dein erster Ansatz mit char sentence[80] war deutlich besser.