Kryptische Zeichen bei Seriellverbindung (Arduino Nano)

Hallo,

ich versuche gerade, über die serielle Schnittstelle meines Arduino Nano über Putty Ein- und Ausgaben zu tätigen, hier erstmal mein Sketch (heruntergebrochen auf das nötigste):

#include <EEPROM.h>

int interval = 5000;  //Counter refresh and save interval
long counter;
char serialinput;
String valueString;
bool serialBlock = false;
unsigned long time_now = 0;

void setup() 
{
  Serial.begin(9600);
}

void loop() 
{
  if(Serial.available())
  {
    Serial.setTimeout(15000);
    serialinput = Serial.read();
    if (serialinput == 's')
    {
      Serial.println("Please enter a new counter value to start with: ");
      serialBlock = true;
      valueString = Serial.readStringUntil('s');       
      long received = atol(valueString.c_str());
      if (received > 0)
      {
        counter = received;        
        Serial.println("received and saved: " + counter);
      } 
      else
      {
        Serial.println("received 0, not saving ");
      }     
      serialBlock = false;
    }
  }
  if (serialBlock == false)
  {
    if(millis() > time_now + interval)
    {
      time_now = millis();
      Serial.println(counter);      
    }
  }
}

Wenn ich das Ausführe und mit s in den Editir-Modus gehe, einen Wert eingebe, und wieder s drücke um den Editiermodus zu verlassen, erhalte ich oft (nicht immer) ein Zeichenwirrwar auf der Konsole:

