Array von SD Karte beschreiben

Hi@all,
ich will mein Array " rfid_[Ids] " erstellen und dieses mit den Daten meiner SD Karte laden.

nur habe ich ein Problem " es geht nicht " und ich weiß nicht weiter wo der Fehler ist. Siehe Monitor

Meine Monitor Ausgabe:

next SD_Tag 8482107
 
SD Tag_Id= 8482107
Ids= 1
rfid_= 8482107
AAA???
8482107


BBB???

next SD_Tag 14255441
 
SD Tag_Id= 14255441
Ids= 2
rfid_= 14255441
AAA???
14255441
14255441

BBB???

next SD_Tag 40310531
 
SD Tag_Id= 4031053
Ids= 3
rfid_= 4031053
AAA???
4031053
4031053
4031053
BBB???

next SD_Tag 15260068
 
SD Tag_Id= 15260068
Ids= 4
rfid_= 15260068
AAA???
15260068
15260068
15260068
BBB???

next SD_Tag 64787028
 
SD Tag_Id= 6478702
Ids= 5
rfid_= 6478702
AAA???
6478702
6478702
6478702
BBB???

next SD_Tag 8419762
 
SD Tag_Id= 8419762
Ids= 6
rfid_= 8419762
AAA???
8419762
8419762
8419762
BBB???
eof:   SD Tag_Id= end
Ids= 7
rfid_= end
AAA???
end
end
end
BBB???

setup complet
CCC???

DDD???

rfid_=   Ids= 1

rfid_=   Ids= 2

rfid_=   Ids= 3

...

Mein Code:

// Function to read a text file one field at a time.
//
#include <SPI.h>
#include <SD.h>
#define CS_PIN 17

/*
 * Lesen Sie eine Datei Feldweise.
 * 
 * File - Zu lesende Datei.
 *
 * str - Zeichenarray für das Feld.
 *
 * size - Größe des str-Arrays.
 *
 * delim - Zeichenfolge mit Feldtrennzeichen.
 *
 * return - Länge des Feldes einschließlich des abschließenden Trennzeichens.
 *
 * Beachten Sie, dass das letzte Zeichen von str kein Trennzeichen ist, wenn
 * Ein Lesefehler tritt auf, das Feld ist zu lang oder die Datei
 * endet nicht mit einem Trennzeichen. Betrachten Sie dies als Fehler
 * wenn nicht am Ende der Datei.
 *
 */
  File file;
  char* rfid_[100];
  int Ids=0;
  bool firstcycle=true;
 
size_t readField(File* file, char* str, size_t size, char* delim) {
  char ch;
  String SD_Tag;
  
  size_t n = 0;
  while ((n + 1) < size && file->read(&ch, 1) == 1) {
    // Delete CR.
    if (ch == '\r') {

      SD_Tag = str;
      Serial.print("\nnext SD_Tag ");
      Serial.println( SD_Tag);
      Serial.println (" ");
      
      continue;
    }
    str[n++] = ch;
    if (strchr(delim, ch)) {
        break;
    }
  }
  str[n] = '\0';
  return n;

}


//------------------------------------------------------------------------------
#define errorHalt(msg) {Serial.println(F(msg)); while(1);}
//------------------------------------------------------------------------------
void setup() {
  Serial.begin(115200);

  // Initialize the SD.
  if (!SD.begin(CS_PIN)) errorHalt("begin failed");

  // Create or open the file.
  file = SD.open("DG.TXT", FILE_READ);
  if (!file) errorHalt("open failed");

  // Rewind the file for read.
  file.seek(0);

  size_t n;      // Length of returned field with delimiter.
  char str[11];  // Must hold longest field with delimiter and zero byte.
  
  // Read the file and print fields.
  while (true) {
    n = readField(&file, str, sizeof(str), ",\n");
   Ids=Ids+1;
 
    // done if Error or at EOF.
    if (n == 0) break;

    // Print the type of delimiter.
    if (str[n-1] == ',' || str[n-1] == '\n') {
     // Serial.print(str[n-1] == ',' ? F("comma: ") : F("endl:  "));
      
      // Remove the delimiter.
      str[n-1] = 0;
    } else {
      // At eof, too long, or read error.  Too long is error.
      Serial.print(file.available() ? F("error: ") : F("eof:   "));
    }
    // Print the field.

    rfid_[Ids]=str ;   
    Serial.print( "SD Tag_Id= ");
    Serial.println(str);
   
    Serial.print( "Ids= ");
    Serial.println(Ids);   

    Serial.print( "rfid_= ");
    Serial.println(rfid_[Ids]);   

    Serial.println( "AAA???");
    Serial.println(rfid_[1]);
    Serial.println(rfid_[2]);
    Serial.println(rfid_[3]);
    Serial.println( "BBB???");

  
  }
  file.close();
  Serial.print( "\nsetup complet\n");

  Serial.println( "CCC???");
  Serial.println(rfid_[1]);
  Serial.println(rfid_[2]);
  Serial.println( "DDD???");
 
  
}
   
