Arduino-Dateinamen innerhalb des Sketches verfügbar ?

Hallo, da ich während der Erstellung von größeren Programmen etliche (Zwischen)versionen erzeuge, hätte ich gerne innerhalb eines Arduino-Sketches den Dateinamen des Arduino-Projektes zur Verfügung gehabt. Gibt es da eine Möglichkeit ? Gibt es evtl. eine vordefinierte Funktion oder Makro, die das automatisiert handhabt ?

Dann könnte auf dem LCD-Display oder im Terminal am Anfang erst mal z.B. "ArduinoTest42.ino" erscheinen, und es wäre klar welcher konkrete Sketch hier aufdem AVR draufgeladen ist.

Ich will das gerade automatisiert haben, ansonsten kenne ich mich leider, daß ich doch immer wieder Vergesse die Versionsnummer manuell im Sketch zu ändern. Und bei mehreren Arduinos und Programmen kann das ein ziemliches Durcheinander werden.

Gruß, Tütenflieger

In der Arduino IDE geht es nicht. Auch das Atmel Studio unterstützt dieses nach deinen Wünschen nicht. Sowas musst du selbst anlegen. Am besten direkt oben im Header.

define VERSION 2.1

o.ä.

Doch, das geht! Dafür gibt es das FILE Makro. Das liefert den vollständigen Pfad.

Wenn man nur den Dateinamen möchte kann man das machen:

Serial.println(strrchr(__FILE__, '\\') + 1);

Und um die Endung (.cpp) abzuschneiden:

const char* filename = __FILE__;
*strrchr(filename, '.') = '\0';
Serial.println(strrchr(filename, '\\') + 1);

Oder um etwas RAM auf dem Stack zu sparen:

void printVersion()
{
  const char* filename = PSTR(__FILE__);
  const char* ptr = strrchr_P(filename, '\\') + 1;

  while (char c = pgm_read_byte(ptr++))
  {
    if (c == '.') break;
    Serial.print(c);
  }
  Serial.println();
}

Danke Serenifly, genau sowas hatte ich gesucht.

Gruß, Tütenflieger

Tütenflieger: Ich will das gerade automatisiert haben, ansonsten kenne ich mich leider, daß ich doch immer wieder Vergesse die Versionsnummer manuell im Sketch zu ändern. Und bei mehreren Arduinos und Programmen kann das ein ziemliches Durcheinander werden.

Danke für die Idee und Serenfly für die Lösung. Ich werde das wohl auch in meine Sketche integrieren.

Statt einer Versionsnummer kann es auch hilfreich sein, den Zeitpunkt der Compilierung als Debugtext auszugeben mit dieser Makrofunktion

  lcd.println(__DATE__);
  lcd.println(__TIME__);

Ich habs mal gestest:
Das Makro __FILE__ funktioniert, und spuckt bei mir nur den Dateinamen ohne Pfad heraus.

Das hier: Serial.println(strrchr(__FILE__, '\\') + 1);
und die folgenden Vorschläge von Serenifly gaben bei mir nix aus.

Bei der Angabe von Backslashs vermute ich mal, daß Serenifly unter Linux arbeitet ?! Ich unter Win8.1. Mit entsprechenden normalen Slashs hab ichs jetzt aber auf die Schnelle nicht getestet. Aber wie schon gesagt, ich habe erstaunlicherweise gar keine Pfadangaben aus dem Makro bekommen. Den Pfad brauche ich aber zugegebenermaßen aber auch nicht.

Gruß,
Tütenflieger

Mhh, ich bin auf Windows 7 und da hat er den ganzen Pfad angezeigt. Mit Backslash...

Dachte das wäre immer so. Wenn da natürlich nur der Dateiname kommt und man dann mit strchr() nach einem Slash oder Blackslash sucht kommt NULL zurück

Hallo,

hab das auch gleich probiert, finde das sehr interessant mit der Namensanzeige.

Bei mir liefert das auch nur den Dateinamen zurück mit Endung. Windows 7 64Bit.

void setup() {
 Serial.begin(38400);

}

void loop() {
  Serial.println(__FILE__);
  Serial.println(__DATE__);
  Serial.println(__TIME__);

  delay(5000);
}

