Go Down

Topic: SD TXT Dateien einlesen (Read 1 time) previous topic - next topic

Lan-Police

Hallo,

also ich suche nach einer möglichkeit 8 TXT Dateien (z.b. raum1.txt) nacheinander

Inhalt der raum1.txt:

Code: [Select]
wohnzimmer,20.00,0x0000
oder
wohnzimmer;20.00;0x0000


die Kommagetrennen Wert in einzelne Variabeln zu übergeben sollbald der Arduino startet.

Hab schon div. Sketch beispiele getestet aber nix funktioniert wirklich  :(

Vllt. hat ja jemand was passendes oder ne Idee ?


jurs


Vllt. hat ja jemand was passendes oder ne Idee ?


Sollen aus 8 verschiedenen Dateien je nur eine Zeile ausgelesen werden?
Warum nicht eine Datei und aus einer Datei werden 8 Zeilen ausgelesen?

Für welche SD-Library soll es denn was werden?

Und in was für Datenstrukturen sollen die Daten rein?
Willst Du die eingelesenen Variablen als Strings wegspeichern (char-Array? verkettete Liste?)?
Oder sollen die Variablen noch wenigstens teilweise umgewandelt werden? Union? Struct? Getrennte Arrays?

Die Variablen sollen aber schon alle miteinander gleichzeitig in den RAM-Speicher eingelesen werden?
Oder sollen sie vielleicht während des Einesens verarbeitet werden und Aktionen anstoßen?

Lan-Police

Hey,

erstmal danke für die schnelle antwort :)

Ich bitte um etwas "mitleid" für mich als Anfänger  :D

Ich möchste so einfach die möglich die Werte einlesen, aus einer Datei wäre auch gut.

Die Raumnamen sollen im gesamten Sketch als char* sowie der Zahlenwert (Raumtemp) als float
und der zweite Zahlenwert als Int. oder so (das is ne Hex  Adresse von einem Wire Temp. Sensor).

Die wahl der SD Lib ist noch offen was dafür halt am besten passen würde ?

Gruß
Jens

jurs


Die wahl der SD Lib ist noch offen was dafür halt am besten passen würde ?


Kommt ja drauf an, was Du brauchst und was in den RAM-Speicher Deines Controllers reinpasst.

Ich habe Dir mal ein Beispiel für die SdFat-Library gemacht, das ist eher ein grosses und umfangreiches Teil und stellt das obere Ende dessen dar, was an SD-Kartenunterstützung für Arduino machbar ist.

Als SD-Karte habe ich mal eine vom Ethernet-Shield genommen (chipSelect = 4).

Die "Raumwerte" werden dabei aus einer einzigen Datei gelesen, die dafür dann bis zu 8 Zeilen haben müßte. Im Setup werden globale Variablen mit den eingelesenen Werten besetzt (und einmal über Serial ausgegeben), die dann im Rest des Programms verwendet werden könnten.

Vielleicht hilft's, ein paar Kommentare stehen dran.

Code: [Select]


#include <SdFat.h>

// SD chip select pin
const uint8_t chipSelect = 4; // Ethernet shield

// file system object
SdFat sd;

//------------------------------------------------------------------------------

#define ZIMMERZAHL 8
char zimmerName[ZIMMERZAHL][21]; // 20 chars + \0
float zimmerFloat[ZIMMERZAHL];
long zimmerLong[ZIMMERZAHL];