//------------------------------------------------------------------------------
void loop() {
  
  if (firstcycle== true ) { 

      Ids=1;
      firstcycle = false;
  } 
  
  if ((Ids>=0)&&(Ids<=100)) {
  
     Serial.print("\nrfid_= ");
     Serial.print(rfid_[Ids]);   
     Serial.print( "  Ids= ");
     Serial.println( Ids);
     
     Ids=Ids+1;

            return;

  }

     Serial.println("end" );
     delay (60000);
}

Ups vergessen siehe Anlage für die Datei

vielleicht kann mir einer Sagen wo der Fehler ist.

Ich will auch nur wissen warum die Felder wieder geleert werden.

Danke im Vor raus
Frank

DG.TXT (45 Bytes)

Dazu solltest Du uns erst mal mitteilen, wie Deine RFID aussehen und wie diese auf der SD vorliegen.
Weiterhin wie Du Dein Array definiert hast.

Gruß Tommy

Ups Sorry,
habe meinen Start geändert

Wenn Du das nicht als Anhang, sondern als Text in Codetags anhängst, können das auch Leute mit mobilen Geräten den Text besser sehen.

Willst Du den RFID-Code als Zahl oder als Zeichenkette im Array eintragen?

Gruß Tommy

Hi Tommy,
char* rfid_[100];

also Zeichenkette

mfg
Frank

char* rfid_[100]; Sind hundert Zeiger, die irgendwohin zeigen, wo der erwartete Text wieder verschwindet.
Du könntest den Text komplett von SD lesen, dir jeweils den Anfang eines Textes in rfid_ merken und das jeweilige Ende durch eine '\0' statt des delimiters markieren. Oder es anders machen.
Die Texte müssen wohl hinterher alle permanent im RAM sein, denke ich mal. Wenn das insgesamt weniger als 100 Zeichen sind, und die in rfid_[100] stehen sollen, ist dieses Array falsch definiert. (Jedenfalls anders als du denkst).

Wo ist der Speicher für die Texte?

Gruß Tommy

Ich wollte bis zu 100 RFiD Tag's die mit bis zu 10 Zeichen in der DG.TXT stehen einlesen.
Diese Tag's sollen Permanent sein und beim Neustart auch neu eingelesen werden.

Das meiste geht auch! ,aber...
Im Monitor sieht man das es am Anfang geht und auch eingetragen wird. aber in jedem durchlauf überschrieben wird.
Im loop ist dann nichts mehr da.

mfg
Frank

Du hast keinen Speicher reserviert.

const byte laenge = 11;  // 10+'\0'
const byte anzahl = 100;

char rfidArray[anzahl][laenge];

Damit hast Du erst mal Speicher für Deine Daten.

Gruß Tommy

Tommy56:

char rfidArray[anzahl][laenge];

Das sind allerdings 1100 Zeichen. “Normale Arduinos” (Uno/Nano) können dazu nicht noch per SD library Dateien lesen, weil dafür nochmal >1024 byte RAM erforderlich sind.

Wenn dieser Einwand zutrifft, begrenze anzahl mal auf 10,
da du evtl. denkst, du hättest mit char* rfid_[100] Platz für hundert Zeichen reserviert
(was wohl dein erster Verständnis-Irrtum ist)

hi @all

@Michael_x:
ich gebe es ungerne zu aber ich glaube du hast den Nagel auf den Kopf getroffen. :confused:

Normalerweise Programmiere ich Siemens SPS-Steuerungen und da ist das mit den Array' s ganz anders :o

Aber ich werde es mit den Neuen Erkenntnissen weiter versuchen.

mfg
Frank

Hitschkock:
ich gebe es ungerne zu aber ich glaube du hast den Nagel auf den Kopf getroffen.

Alternativ kannst Du versuchen mit FRAM(spi) zu arbeiten.
Den Inhalt der Karte im setup() oder bei Feststellung, das die Karte getauscht wurde, da (einmalig) rein kopieren und von dort lesen.

char* und char sind eben zwei ganz verschiedene Datentypen, und eine SPS wird normalerweise nicht in C/C++ programmiert. Du bist übrigens nicht allein mit diesem Problem, dass man sich ohne C-Grundkenntnisse gerne verirrt.

Wenn man bedenkt, dass ein Arduino nicht für Textverarbeitungs-Aufgaben optimiert ist, ist eher erstaunlich, was man mit 2 kB RAM alles hinkriegen kann, wenn man will und sich auf die Grenzen einlässt.

100 Zeichen für 10 Tag-ID's ist ja schonmal was. Dann sieht es so aus, als könnte man jede deiner ID ("14255441") locker binär in 4 byte packen, Dann hättest du in 100 Byte schon Platz für 25.

Und so für kleine und relativ statische Datenmengen bietet sich statt SD-Karte auch der EPROM-Bereich an. Da ist der Overhead zum Lesen/Schreiben deutlich kleiner.

Warum willst du die Daten im RAM halten?

Belasse sie auf der SD und lies wenn du es brauchst:

Wenn du einen Tag gelesen hast, öffnest du die Datei, liest die Datei zeilenweise ein - du findest den Tag oder nicht. Schließe die Datei.

Dann können auch 4711 Tags in der Datei sein.

Hi @all,

