Arduino bleibt bei Stringfunktion hängen

Hi,
ich möchte mehrere Strings zu einem großen String machen, was auch super funktioniert hat. Nachdem ich aber mein Programm weiter geschrieben habe hängt es sich immer an der gleichen Stelle auf, nämlich da wo ich die großen String baue. Hier ist der Codeabschnitt:

void Transceiver(float Temp, float Press, float Hum)
{
  Serial.println("Test Transceiver");
  int sendlengthMax;
  static char sendbuffer[62];
  static int sendlength = 0;
  int Wertelength = 3;
  float Messung[Wertelength] = {Temp, Press, Hum};
  
  char input[sendlengthMax];
  String str = String(Messung[0], 3);
  Serial.println(str);
  if(Wertelength > 1)
  {
    Serial.println("Test1");
    Serial.println(Messung[0]);
    for(int i = 1; i <= (Wertelength - 1); i++)
    {
      Serial.println("Test2");
      Serial.println(Messung[i]);
      Serial.println(String(Messung[i], 3));
      str = str + "/" + String(Messung[i], 3);
      Serial.println("Test3");
    }
  }

Ich komme immer bis "Serial.println(Messung[i]);". Die Stringfunktion muss ein Problem mit dem Aufruf Messung[i] haben, da der Befehl String(Messung[0]) funtioniert.

Schon mal danke für eure Hilfe.
Grüße,
Tim

Oops

Welchen Arduino nutzt Du? Und was sind 'große' Strings?
Die String-Klasse ist sehr speicherintensiv, und deshalb kritisch auf den kleinen Arduinos mit wenig RAM. Dort sollte man die eigentlich besser nicht verwenden - sie führt leicht zu einem Speicherüberlauf und dann hakt's. Besser ist es deshalb, mit C-strings zu arbeiten.
Aus deinem Codefragment kann man nichts entnehmen. Was sagt denn der Compiler über die Speichernutzung?

Ich arbeite mit dem Moteino, welcher 16kB RAM hat. Das ist zwar kein offizielles Board von Arduino kann aber mit der Arduino Software programmieren. Mit "großen Strings" meine ich den String den aus den anderen Strings zusammen baue. Der Compiler sagt, dass ich noch genug Speicher habe. Das Codefragment wird in der loop einfach aufgerufen, wenn gewisse Bedingungen erfüllt sind, daher macht es nicht viel Sinn den ganzen Code zu teilen.

Grüße,
Tim

Do not use the String class / data type on AVR based MCU's, it is known to cause lockups and other weird behavior. You are also mixing String and (c-)string in your concatenations and that is also problematic.

//Remove this
str = str + "/" + String(Messung[i], 3);

//Add this:
str += String("/");
str += String(Messung[i], 3);

If that works, you know that the "String" thing is messing things up. Yet again.

Der Compiler kennt den Speicherverbrauch der Strings nicht, da die erst zur Laufzeit dynamisch angelegt werden.

Gruß Tommy

Viel besser ist
Serial.println(Messung[i], 3);

usw.

Belegt einen undefiniert großen RAM-Bereich auf dem Stack, wie @TheMemberFormerlyKnownAsAWOL schon gleich zu Beginn bemerkt hat.

Das ist zwar blutig Wahr, aber gleichzeitig auch irgendwie uninteressant, da es wegen "unused" gar nicht im Code landet. Der Optimierung zum Opfer fällt.
Ich glaube also nicht, dass das hier das Problem ist.
Repariert gehört es trotzdem!
Keine Frage!

Bei mir läuft die Funktion auf einem UNO!
Perfekt!
Trotz einem ganzen Eimer voll Meldungen:

E:\Programme\arduino\portable\sketchbook\Combie\Pstr001\Pstr001.ino: In function 'void Transceiver(float, float, float)':
E:\Programme\arduino\portable\sketchbook\Combie\Pstr001\Pstr001.ino:24:9: warning: ISO C++ forbids variable length array 'Messung' [-Wvla]
   24 |   float Messung[Wertelength] = {Temp, Press, Hum};
      |         ^~~~~~~
E:\Programme\arduino\portable\sketchbook\Combie\Pstr001\Pstr001.ino:26:8: warning: ISO C++ forbids variable length array 'input' [-Wvla]
   26 |   char input[sendlengthMax];
      |        ^~~~~
E:\Programme\arduino\portable\sketchbook\Combie\Pstr001\Pstr001.ino:21:15: warning: unused variable 'sendbuffer' [-Wunused-variable]
   21 |   static char sendbuffer[62];
      |               ^~~~~~~~~~
E:\Programme\arduino\portable\sketchbook\Combie\Pstr001\Pstr001.ino:22:14: warning: unused variable 'sendlength' [-Wunused-variable]
   22 |   static int sendlength = 0;
      |              ^~~~~~~~~~
E:\Programme\arduino\portable\sketchbook\Combie\Pstr001\Pstr001.ino:26:8: warning: unused variable 'input' [-Wunused-variable]
   26 |   char input[sendlengthMax];
      |        ^~~~~
E:\Programme\arduino\portable\sketchbook\Combie\Pstr001\Pstr001.ino: At global scope:
E:\Programme\arduino\portable\sketchbook\Combie\Pstr001\Pstr001.ino:22:14: warning: 'sendlength' defined but not used [-Wunused-variable]
   22 |   static int sendlength = 0;
      |              ^~~~~~~~~~
E:\Programme\arduino\portable\sketchbook\Combie\Pstr001\Pstr001.ino:21:15: warning: 'sendbuffer' defined but not used [-Wunused-variable]
   21 |   static char sendbuffer[62];
      |               ^~~~~~~~~~
E:\Programme\arduino\portable\sketchbook\Combie\Pstr001\Pstr001.ino: In function 'Transceiver(float, float, float)':
E:\Programme\arduino\portable\sketchbook\Combie\Pstr001\Pstr001.ino:26:27: warning: 'sendlengthMax' is used uninitialized [-Wuninitialized]
   26 |   char input[sendlengthMax];
      |                           ^

Ihm möchte das in einem String zusammenstoppeln, um es an anderer Stelle Auszugeben/weiterzugeben.
Die Serial... sind wohl nur Debugausgaben.

Danke für den Anstoß!



// eine String Klasse in die man rein Drucken kann
class Pstr : public String, public Print
{
  public:
  using String::String;
  using String::operator =;
  virtual size_t write(uint8_t value) override
  {
    *this += static_cast<char>(value);
    return 1;
  }
};

void Transceiver(float Temp, float Press, float Hum)
{
  Pstr str;
  str.reserve(50);
  constexpr unsigned Wertelength = 3;
  float Messung[Wertelength] = {Temp, Press, Hum};
  
  str.print(Messung[0], 3);
  if(Wertelength > 1)
  {
    for(unsigned i = 1; i < Wertelength; i++)
    {
      str += "/"; 
      str.print(Messung[i], 3);
    }
  }
  Serial.println(str); // kontrollausgabe
}


void setup() 
{
  Serial.begin(9600);
  Transceiver(27.66, 854.5, 65.76);
}

void loop() 
{

}

Ausgabe: 27.660/854.500/65.760

Oh, das wollte ich nicht.
Eine Funktion, die beim Aufruf drei Zahlen auf Serial ausgibt, kann man einfacher schreiben.

Dafür schon. Bitte sehr. :slight_smile:

Mir egal...
Jetzt must du mit den Folgen leben.
:japanese_ogre:

Ist doch hübsch... oder?

Danke für die vielen Antworten. Die Serial.print Aufrufe dienen nur zum debugen. Der zusammengebaute String soll per funk später an einen anderen Moteino gesendet werden, daher möchte alle 3 Messwerte zu einem String haben um nicht jeden Wert einzeln zu schicken.
Der Ansatz von @combie mit der Klasse sieht nicht schlecht aus. Den werde ich Dienstag oder Mittwoch ausprobieren können, da das kein privates Projekt ist sondern ein HiWi Projekt und ich nicht jeden Tag im Büro bin.