void readFileToVars(char* fn)
// reads a file from SD card, max ZIMMERZAHL lines in the form
// wohnzimmer,20.00,0x0000
// wohnzimmer;20.00;0x0000
{
  byte zimmerNum;
  byte i,var;
  char c;
  char temp[10]; // max length of temporary strings is 9+'\0'
  zimmerNum=0;
  ifstream file(fn);
  if (!file.is_open()) sd.errorHalt("open failed");
  memset(zimmerName[zimmerNum],0,21); // clear zimmerName
  i=0;var=1;
  while ((c = file.get()) >= 0)
  {
    switch (c) {
    case '\r': break; // CR do nothing
    case ',':  // field seperator
    case ';': // field seperator
    case '\n': //  LF starts new line for another room, also field seperator
      {
        // if we read the second variable, it's the temp
        if (var==2) zimmerFloat[zimmerNum]=atof(temp);
        // if we read the third variable, it's the hex number
        if (var==3)
        {
          zimmerLong[zimmerNum]=strtol(temp,NULL,0);
        }
        var++;
        i=0;
        memset(temp,0,sizeof(temp));
        if (c=='\n') // special treatment for new line
        {
          zimmerNum++; // increase zimmerNum
          i=0;var=1;
          if (zimmerNum==ZIMMERZAHL) goto the_end; // no more variables available
        }
        break;
      } 
    default: // normal characters, except seperators, with ASCII code 32 or above
      if ((c>=32)&&(var==1)) // insert first variable into zimmerName
      {
        zimmerName[zimmerNum][i]=c;
        i++;
      } 
      else if ((c>=32)&&((var==2)||(var==3)))// insert other variables to temporary char arrray
      {
        temp[i]=c;
        i++;
      } 
    } 
  }
the_end: 
  file.close();
}

//------------------------------------------------------------------------------

void setup() {
  Serial.begin(9600);
  Serial.println("Start");
  while (!Serial) {}  // wait for Leonardo

  // initialize the SD card at SPI_HALF_SPEED to avoid bus errors with
  // breadboards.  use SPI_FULL_SPEED for better performance.
  if (!sd.begin(chipSelect, SPI_HALF_SPEED)) sd.initErrorHalt();

  readFileToVars("RAUM.TXT");
  for (int i=0;i<ZIMMERZAHL;i++)
  {
    Serial.println(zimmerName[i]);
    Serial.println(zimmerFloat[i]);
    Serial.println(zimmerLong[i]);
    Serial.println();
  } 
}

//------------------------------------------------------------------------------

void loop()
{
}

//------------------------------------------------------------------------------







Lan-Police

Hallu jurs,

ich hab den Code:

Code: [Select]



#include <SdFat.h>


// SD chip select pin
const uint8_t chipSelect = 4; // Ethernet shield

// file system object
SdFat sd;

//------------------------------------------------------------------------------

#define ZIMMERZAHL 5
char zimmerName[ZIMMERZAHL][21]; // 20 chars + \0
float zimmerFloat[ZIMMERZAHL];
long zimmerLong[ZIMMERZAHL];

void readFileToVars(char* fn)
// reads a file from SD card, max ZIMMERZAHL lines in the form
// wohnzimmer,20.00,0x0000
{
  byte zimmerNum;
  byte i,var;
  char c;
  char temp[10]; // max length of temporary strings is 9+'\0'
  zimmerNum=0;
  ifstream file(fn);
  if (!file.is_open()) sd.errorHalt("open failed");
  memset(zimmerName[zimmerNum],0,21); // clear zimmerName
  i=0;var=1;
  while ((c = file.get()) >= 0)
  {
    switch (c) {
    case '\r': break; // CR do nothing
    case ',':  // field seperator
    case ';': // field seperator
    case '\n': //  LF starts new line for another room, also field seperator
      {
        // if we read the second variable, it's the temp
        if (var==2) zimmerFloat[zimmerNum]=atof(temp);
        // if we read the third variable, it's the hex number
        if (var==3)
        {
          zimmerLong[zimmerNum]=strtol(temp,NULL,0);
        }
        var++;
        i=0;
        memset(temp,0,sizeof(temp));
        if (c=='\n') // special treatment for new line
        {
          zimmerNum++; // increase zimmerNum
          i=0;var=1;
          if (zimmerNum==ZIMMERZAHL) goto the_end; // no more variables available
        }
        break;
      } 
    default: // normal characters, except seperators, with ASCII code 32 or above
      if ((c>=32)&&(var==1)) // insert first variable into zimmerName
      {
        zimmerName[zimmerNum][i]=c;
        i++;
      } 
      else if ((c>=32)&&((var==2)||(var==3)))// insert other variables to temporary char arrray
      {
        temp[i]=c;
        i++;
      } 
    } 
  }
the_end: 
  file.close();
}

//------------------------------------------------------------------------------

