TMRpcm.play funktioniert nicht, wenn Serial.print erfolgt

Hallo,

ich habe die letzte Zeit an einem größeren Code gearbeitet.
Folgende Includes habe ich verwendet:

#include <SD.h>             // You need to include the SD library
#include <EEPROM.h>         // You also need this library to save the volume level to the EEPROM
#include <TMRpcm.h>         // You also need to include this library to play Files
#define SD_ChipSelectPin 4  // Select the CS Pin

Der Code ist 22.714 Bytes groß und läuft auf einem UNO.

Bei dem Code habe ich folgendes Problem:

void setup()
{ 
  pinMode(frontbutton, INPUT_PULLUP);
  pinMode(in, INPUT); // Rotarywheel
  tmrpcm.speakerPin = 9; // Speaker

  Serial.begin(9600);
  if (!SD.begin(SD_ChipSelectPin))
  {
    Serial.println("SD fail");  
    return;
  }
  Serial.println("SD okay"); 
  tmrpcm.quality(2);
  
  volumelevel = EEPROM.read(0);
  [color=red]//Serial.print("Volume "); Serial.println(volumelevel);[/color]
  if((volumelevel >= 1) && (volumelevel <= 4))
  { 
    tmrpcm.setVolume(volumelevel); 
  }
  else
  { 
    tmrpcm.setVolume(3); 
  }
  
  delay(100);
  [color=blue]tmrpcm.play("Auskun.wav");[/color]
  delay(1000);
}
[...]

Wenn ich den Teil "//Serial.print("Volume "); Serial.println(volumelevel);" nichtmehr durch // kommentiere, spielt die TMRpcm Library nichtmehr die "Auskun.wav" Datei.
Das "Serial.println("SD okay");" stör sie jedoch nicht.

Weiter unten das gleiche Problem:

void Anrufen()
{
  Serial.print("Calling Number: "); 
  Serial.print(Nummer[0]); 
  Serial.print(Nummer[1]); 
  Serial.print(Nummer[2]); 
  Serial.println(Nummer[3]);
  delay(100);
  [color=blue]tmrpcm.play("TutTut.wav");[/color]
  if(digitalRead(frontbutton) == HIGH)
  {
    delay(random(2000, 12000)); 
  }
  else
  {
    delay(2000);
  }

  if((Nummer[0] == 10) & (Nummer[1] == 1) & (Nummer[2] == 10) & (Nummer[3] == 1))// 01.01 
  { 
    tmrpcm.play("Test.wav");
  }

[...]

//Laut- und Leisereinstellung
  else if((Nummer[0] == 10) & (Nummer[1] == 10) & (Nummer[2] == 10) & (Nummer[3] == 1))// Lauter 0001
  { 
    //tmrpcm.volume(1);
    [color=red]tmrpcm.play("Lauter.wav");[/color]
    volumelevel = (EEPROM.read(0) + 1); 
    if((volumelevel >= 1) && (volumelevel <= 4)) { 
      tmrpcm.setVolume(volumelevel); 
      EEPROM.write(0, volumelevel);
      [color=limegreen]//Serial.print("New Volume: ");  Serial.println(volumelevel);[/color]
    }
  }

Sobald ich "//Serial.print("New Volume: "); Serial.println(volumelevel);" auskomentiere, spielt er weder "TutTut.wav", obwohl dies viel weiter oben im Sketch geschehen soll, noch "Lauter.wav".

"Serial.print(Nummer[xy]);" stört jedoch wieder nicht...

Auch wenn "Nummer[0] == 10) & (Nummer[1] == 10) & (Nummer[2] == 10) & (Nummer[3] == 1)" nicht zutrift funktioniert es nicht.

Sobald "Serial.print" wieder //kommentiert ist, geht alles wieder...

Habt ihr eine Idee, an was das liegt?
Danke und Gruß

Am RAM.

Aber das ist nur die Standard Idee.

Ausser dass du das F-Makro (FlashStringHelper) offensichtlich nicht kennst, sieht man an deinen Schnipseln nichts. Das Wichtigste, die Variablendefinitionen, fehlt nämlich.

Bist du mit dem RAM am Ende? Sieht fast so aus

Gib das mal am Ende von setup() aus:

int getFreeRAM() 
{
   extern int __heap_start, *__brkval; 
   int v; 
   return (int) &v - (__brkval == 0 ? (int) &__heap_start : (int) __brkval); 
}

Wenn da nicht mehr viel frei ist, hilft erstmal überall wo du print() mit Strings machst ein F() um den String zu machen:

Serial.println(F("String im Flash"));

Gib das mal am Ende von setup() aus:

int getFreeRAM() 
{
   extern int __heap_start, *__brkval; 
   int v; 
   return (int) &v - (__brkval == 0 ? (int) &__heap_start : (int) __brkval); 
}

[/quote]

noch ins setup() { } mit rein oder dahinter?
Dahinter: passiert nichts weiter
Mit rein: 85: error: a function-definition is not allowed here before '{' token

Wieso wird immer alles so wörtlich genommen? :confused:

Das ist eine Funktion. Die kann natürlich nicht in setup() stehen. Aber du sollst du am Ende von setup() aufrufen und auf Serial ausgeben, damit man einmal sieht was noch an Speicher frei ist.

Ich nehme mal an nicht sehr viel. Wenn du dann konsequent bei print() das F() Makro um die Strings macht, sieht du dass du dann mehr frei hast.

Ich steh grad noch auf dem Schlauch...

int getFreeRAM() 
{
   extern int __heap_start, *__brkval; 
   int v; 
   return (int) &v - (__brkval == 0 ? (int) &__heap_start : (int) __brkval); 
}

setup(){
[...]
Serial.print(getFreeRAM);
}

Habe im Code nur 7 Serial.print("String"); drin.
Dann noch ca. 20 Serial.print(integer);s. Sind das echt zu viel?

Serenifly:
Wenn da nicht mehr viel frei ist, hilft erstmal überall wo du print() mit Strings machst ein F() um den String zu machen:

Serial.println(F("String im Flash"));

Das hat jedenfalls geholfen :slight_smile:

Ist das wirklich so schwer zu verstehen? Die Funktion heißt getFreeRAM. Die gibt dir den freien RAM Speicher in Bytes zurück. Wenn du also den Serial Monitor offen hast und dich verbindest wird dir durch den Auto-Reset der freie Speicher angezeigt.

Die SD Library alleine belegt glaube ich schon 512 Byte für den Sektor-Puffer. Das ist ein Viertel deines Speichers.

Integer sind egal. Die müssen so oder so im RAM sein, da es halt Variablen sind. Aber konstante Strings müssen es nicht. Aber durch die Harvard-Architektur des Prozessors und die Limitationen des Compilers werden die beim Programm-Start ins RAM kopiert und verschwenden dort Speicher. Durch das F() Makro bleiben die dann im Flash.

Ansonsten kannst du wie schon gesagt mal deine Variablen Definitionen zeigen. Da lässt sich vielleicht auch was optimieren. z.B. kleinere Datentypen verwenden wenn möglich. Oder Konstanten const deklarieren.

Eben. und du sagst, dass beim auskommentieren von dem einen serial es läuft. daher liegt die Vermutung nahe, dass es eben an diesen paar Bytes liegt.

Deswegen der Ratschlag, die Funktion mit einzubauen, die dir das freie RAM zeigt.

Wenn du allerdings damit schon Probleme hast, solltest du dir zuerst noch ein paar Basics dazu anschauen.

Also die Funktion am Schluss HINTER die letzte geschweifte Klammer und im setup VOR die letzte geschweifte Kammer den Aufruf
Serial. ptrintln(getFreeRAM());
werte merken, alle Strings in F-Macro und wieder Den Wert ausgeben lassen.

ich tippe zu langsam. waren sogar 2 schneller

Hallo,

ich habe das gleiche Problem nun bei einem anderen Arduino.
Habe schon alle Strings probeweise entfernt.

getFreeRAM habe ich eingebaut.
Am Ende vom Setup sagt er mir, dass 398 frei sind.
An der Stelle, wo das Problem auftritt, sagt er mir 347 frei...

[...]
else if(temperaturint == 25) { tmrpcm.play("25.wav"); }
        else if(temperaturint == 26) { tmrpcm.play("26.wav"); }
        else if(temperaturint == 27) { tmrpcm.play("27.wav"); }/*
        else if(temperaturint == 28) { tmrpcm.play("28.wav"); }
        else if(temperaturint == 29) { tmrpcm.play("29.wav"); }
[...]

so geht es.

[...]
else if(temperaturint == 25) { tmrpcm.play("25.wav"); }
        else if(temperaturint == 26) { tmrpcm.play("26.wav"); }
        else if(temperaturint == 27) { tmrpcm.play("27.wav"); }
        else if(temperaturint == 28) { tmrpcm.play("28.wav"); }/*
        else if(temperaturint == 29) { tmrpcm.play("29.wav"); }
[...]

so geht es NICHT, obwohl RAM weiterhin 347 sagt.

hi,

wenn er RAM 347 sagt, ist das ja meiner meinung nach kein "wirklich" ernstzunehmender wert. mehr ein richtwert.
wie soll diese prüfung am ende von setup wissen, wieviel speicher von lokalen variablen benötigt werden wird. die werden ja erst am anfang einer funktion angelegt und am ende wieder gelöscht (so seh' ich das zumindest).

selbst wenn Du es jetzt "gerade so" hinbekommst, stehst Du bei einer änderung bald wieder im regen.
mein tip: nimm einen arduino mega, da hast Du reserven.

gruß stefan