0
0
0
0
Please enter a new counter value to start with:
▒Wz▒~▒▒▒u▒▒▒z▒wγ~▒▒▒[▒▒g▒y▒▒v▒▒▒~B▒~▒▒▒▒▒▒▒5▒z▒g|▒▒▒S▒W▒▒▒▒▒7▒_7▒▒▒▒͏a▒▒▒G▒}f}▒Wx▒▒՛▒▒J▒;▒▒kR▒Gx▒▒_▒▒ޟ▒{~▒▒׹޼▒_=▒▒׫▒o▒9▒▒g▒\ݩ▒▒پ{▒▒▒o_▒ Rw▒{▒▒~▒▒▒▒▒▒ݥ▒▒▒O▒▒▒▒▒Gν▒▒;▒▒;▒▒?▒▒▒m▒▒▒Ҙ▒ֽ_▒▒▒W▒o:3
▒▒▒▒▒▒▒▒▒▒_W<?▒u▒▒▒▒-▒▒_▒▒▒߰o▒▒▒▒vv▒▒߿▒▒▒.▒▒8▒~X▒
▒▒▒Čw▒▒▒▒?▒▒▒▒▒j▒k▒▒'▒_▒▒▒▒yQ▒2c=/B▒▒~ԍn?▒▒▒▒Z/▒▒▒;p
▒▒߳▒3▒}▒▒▒L3▒▒.՞r▒V▒PMo▒2▒▒彛▒▒▒L▒▒۷V:▒▒▒D▒▒˛▒▒ԻS.]▒,▒BS6▒▒▒s▒▒▒uO▒▒▒▒▒J;▒▒Jf▒2▒Ϧfi▒▒▒ew??▒▒▒▒}▒▒▒▒v▒▒,ڣ▒▒▒▒▒▒▒▒wwuƌ▒▒wn▒cL▒▒r▒▒▒q▒▒▒O▒d▒▒▒y▒L▒▒▒W▒▒▒$▒Zy7▒}▒{▒▒▒^̙▒s▒z6▒}▒lM▒▒▒N:▒3▒▒▒Y~▒▒▒▒^▒_w▒▒{]▒▒<▒▒a▒-▒▒▒▒▒Վvu▒▒"▒▒n▒▒▒ڭjt2▒W▒▒▒▒^G▒|▒▒▒>▒z)▒▒▒i▒▒▒▒▒▒▒d▒▒㿺▒▒w▒n▒▒▒^▒▒r^▒S▒i▒▒F▒#▒=▒-▒▒[▒▒T▒D|n▒▒Z▒▒?Oܷu▒▒▒▒▒j▒t}▒zBk▒▒gy▒͔r+▒-1▒▒▒▒▒[糮▒▒▒▒}▒0b▒]▒▒▒▒▒▒▒▒
ٞ7▒▒▒▒=▒▒▒▒C▒▒▒ztq▒▒߿▒{▒▒▒▒k▒m▒▒▒O▒▒^▒&8j▒▒▒▒-▒~▒y▒%▒▒▒▒▒▒▒▒▒_▒▒▒ݱ'?▒▒▒▒+▒▒߭▒[▒▒▒ퟻ|}Y▒v▒▒oy▒▒▒▒▒=▒9▒▒▒~▒5▒▒W▒▒cyҝP▒eͿ▒▒▒▒X_▒▒▒▒+7
546456464

Oder als Screenshot:

Baudrate ist natürlich in Putty ebenfalls auf 9600 eingestellt. Habt ihr Ideen, woran das liegen könnte? VIelen Dank :slight_smile:

bitte zeige mal genau die Verkabelung zwischen Nano - TTL-Adapter - PC

welchen TTL-Adapter verwendest du - bitte verlinke das Produkt

Das ist einfach ein Arduino Nano "Klon" von Azdelivery (tritt mit einem zweiten baugleichen Gerät ebenfalls auf):

Tausch des USB Kabels hat nichts geholfen. An dem Testarduino hängt sonst nix an Inputs oder Outputs drauf, nur USB Kabel zu PC.

erklär mal was du genau mit deinem Sketch funktional machen willst.

Das wird wahrscheinlich nur gehen wenn du "s1234s" in einem Block sendest und nicht als einzelne Tastendrücke mit Pause.

Natürlich nicht.

Nein!
Das geht so:

long counter=4000;

void setup() 
{
  Serial.begin(9600);
}

void loop() 
{
  Serial.println("received and saved: " + counter);
}

Meldung:

warning: 'strlen' reading 1 or more bytes from a region of size 0 [-Wstringop-overread]

Der Grund für dein Problem:
Deine Zeiger Arithmetik geht gründlich schief.

1 Like

Okay, ich habe aufgrund deines Minimalbeispiels noch nicht verstanden wo ich einen Überlauf habe, auch werden mir in der IDE keine Warnings beim Kompilieren angezeigt, muss man die irgendwo aktivieren?

Sinn und zweck des Ganzen ist in der laufenden Loop durch drücken einer Taste (in meinem Beispiel 's') die Verarbeitung anzuhalten, einen Wert einzulesen (long) und eine interne Variable damit zu beschreiben, wobei die EIngabe mit 's' abgeschlossen wird. Man hätte auch \n nehmen können, ich habe aber das Problem dass unter verschiedenen Termionalprogrammen unter Linux und Windows beim Drücken der Eingabetaste verschiedene Carriage Returns gesendet werden, mal \n, mal \r, mal beides, also pragmatischer Ansatz: nimm halt s :slight_smile:

Soll eigentlich auch gar keine sein.
Serial.println ("hallo" + 3); // Ausgabe "lo"

Wer nur auf die Idee gekommen ist, mit + könne man neue Texte erzeugen ?? :stuck_out_tongue:

1 Like

std::string und String könnten das.
(dank eigener Operatoren)

Habe ich doch gesagt...
Die Addition geht schief.
In deinem (noch zu erwerbenden?) C++ Grundlagenbuch findest du die vollständige Erklärung.

1 Like

Okay, jetzt sehe ich klarer wo das Problem ist. Lösungsansatz:

Serial.println("received and saved: " + (String)counter);

Gab's da nicht auch irgendwas mit Format-Modifieren (in der Art "Der Wert %l wurde gelesen", counter), ich finde da nur die korrekte Syntax gerade nicht :frowning:

Ja, in den Voreinstellungen der IDE kannst Du verschiedene Stufen wählen.

C++ behandelt Zeichenketten etwas abweichend von anderen Sprachen.

long counter=4000;

void setup() 
{
  Serial.begin(9600);
}

void loop() 
{
  Serial.println("received and saved: " + String(counter));  // auf einem Nano nicht empfehlenswert
  char buf[50];
  snprintf(buf, 50, "received and saved: %ld\n", counter++);
  Serial.println(buf);
  delay(2000);
}

Man kann auf einem Nano auch printf nachrüsten.

Formatierte Ausgabe (ergänzt mit freundlicher Unterstützung durch @combie :slightly_smiling_face:)

1 Like

Kurze Frage: warum ausgerechnet auf einem Nano nicht empfehlenswert?

Die String-Klasse soll, so habe ich in diesem Forum gelesen, zu ungenutzten Speicherlücken führen, die wegen das geringen Speichervolumens des ATmega328 zu Laufzeitfehlern führen können. Wenn Du für String-Variablen Speicherplatz vorab reservierst, soll es besser sein.

So ungefähr :innocent:

1 Like

Aber auch nur "ungefähr"!
In diesem Fall nur fürchterlich "unschön", aber kein Fragmentierungsproblem.
Die Stringinstanz, bzw. beide werden lokal erzeugt und wieder dekonstruiert.
Verschwinden also folgenlos.

Ist nur unsinnig kompliziert!
Serial.println("received and saved: " + (String)counter);
Es werden 2 String Instanzen erzeugt.
incl. 3facher Speicherreservierungsorgie

Besser wg. viel sparsamer:
Serial.print(F("received and saved: ")); Serial.println(counter);

Oder wie bei mir üblich:
cout << F("received and saved: ") << counter << endl;

2 Likes

@combie: Danke!

Die Variante von @combie im Zusammenhang:

#include <Streaming.h>
Print &cout = Serial; // cout Emulation für "Arme"

long counter=4000;

void setup() 
{
  Serial.begin(9600);
}

void loop() 
{
  cout << F("received and saved: ") << counter << endl;
  
  Serial.println("received and saved: " + String(counter));  // auf einem Nano nicht empfehlenswert
  
  char buf[50];
  snprintf(buf, 50, "received and saved: %ld\n", counter++);
  Serial.println(buf);

  delay(2000);
}

Quelle

2 Likes

Meiner Meinung nach solltest du das Tutorial durchmachen:
Serial Input Basics - updated - Using Arduino / Introductory Tutorials - Arduino Forum

nach 2 Stunden hast du dann eine sauber funktionierende Serial-Verbindung.

2 Likes