Danke für das große feedback. :slight_smile:

@ michael_x jetzt geht mein Array! war ganz anders wie gedacht.

@ noiasca da ich jetzt Speicherprobleme habe muss ich wohl mal über deine Idee nachdenken.

Aktuell kann ich nur 12 Karten verwalten, das ist zu wenig!!

Vielleicht hat jemand eine Idee wie ich sonst noch Speicher sparen könnte.

ich will “” long arfid_[12]; // SD Karten Array “” auf 100 hoch bekommen

mfg
Frank

DG_RM6300_LCD_SD.ino (11.1 KB)

Vielleicht hat jemand eine Idee wie ich sonst noch Speicher sparen könnte.

zwei weitere sogar.

a)
lies mal hier:
https://www.arduino.cc/reference/de/language/variables/utilities/progmem/

Das heißt, alle Fix-Texte im Flash belassen und nicht in den RAM kopieren.

Serial.print( "SD in char Tag_Id= ");

zu

Serial.print(F("SD in char Tag_Id= "));

b) prüfe deine Datentypen! Es gibt so viel mehr als int. Jedes int überprüfen ob du wirklich 2 byte brauchst oder ob du vieleicht auch mit einem byte/char/int8_t/uint8_t auskommst!(!!!)

nur auszugsweise... werden diese zahlen jemals größer als 128/ oder 256?
wenn nicht, ändere d

int      spare = 2;                       
int        red = 3;                       
int      green = 4;
int       Lock = 5;
int  BackLight = 6;

c) nur der Vollständigkeit wegen, gem. #13

löse das

long arfid_[12]; // SD Karten Array

auf, und lies deine Datei wenn du eine Karte gelesen hast ob diese in der Datei ist.
mach dir eine Funktion mit deinem Datei-Zugriff, übergib per Parameter die gelesene Karten-ID und lass dir von der Funktion ein true/false zurück geben ob diese in der Datei steht.

Moin moin noiasca,

das Serial.Print(F( “test”)) oder lcd.Print(F( “test”)) ist meine Hauptlösung!

Das mit dem PROGMEM hat so nichts gebracht.

long arfid_[13];  // SD Karten Array

Der Sketch verwendet 16392 Bytes (53%) des Programmspeicherplatzes. 
Das Maximum sind 30720 Bytes.
Globale Variablen verwenden 1750 Bytes (85%) des dynamischen Speichers, 
298 Bytes für lokale Variablen verbleiben. Das Maximum sind 2048 Bytes.

---mit----  Serial.println(F(" abc "));
Der Sketch verwendet 16360 Bytes (53%) des Programmspeicherplatzes. 
Globale Variablen verwenden 1172 Bytes (57%) des dynamischen Speichers, 
876 Bytes für lokale Variablen verbleiben.
----mit-----  lcd.print(F("  abc  "));
Der Sketch verwendet 16442 Bytes (53%) des Programmspeicherplatzes.
Globale Variablen verwenden 1098 Bytes (53%) des dynamischen Speichers, 
950 Bytes für lokale Variablen verbleiben.


long arfid_[50];  // SD Karten Array
Der Sketch verwendet 16442 Bytes (53%) des Programmspeicherplatzes. 
Globale Variablen verwenden 1246 Bytes (60%) des dynamischen Speichers, 
802 Bytes für lokale Variablen verbleiben.

long arfid_[100];  // SD Karten Array
Der Sketch verwendet 16444 Bytes (53%) des Programmspeicherplatzes.
Globale Variablen verwenden 1446 Bytes (70%) des dynamischen Speichers, 
602 Bytes für lokale Variablen verbleiben. 

long arfid_[120];  // SD Karten Array
Der Sketch verwendet 16444 Bytes (53%) des Programmspeicherplatzes.
Globale Variablen verwenden 1526 Bytes (74%) des dynamischen Speichers, 
522 Bytes für lokale Variablen verbleiben.

long arfid_[150];  // SD Karten Array
Der Sketch verwendet 16444 Bytes (53%) des Programmspeicherplatzes.
Globale Variablen verwenden 1646 Bytes (80%) des dynamischen Speichers, 
402 Bytes für lokale Variablen verbleiben.
Wenig Arbeitsspeicher verfügbar, es können Stabilitätsprobleme auftreten.

mehr Tag’s (125) brauche ich nicht :slight_smile:

Danke Danke Danke!!

mfg
Frank

Hitschkock:
das Serial.Print(F( "test")) oder lcd.Print(F( "test")) ist meine Hauptlösung!

long arfid_[120];  // SD Karten Array

Der Sketch verwendet 16444 Bytes (53%) des Programmspeicherplatzes.
Globale Variablen verwenden 1526 Bytes (74%) des dynamischen Speichers,
522 Bytes für lokale Variablen verbleiben.

Sag mal bitte unter welcher IDE-Version. das es für einen UNO ist, ist klar, aber je nach Version bekomme ich hier Eigenartiges....

Hi My_xy_projekt,

Ich habe einen Nano keinen Uno!
IDE 1.8.13

mfg
Frank

Das ist der gleiche Prozessor und der gliche RAM.

Gruß Tommy