void setup() {
  Serial.begin(9600);
  Serial.println("Start");
  while (!Serial) {}  // wait for Leonardo

  // initialize the SD card at SPI_HALF_SPEED to avoid bus errors with
  // breadboards.  use SPI_FULL_SPEED for better performance.
  if (!sd.begin(chipSelect, SPI_HALF_SPEED)) sd.initErrorHalt();

  readFileToVars("raum.txt");
  for (int i=0;i<ZIMMERZAHL;i++)
  {
    Serial.println(zimmerName[i]);
    Serial.println(zimmerFloat[i]);
    Serial.println(zimmerLong[i]);
    Serial.println();
  } 
}

//------------------------------------------------------------------------------

void loop()
{
}

//------------------------------------------------------------------------------



mal mit 5 Räumen auf dem UNO Board getestet. Die Raumnamen und Temp. liest er sauber aus nur bei den Sensoradressen (egal ob als Hex oder Dez.) gibst probleme ... siehe Serial Output:

Code: [Select]
Start
wohnzimmer
10.00
46969

schlafzimmer
11.00
30492

buero
12.00
0

treppenhaus
13.00
41981

garage
14.00
0



Das ganze wird aber noch auf ein Mega Board verschoben .... just 4 info

Gruß
Jens

rz259

Wenn du keine weiteren Infos hast, dann wird dir hier auch keiner helfen können. Was stimmt denn genau nicht? Ich sehe im Serial Output erst mal keinen Fehler.

Rudi


jurs


mal mit 5 Räumen auf dem UNO Board getestet. Die Raumnamen und Temp. liest er sauber aus nur bei den Sensoradressen (egal ob als Hex oder Dez.) gibst probleme ... siehe Serial Output:


Deine Probleme kann ich nicht nachvollziehen. Der von mir gepostete Code liest Raumnamen, Float-Temperaturen und Sensoradressen exakt nach Deinem vorgegebenen Muster (String, Fliesskommazahl, Ganzzahl) aus, und zwar bei der Ganzzahl egal ob sie als Hex oder Dez Zahl angegeben wurde.

Vom Beispielprogramm ausgegeben werden die Adressen allerdings jeweils als Dezimalzahl, auch wenn sie in der Datei als Hex angegeben wurden. Wenn Du die Zahl sowohl in Hex als auch Dez Notation ausgeben möchtest, nimm beispielsweise:
Code: [Select]

    Serial.print("Hex: ");Serial.println(zimmerLong[i],HEX);
    Serial.print("Dez: ");Serial.println(zimmerLong[i]);


Einzige Klippe ist das Dateiende: Mein Code funktioniert für das letzte Feld in der letzten Zeile der Datei (also die Sensoradresse des letzten Raumes) nur dann, wenn die Zeile mit einem Linefeed-Steuerzeichen abgeschlossen ist. Mein Code funktioniert für die letzte Sensoradresse nicht, wenn die letzte Zeile mit Raumangaben ohne Linefeed-Steuerzeichen endet.

Also entweder beendest Du die Datei so, dass am Ende der letzten Zeile noch mindestens ein Trennzeichen oder ein Linefeed-Steuerzeichen folgt. Oder Du schreibst den Code so um, dass das letzte Feld in der letzten Zeile auch ohne Trennzeichen (Komma, Semikolon, Linefeed-Steuerzeichen) ausgewertet wird, einfach nur wenn die Datei nach der letzten Zeile ohne Zeilenende-Steuerzeichen zuende ist.

Wenn Du sowohl mit der Dateierstellung Probleme hast, hinter die letzte Zeile ein Linefeed-Steuerzeichen ans Ende der Datei zu bekommen, als auch mit dem Umschreiben des Codes Probleme hast, kannst Du auch einfach ein normales Trennzeichen ans Zeilenende setzen, wenigstens in der letzten Zeile der Datei, z.B. in der Form
kinderzimmer;22.59;0x4711;


Lan-Police

Hallo Jurs,

vielen Dank für deine Mühe, das mit dem Trennzeichen war genau der Fehler. Ich werde das ganze mal die nächsten Tage auf dem Mega Board testen und nochmal Rückmeldung geben.

Nochmals Danke !  ;)

Gruß
Jens

Go Up