Array aus Sensordaten auf SD Karte schreiben und auslesen

Hi ich sitz seit mehreren Tagen vor Forumsbeiträgen und finde irgendwie nix was zu meinem Problem passt. :disappointed_relieved:

Ich Versuche zur Zeit ein Array aus Messungen eines Temperatursensor (Tmp 36 GZ) und eines Ultraschallsensor (HC-SR04 (4 Pins))
zu erstellen und in einer .Txt datei abzuspeichern. Dafür nutze ich weiter einen UNO und den CNT-002 von CNEWTEC(SD-Card Reader).

Das Ziel wäre später um die 10 Signale auf Karte zu speichern und bei Bedarf abzurufen (Stichwort Mapping) aber davon bin ich noch weit entfernt.

Ich habe schon so einiges Probiert. Vom einzeln die Variablem auf SD schreiben bis zum Versuch die Daten für den Moment der Messung in ein Array zu Packen und das dann in die txt. Datei zu speichern. Doch ohne Erfolg.

Einzeln die Daten (also nur Temp. Sensor) zu schreiben geht ohne Probleme, aber beide Sensoren gleichzeitig auf SD zu bannen klappt nicht( schreibt trotzdem nur den Temp wert in die Datei) und mit dem Array erscheinnen nur zusammenhängende Zahlen die aber nix mit der Seriellen Ausgabe gemein haben.

Hier mal mein Code…

//SD
#include<SD.h>
File myFile;
//ultraschallsensor
int pingPin = 7;
int inPin = 8;
float cm = 0;
//Temp.sensor
float Temp = 0;
//Array erstmal 5 Zeilen mit den 2 Daten der Sensoren
float Data[5][2] = {Temp, cm};
//________________________________________________________________________________________
void setup()    // Ausgabe über den Seriellen Monitor( Ist die Karte überhaupt vorhanden?)
{               
Serial.begin (9600);

Serial.print("warten auf SD Card...");
pinMode(10, OUTPUT);
if(SD.begin(4))
{
  Serial.println("Karte gefunden.\n");
}
if (!SD.begin(4))
{
Serial.println("Karte nicht gefunden!\r");
return;
}
}
//___________________________________________________________________________________________________________
void findTemps()  //Tempsensor Tmp36GZ mit dazu gehöriger °C Berechnung der Eingangswerte
{
float voltage = 0;
float sensor = 0;
sensor = analogRead(0);
voltage = (sensor * 5000)/1024;
voltage = voltage - 500;
Temp = voltage / 10;
Serial.print(Temp);
Serial.println(" deg.C\r");
}
//________________________________________________________________________________________
void findcm()    //Ultraschallsensor HC-SR04 (4 Pins) mit dazugehöriger Auswertung der Daten
{
float Dauer, cm;

pinMode(pingPin, OUTPUT);
digitalWrite(pingPin, LOW);
delayMicroseconds(2);
digitalWrite(pingPin, HIGH);
delayMicroseconds(10);
digitalWrite(pingPin, LOW);

pinMode(inPin, INPUT);
Dauer = pulseIn(inPin,HIGH);

cm = microsecondstoCentimeters(Dauer);
Serial.print(cm);
Serial.println("cm\r");
}
float microsecondstoCentimeters(float microseconds)
{
return microseconds /29 /2;
}
//________________________________________________________________________________________
void schreiben()
{
myFile = SD.open("Test.txt", FILE_WRITE);  //Schreibt in die Datei Test.txt, auf SD
if (myFile)
{
Serial.println("Schreibe in Test.txt...\n");
myFile.print(Data[5][2]);                  //Versuch das Array in die Datei zu bekommen
myFile.close();
Serial.println("Fertig\n");
}
}
//________________________________________________________________________________________
void loop()
{                          //Wiederholung der Schleifen nach definierter Zeit
findTemps();
findcm();
schreiben();
delay(10000);
}

Jetz die Frage(n). Versteh ich es nur nicht? Ist das ein problem der schnelligkeit des Schreibvorganges? Oder ist das so einfach nicht vorgesehen?

LG der Lexi…

Wenn ich das richtig sehe, wird das Array Data nur einmalig beschrieben. Und das ganz am Anfang des Sketches in Zeile 11.

Des weiteren glaube ich (aber auch nur weil ich nicht besser weiss), das das Array falsch definiert ist. Du brauchst hier gar kein zweidimensionales Array. Ein Eindimensionales reicht hier.

Sowas in der Art wie (habe nur die für das Array relevanten Teile drin ...)

float Data[2] = {0.0, 0.0} // Array initialisieren

void setup() {
[...]
}