bringt

Dateiname_001.ino
Mar 20 2015
23:18:19

dann habe ich ohne nachzudenken erweitert auf

void setup() {
 Serial.begin(38400);

}

void loop() {
  Serial.println(__FILE__);
  Serial.println(__DATE__);
  Serial.println(__TIME__);

  delay(5000);
  
  const char* filename = __FILE__;
  *strrchr(filename, '.') = '\0';
  Serial.println(strrchr(filename, '\\') + 1);
  
  delay(5000);
  
}

und erhalte das, einmal abgeschnitten, immer abgeschnitten

Dateiname_001.ino
Mar 20 2015
23:21:20

Dateiname_001
Mar 20 2015
23:21:20

Dateiname_001
Mar 20 2015
23:21:20

Dateiname_001
Mar 20 2015
23:21:20

Dateiname_001
Mar 20 2015
23:21:20

Ich komme nur noch nicht dahinter wie das abschneiden funktioniert, denn man arbeitet mit Zeigern. strrchr liefert doch nur die Anzahl der Zeichen zurück bis zum gesuchten Zeichen. Oder? Wenn da noch mehr kommt was man nicht braucht, müßte man doch angeben, gebe von bis aus. Ich hab auch irgendwie einen Knoten im Hirn.

strrchr liefert doch nur die Anzahl der Zeichen zurück bis zum gesuchten Zeichen. Oder

Nein. Das wäre strcspn(): http://www.cplusplus.com/reference/cstring/strcspn/ str(r)chr() liefert wie strstr() einen Zeiger auf das Zeichen: http://www.cplusplus.com/reference/cstring/strrchr/

Den dereferenziert man dann mit * und schreibt NULL an die Stelle. Dann hört der String da auf

Aber strrchr() auf Backslash darfst du dann eben nicht machen, wenn du nicht den vollständigen Pfad hast. Keine Ahnung wieso das bei mir anders ist.

EDIT: Dass er das immer abschneidet liegt daran, dass da nur ein Zeiger auf einen String deklariert wird, der sowieso immer im RAM steht. Wenn man wirklich ein Array deklariert sieht das anders aus.

Hallo,

hab jetzt wie blöde überlegt wie man in dem Bsp. auf 18 kommt, wenn man nach s sucht.

Dann hab ich nochmal gegoogelt. Der Zeiger zeigt auf das letzte gefundene gesuchte Zeichen, auch wenn mehrere vorhanden sind. Richtig?

https://www.proggen.org/doku.php?id=c:lib:string:strrchr

und Du Genie schreibst dann an die Stelle eine 0, was beim nachfolgenden lesen als Endeerkennung dient. Deswegen sah ich nie wieder meine Endung. Genial. Immer wieder faszinierend wie Du das machst. ;)

Deswegen sah ich nie wieder meine Endung

Der Grund weshalb das immer so ist wenn man es nur einmal macht, liegt wie gesagt daran, dass nur ein Zeiger deklariert und kein Array. Daran hatte ich gar nicht gedacht.

Das ist auch unsauber, weil man dann einen NULL-Pointer dereferenziert. Das scheint zwar hier zu gehen, aber genaugenommen ist es undefiniertes Verhalten.

So sieht es schon anders aus:

void loop()
{
  Serial.println(__FILE__);

  char filename[] = __FILE__;
  *strrchr(filename, '.') = '\0';
  Serial.println(filename);

  Serial.println();
  delay(5000);
}

Da wird dann nur das Array geändert und der String ist danach noch komplett im RAM

Und dass sich in den vollständigen Pfad hatte liegt an Visual Micro. In der Arduino IDE kommt da bei mir auch nur der Datei-Name. Und auch .ino statt .cpp (obwohl da auch im Hintergrund eine .cpp Datei draus gemacht wird). In den meisten Fällen greift Visual Micro einfach auf die Arduino IDE zu, aber hier unterscheiden die sich wohl.

Hallo,

funktioniert. :D Egal ob mit IDE 1.0.6 oder 1.6.

Wie gesagt, staune immer wieder wie du mit char's und string's um Dich wirfs't. ;)