Ist "String" hier ein Problem?

Hi,

ich habe hier einen kleinen Testsketch, mit dem ich die Funktionalität mit einem Bluetooth-Modul getestet hatte, funktioniert auch wie gewünscht. Was ich nicht weiß ist, wenn der Testsketch dann Teil eines etwas größeren endlichen Automaten wird, ob mir “String msg” den RAM fragmentiert? Falls ja, würde ich mich über einen Lösungsansatz freuen.
Der Sketch gibt ziemlich genau wieder was ich benötige: Eine Zeichenkette wird via BT-Terminal vom Smartphone gesendet, und bei Übereinstimmung auf dem Arduino als Aktion ausgeführt. Einzelne Ziffern oder Buchstaben auszuwerten helfen mir hier nicht weiter.

Gruß André

/*
  Wiring Setup
  ============
  Bluetooth Module Rx-------Arduino Pin 11 (Tx)
  Bluetooth Module Tx-------Arduino Pin 10 (Rx)
  Bluetooth Module VCC------Arduino 5v
  Bluetooth Module GND------Arduino GND
*/

#include <avr/wdt.h>                          // Watchdog-Timer
#include <SoftwareSerial.h>
const byte BTRX = 10;
const byte BTTX = 11;
SoftwareSerial SerialBT(BTRX, BTTX);
String msg;                                   // Die versendete Nachricht

void setup()
{
  pinMode(LED_BUILTIN, OUTPUT);               // Eingebaute LED nutzen
  SerialBT.begin(9600);                       // Verbindung mit HM-10 || HC-05 aufbauen
  SerialBT.println(F("BT-Verbindung steht"));
  wdt_enable(WDTO_4S);                        // Watchdog auf 4 s stellen
}

void loop()
{
  wdt_reset();

  if (SerialBT.available())                   // Daten liegen an
  {
    msg = SerialBT.readString();              // Nachricht lesen
    if (msg == "ein")
    {
      digitalWrite(LED_BUILTIN, HIGH);
      SerialBT.println(F("LED an Pin 13 ist eingeschaltet!"));
    }
    else if (msg == "aus")
    {
      digitalWrite(LED_BUILTIN, LOW);
      SerialBT.println(F("LED an Pin 13 ist ausgeschaltet!"));
    }
    else if (msg == "Reset")
    {
      digitalWrite(LED_BUILTIN, HIGH);
      SerialBT.println(F("Reset wird durchgeführt!"));
      delay(5000);
    }
    else
    {
      SerialBT.print(F("Eingabe <"));
      SerialBT.print(msg);
      SerialBT.println(F("> ungültig"));
    }
  }
}

Falls Du Deine Message mit einem Endezeichen (z.B. NewLine '\n') abschließt, kannst Du die Routine hier benutzen, um diese in ein Char-Array einzulesen.

Zur Fragmentierung hätte ich früher immer ja gesagt. Da habe ich aber letztens dafür hier Schelte bekommen, also halte ich mich da raus. Das muss dann jeder selbst feststellen, ob es auf Dauer funktioniert oder nicht.

Gruß Tommy

[quote author=Reference readString]The function terminates if it times out[/quote] if sollte wohl eher only when heißen und deutet an, dass es sich nur um eine convenience Funktion für ganz Faule ohne große Ansprüche handelt. Ein Endezeichen (newline) statt Timeout ist sicher besser.

Warum ein einzelner Buchstabe (z.B. 'e', 'a', 'R') als Kommando nicht ausreicht, erschließt sich mir übrigens aus den Ausführungen bisher nicht.

Und, zur eigentlichen Frage: Kann gut sein, dass String Objekte kein Problem darstellen, auch wenn die Ansprüche noch ein wenig steigen sollten. Nicht benutzter RAM braucht genausoviel Strom wie benutzter.

Einzelne Ziffern oder Buchstaben auszuwerten helfen mir hier nicht weiter

naja, so wie du aktuell

if (msg == "ein")

mit deinem Großbuchstaben-S-String Objekt msg machst,

kannst ja auch strcmp, strncmp und ähnliches mit char Arrays machen. Wo ist das konkrete Problem eine Zeichenkette zu vergleichen?

Hi,

erstmal danke für eure Antworten!
Ich habe mir bisher keine Gedanken darüber gemacht, ob man bei einem BT-Modul die Nachricht auch anders annehmen könnte als in Form eines Strings oder eines einzelnen chars, da eine BT-Verbindung einigermaßen sicher sein sollte, im Gegensatz zu einem HC-12 Moduls (433 MHz serial pass truth) zum Beispiel.
Einzelne Buchstaben oder Ziffern fallen aber aus Sicherheitsgründen aus.
Wenn ich die msg vom BT-Modul aber genau so entgegen nehmen kann wie die langsamen Bytes bei meinem HC-12 Modul, dann hätte ich eine Lösung mit Start- und End-Marken schon da. Danke fürs darüber sprechen!

