ich habe hier schon viele gute und hilfreiche Informationen gefunden, doch an dieser Stelle habe ich nun wirklich nichts passendes gefunden. Somit wollte ich einen neuen Beitrag eröffnen.
Meine Aufgabe ist einen Datenlogger zu entwickeln an dem unterschiedlich viele Sensoren angeschlossen werden können. Der Datenlogger besteht aus einem Arduino UNO einer SD Karte und einer RTC. Über eine Init Datei auf der SD Karte soll die Konfiguration bestimmt werden.
Die Init Datei könnte so aussehen:
NTC: 5;
MD: 3;
HMD: 2;
#include <SPI.h>
#include <SD.h>
File myFile;
char Init [100];
int i = 0;
void setup() {
// Open serial communications and wait for port to open:
Serial.begin(9600);
while (!Serial) {
; // wait for serial port to connect. Needed for native USB port only
}
Serial.print("Initializing SD card...");
if (!SD.begin(4)) {
Serial.println("initialization failed!");
while (1);
}
Serial.println("initialization done.");
// open the file. note that only one file can be open at a time,
// so you have to close this one before opening another.
myFile = SD.open("INI.txt");
if (myFile) {
Serial.println("INI.txt:");
// read from the file until there's nothing else in it:
while (myFile.available()) {
char ltr = myFile.read();
Init [i] += ltr;
i++;
//Serial.write(myFile.read());
}
i = 0;
// close the file:
myFile.close();
} else {
// if the file didn't open, print an error:
Serial.println("error opening test.txt");
}
Serial.println(Init);
}
void loop() {
// nothing happens after setup
}
Ich habe den Code geschrieben und er gibt mir als Ausgabe:
Das ist soweit richtig. Jetzt ist aber meine Frage, wie ich die 5, die 3 und die 2 als Integer Werte bekomme, sodass ich sie als Konfigurationsvariablen verwenden kann.
Die Zahlen können auch 2-stellig werden. Kann ich irgendwie nummerische werte in meinem char suchen? Habe da so Funktionen gefunden die aber schlecht für den RAM sind. Hat einer eine Idee für mein Problem.
#include <SPI.h>
#include <SD.h>
File myFile;
char Init [100];
int i = 0;
void setup() {
// Open serial communications and wait for port to open:
Serial.begin(9600);
while (!Serial) {
; // wait for serial port to connect. Needed for native USB port only
}
Serial.print("Initializing SD card...");
if (!SD.begin(4)) {
Serial.println("initialization failed!");
while (1);
}
Serial.println("initialization done.");
// open the file. note that only one file can be open at a time,
// so you have to close this one before opening another.
myFile = SD.open("INI.txt");
if (myFile) {
Serial.println("INI.txt:");
// read from the file until there's nothing else in it:
while (myFile.available()) {
char ltr = myFile.read();
Init [i] += ltr;
i++;
//Serial.write(myFile.read());
}
i = 0;
// close the file:
myFile.close();
} else {
// if the file didn't open, print an error:
Serial.println("error opening test.txt");
}
//Serial.println(Init);
int NTC = readBytesUntil(";", Init, 10);
//int NTC = atof(strtok(Init, ";"));
//int MD = atof(strtok(NULL, ";"));
Serial.println(NTC);
//Serial.println(MD);
//Serial.println(Init);
}
void loop() {
// nothing happens after setup
}
Was mach ich mit der readBytesUntil() Funktion falsch?
Weil Du Dich nicht damit beschäftigt hast, was ReadBytesUntil macht, sondern einfach irgendwas hinschreibst.
Es gibt viele Beispiele zu readBytesUntil mit Serial. Das Vorgehen ist das bei File das Gleiche. Es liest Zeichen in den Puffer Init. Beispiele wird Dir Google suchen.
Lass Dir Init per Serial.print anzeigen. Dann zerlege ihn am ':' (strtok) und wandle den 2. Teil in eine Zahl um (atoi). Einige Infos zur Zerlegung gibt es hier.
Ich kann die Zahlen einzeln schreiben aber wie finde ich raus ob gerade eine Zahl da ist? und wenn ja dann speicher sie mir in die Variablen NTC, MD und HMD.
Meine Annahme ist, dass die Textdatei in meinem Char drin ist.
Kann ich den Char nach nummerischen Werten durchsuchen?
if (ptr == numeric) geht leider nicht.
Tommys Vorschlag, den Firlefanz "NTC:" usw. zu ignorieren und
den 2. Teil per int ntc =atoi(ptr);
den 4. Teil per int md =atoi(ptr);
den 6. Teil per int hmd =atoi(ptr);
auszuwerten, ist am einfachsten.
Alternativ könntest du eingabe erstmal nach ';' aufteilen. Dann jedes Pärchen am ':' trennen, den ersten Teil per strcmp untersuchen und je nach Ergebnis den zweiten Teil der passenden Variablen zuweisen.
Aber da im Problemfall keiner zuschaut oder sinnvoll darauf reagieren könnte, ist einfach auch gut.
Oder steht zu befürchten, dass die Reihenfolge der Werte sich ändert?
Du machst übrigens einen schlechten Eindruck, wenn du von deinem Char schreibst, aber eigentlich ein char array oder ein char* ( in diesem Fall char eingabe[], bzw. char* ptr ) meinst.
michael_x:
Alternativ könntest du eingabe erstmal nach ';' aufteilen. Dann jedes Pärchen am ':' trennen, den ersten Teil per strcmp untersuchen und je nach Ergebnis den zweiten Teil der passenden Variablen zuweisen.
Das geht auch noch einfacher wenn jeder Wert in einer eigenen Zeile steht. strtok() ist dann gar nicht nötig:
char str1[] = "NTC: 5";
char str2[] = "MD: 3";
void setup()
{
Serial.begin(9600);
if (strncmp(str1, "NTC", 3) == 0)
{
int val = atoi(str1 + 4);
Serial.println(val);
}
if (strncmp(str2, "MD", 2) == 0)
{
int val = atoi(str2 + 3);
Serial.println(val);
}
}
void loop()
{
}
Die Länge des Anfangs ist bekannt. Wieso also irgendetwas splitten? Man vergleicht den Anfang in verwendet dann Zeiger-Arithmetik um den zu überspringen
Noch einfach geht es wenn man Kommandos und Identifizierer auf einen einzelnen Buchstaben reduziert. Dann kann man switch/case verwenden
Daher wird NTC zweimal überschrieben und ist zum Schluss auf dem Wert 2.
Außerdem ist % generell erheblich komplizierter als eine Abfrage wie (i == 2), wenn der Compiler das nicht schlauerweise als gerade/ungerade interpretiert und in Wirklichkeit ein (i & 1) draus macht.
Und du solltest klären, ob du mit i = 1 oder mit i = 0 anfangen willst.
Jetzt habe ich noch ein Problem welches ich mir nicht erklären kann.
Wenn ich das INIT char (char Init [130]) global deklariere läuft das Programm durch, wenn ich es wie im zweiten Code nur in der Funktion deklariere bekomme ich nur Mist als Ausgabe. Ich verwende den char aber nur in dem Unterprogramm.
Wo habe ich nen Denkfehler?
#include <SPI.h>
#include <SD.h>
File myFile;
int NTC, MD, HMD;
char Init [130];
void setup() {
// Open serial communications and wait for port to open:
Serial.begin(9600);
while (!Serial) {
; // wait for serial port to connect. Needed for native USB port only
}
Serial.print("Initializing SD card...");
if (!SD.begin(4)) {
Serial.println("initialization failed!");
while (1);
}
Serial.println("initialization done.");
fINI();
int _iaNTC[NTC];
int _iaMD[MD];
int _iaHMD[HMD];
for (int i = 0; i < NTC; i++)
_iaNTC[i] = analogRead(i);
for (int i = NTC; i < (NTC + MD); i++)
_iaMD[i] = analogRead(i);
for (int i = (NTC + MD); i < (NTC + MD + HMD); i++)
_iaHMD[i] = analogRead(i);
Serial.println("NTC");
for (int i = 0; i < NTC; i++)
Serial.println(_iaNTC[i]);
Serial.println("MD");
for (int i = NTC; i < (NTC + MD); i++)
Serial.println(_iaMD[i]);
Serial.println("HMD");
for (int i = (NTC + MD); i < (NTC + MD + HMD); i++)
Serial.println(_iaHMD[i]);
Serial.println("");
Serial.print("NTC = " );
Serial.println(NTC);
Serial.print("MD = " );
Serial.println(MD);
Serial.print("HMD = " );
Serial.println(HMD);
}
void loop() {
// nothing happens after setup
}
void fINI()
{
char trennzeichen[] = "=\n";
int i = 0;
int j = 1;
char *ptr;
// open the file. note that only one file can be open at a time,
// so you have to close this one before opening another.
myFile = SD.open("INI.txt");
if (myFile) {
Serial.println("INI.txt:");
// read from the file until there's nothing else in it:
while (myFile.available()) {
char ltr = myFile.read();
Init [i] += ltr;
i++;
}
i = 0;
ptr = strtok(Init, trennzeichen);
// solange was gefunden wurde
while (ptr != NULL) {
ptr = strtok(NULL, trennzeichen);
Serial.println(ptr);
Serial.print("j=");
Serial.println(j);
j++;
if (j == 11)
NTC = atoi(ptr);
if (j == 13)
MD = atoi(ptr);
if (j == 15)
HMD = atoi(ptr);
}
Serial.println(" ");
Serial.println(" ");
j = 0;
// close the file:
myFile.close();
} else {
// if the file didn't open, print an error:
Serial.println("error opening test.txt");
}
delay(1000);
}
#include <SPI.h>
#include <SD.h>
File myFile;
int NTC, MD, HMD;
void setup() {
// Open serial communications and wait for port to open:
Serial.begin(9600);
while (!Serial) {
; // wait for serial port to connect. Needed for native USB port only
}
Serial.print("Initializing SD card...");
if (!SD.begin(4)) {
Serial.println("initialization failed!");
while (1);
}
Serial.println("initialization done.");
fINI();
int _iaNTC[NTC];
int _iaMD[MD];
int _iaHMD[HMD];
for (int i = 0; i < NTC; i++)
_iaNTC[i] = analogRead(i);
for (int i = NTC; i < (NTC + MD); i++)
_iaMD[i] = analogRead(i);
for (int i = (NTC + MD); i < (NTC + MD + HMD); i++)
_iaHMD[i] = analogRead(i);
Serial.println("NTC");
for (int i = 0; i < NTC; i++)
Serial.println(_iaNTC[i]);
Serial.println("MD");
for (int i = NTC; i < (NTC + MD); i++)
Serial.println(_iaMD[i]);
Serial.println("HMD");
for (int i = (NTC + MD); i < (NTC + MD + HMD); i++)
Serial.println(_iaHMD[i]);
Serial.println("");
Serial.print("NTC = " );
Serial.println(NTC);
Serial.print("MD = " );
Serial.println(MD);
Serial.print("HMD = " );
Serial.println(HMD);
}
void loop() {
// nothing happens after setup
}
void fINI()
{
char trennzeichen[] = "=\n";
int i = 0;
int j = 1;
char Init [130];
char *ptr;
// open the file. note that only one file can be open at a time,
// so you have to close this one before opening another.
myFile = SD.open("INI.txt");
if (myFile) {
Serial.println("INI.txt:");
// read from the file until there's nothing else in it:
while (myFile.available()) {
char ltr = myFile.read();
Init [i] += ltr;
i++;
}
i = 0;
ptr = strtok(Init, trennzeichen);
// solange was gefunden wurde
while (ptr != NULL) {
ptr = strtok(NULL, trennzeichen);
Serial.println(ptr);
Serial.print("j=");
Serial.println(j);
j++;
if (j == 11)
NTC = atoi(ptr);
if (j == 13)
MD = atoi(ptr);
if (j == 15)
HMD = atoi(ptr);
}
Serial.println(" ");
Serial.println(" ");
j = 0;
// close the file:
myFile.close();
} else {
// if the file didn't open, print an error:
Serial.println("error opening test.txt");
}
delay(1000);
}
Ok Danke Thommy da habe ich noch nicht drüber nachgedacht, aber das macht auch Sinn und funktioniert genau so. UND jetzt kann ich mein Char unten deklarieren in meiner Funktion und es geht auch. Spart satt auch satt Speicher.
Das täuscht etwas. Die lokalen 130 byte werden beim Compilieren nicht mitgezählt, werden aber gebraucht, wenn der RAM sowieso am knappsten ist: Während die Datei geöffnet ist.
Wirklich hilft es nur, wenn du außerhalb von fIni() andere Funktionen hast, die ähnlich großen Bedarf an lokalen Variablen haben.
Wenn es geht, ist es gut.
Ansonsten wäre es sparsamer, nicht den ganzen Text der Datei erst zu lesen (kopieren) und dann die 3 int Variablen zu bestimmen. Leider müsste man dazu eine Alternative für strtok() finden/machen oder das Parsen ganz anders realisieren.
Ja das ganze ist ein wenig aufwendig mit dem kompletten einlesen nur um die 3 INI Werte auszulesen. Das ist mir auch schon aufgefallen.
Wie kann ich die Größe meines Array dynamisch machen? bei char Init[] kommt eine Fehlermeldung. Wenn ich den Bereich vergrößere (char Init[160]) bekomme ich in den leeren Speicherstellen immer irgendwelchen mit angezeigt beim Serial.print(Init).