void findTemps() {
float voltage = 0;
float sensor = 0;
sensor = analogRead(0);
voltage = (sensor * 5000)/1024;
voltage = voltage - 500;
Temp = voltage / 10;
Serial.print(Temp);
Serial.println(" deg.C\r");
Data[0] = Temp; // Den aktuellen Wert ins Array schreiben
}

void findcm() {
float Dauer, cm;

pinMode(pingPin, OUTPUT);
digitalWrite(pingPin, LOW);
delayMicroseconds(2);
digitalWrite(pingPin, HIGH);
delayMicroseconds(10);
digitalWrite(pingPin, LOW);

pinMode(inPin, INPUT);
Dauer = pulseIn(inPin,HIGH);

cm = microsecondstoCentimeters(Dauer);
Serial.print(cm);
Serial.println("cm\r");
Data[1] = cm; // Den aktuellen Wert ins Array schreiben
}

void schreiben() {
myFile = SD.open("Test.txt", FILE_WRITE);
if (myFile)
{
Serial.println("Schreibe in Test.txt...\n");
myFile.print(Temp);
myFile.print(" ");
myFile.println(cm);
myFile.close();
Serial.println("Fertig\n");
}

void loop()
{
findTemps(); // füllt Data[0]
findcm(); // füllt Data[1]
schreiben(); //schreibt Data[] auf SD
Data[] = {0.0, 0.0}; // array wieder nullen, um nicht bei einem sensorausfall den letzen wert immer wieder zu nutzen
delay(10000);
}

Happy hacking!

Lexi_ka:
Ich habe schon so einiges Probiert.

Und warum probierst Du es nicht mal mit “programmieren lernen”?
Allerdings könnte es länger als drei Nachmittage dauern.

Wenn Du nur so ein Array mit 2 Elementen hast:

float Data[2]

versuchs mal für eine zeilenweise Ausgabe in eine Textdatei mit:

myFile.print(Data[0]); // Erste Gleitkommazahl
myFile.print(';');             // Trennzeichen
myFile.print(Data[1]); // Zweite Gleitkommazahl
myFile.println();           // Zeilenende

Danke für die netten und Hilfreichen Tips. (vor allem Jurs)

Hab es jetzt so gemacht:

void schreiben()
{
  int Data[2]={Temp, cm};
myFile = SD.open("Test.txt", FILE_WRITE);  //Schreibt in die Datei Test.txt, auf SD
if (myFile)
{
Serial.println("Schreibe in Test.txt...\n");
Serial.print(Data[0]);
Serial.println(" deg.C\r");
Serial.print(Data[1]);
Serial.println("cm\r");
myFile.print(Data[0]); 
myFile.print(';');             
myFile.print(Data[1]); 
myFile.println();           
myFile.close();
}
}

Und es scheint zu funktionieren.

Also Danke nochmal...Ciaoi

Lexi_ka: Und es scheint zu funktionieren.

Wesentlich üblichere Trennzeichen als der Wagenrücklauf "\r" ("Return") zwischen zwei Datenfeldern innerhalb eines Datensatzes wäre allerdings das Tabulator-Steuerzeichen "\t" oder das Semikolon ";" oder ein Komma ",".

Nur mal so, falls Du die Daten später beispielsweise in eine Tabellenkalkulation wie OpenOffice Calc oder Windows Excel importieren möchtest zur weiteren Auswertung.

Oh guter Tip danke ;)

Lexi_ka: Oh guter Tip danke ;)

Ich sehe gerade, Du machst mitten im Datensatz sogar das:

Serial.println("cm\r");

Ein println() alleine macht schon "\r\n", und mit "println("\r") sendest Du "\r\r\n".

Bei üblichen Text-Datenformaten wie "CSV-Format" oder "Tab-Delimited" steht immer ein Datensatz in einer Zeile, getrennt durch ein Trennzeichen, z.B.:

100;200;555

Und ein Zeilenendezeichen kommt erst nach dem Datensatz.

Üblicherweise werden auch redundante Informationen mit "Masseinheit" nicht jedesmal mitgespeichert. Wenn, dann packt man diese in eine erste Zeile, z.B.

deg.C;cm
17.6;112
17.6;115
17.7;120

Oder

deg.C   cm
17.6    112
17.6    115
17.7    120

(Wobei sich hier ein einzelnes Tabulator-Trennzeichen \t zwischen den Feldern befindet)

Es ergibt sich dann immer so, dass der erste Wert in einer Zeile die Temperatur ist und der zweite Wert die Entfernung, wenn Du solche standardisierten Logdateien mit Trennzeichen erstellst, bei der immer die Felder eines Datensatzes in einer Zeile stehen.