Gruß André

Hallo,

Tommy56:
Zur Fragmentierung hätte ich früher immer ja gesagt. Da habe ich aber letztens dafür hier Schelte bekommen, also halte ich mich da raus. Das muss dann jeder selbst feststellen, ob es auf Dauer funktioniert oder nicht.

den Hinweis, daß man sich des Problems mit Fragmentierung bewußt sein sollte, halche auch ich für sehr wichtig. Auf den kleinen AVR sehr wichtig, bei den ESP8266 und ESP32 o.ä. weniger, weil es erst bei großen Stringlängen und komplexen Stringbearbeitugen zuschlägt.
Wenn sowas nach mehr oder längerer Laufzeit scheinbar zufällig abstürzt, ist das auch bei mir erste Stellen zum prüfen.
Bei seiner BT-Sache wäre schon die Frage, welche Anzahl Zeichen da in String msg maximal ankommen können und wie man den String anschließend weiter bearbeitet. Auf einem kleinen AVR würde ich schon ab 16-32 Zeichen nachdenklich werden…

Gruß aus Berlin
Michael

Wenn ich die msg vom BT-Modul aber genau so entgegen nehmen kann wie die langsamen Bytes bei meinem HC-12 Modul, dann hätte ich eine Lösung mit Start- und End-Marken schon da.

Deine BT Nachricht kommt auch nur mit 9600 rein. Da sehe ich keinen Unterschied zur HC12-Kommunikation (außer beim HC12 Übertragungsmodus FU4 mit max 1200 Bd und eff. 500 bps).

Hi,

@ noiasca, nach dieser Abhandlung von Robin habe ich vor 2 Monaten meine HC-12 Verbindung aufgebaut und getestet, nur die BT-Verbindung habe ich damit nicht in Zusammenhang gebracht.
@ amithlon, die einzelne msg wird zwischen 8 bis max. 16 Zeichen groß sein, und auf einem Pro Mini laufen, wird aber mindestens bis Weihnachten dauern, daß die HW und der Sketch steht …

Gruß André

den spannungsteiler an tx sollte man noch erwähnen.

Zur Fragmentierung hätte ich früher immer ja gesagt. Da habe ich aber letztens dafür hier Schelte bekommen, also halte ich mich da raus. Das muss dann jeder selbst feststellen, ob es auf Dauer funktioniert oder nicht.

Kann mich nicht an Schelte erinnern. Aber vielleicht war sie ja berechtigt... KA....

Und ja: Fragmentierung kann zu einem Problem werden.

Wenn man allerdings nur eine einzige String Instanz verwendet, und sonst keine dynamische Verwaltung, dann eher nicht.

Auch kann man sich etwas gegen die Fragmentierung wehren, in dem man einmal genug Speicher reserviert.

Wie auch immer... Gut und Böse, lassen sich nicht/kaum pauschalisieren. Denn dafür ist das Konzept "Rand-/Rahmenbedingung" zu weit verbreitet.

Hallo combie,

vielen Dank auch für Deine geschätzte Antwort! Beim stöbern im Netz zum Thema "böse" Strings bin ich heute auch über reserve() gestolpert, und wenn ich es richtig interpretiere, dann wird für den String ein Speicherbereich alloziert, der immer wieder dafür verwendet wird?!

https://learn.adafruit.com/memories-of-an-arduino/optimizing-sram

Gruß André

Ja, mit reserve kann man der Fragmentierung entgegen wirken. Mann sollte ihn also so groß machen, dass der geplante Inhalt rein passt.

Gruß Tommy

Mann sollte ihn also so groß machen, dass der geplante Inhalt rein passt.

Der Witz ist eben, dass man sich Gedanken macht. Allerdings wurde die String Klasse erfunden für Leute, die sich keine Gedanken machen. :)

Die müssen dann halt mit den evtl. auftretenden Problemen leben. Ich finde, Leute die sich keine Gedanken machen, sollten sowieso von der Programmierung fern bleiben.

Gruß Tommy

Ich finde, Leute die sich keine Gedanken machen, sollten sowieso von der Programmierung fern bleiben.

Das größte Problem, ist die Wahl der richtigen Gedanken. Frei nach Dale Carnegie

Hallo combie

Du hattest geschrieben "allerdings nur eine einzige String Instanz verwendet"

bedeutet das man es nur für einen String benutzen kann oder auch mehrere

gib es so etwas für Char String

Gruss juergen

Du kannst so viele Instanzen nutzen wie du magst.