Hier ist mein Code, welcher leider nicht funktioniert. Wo ist aber der Fehler?
1 | |
2 | |
3 | |
4 | |
5 | |
6 | |
7 | |
8 | |
9 | |
10 | |
11 | |
12 | |
13 | |
14 | |
15 | |
16 | |
17 | |
18 | |
19 | |
|
Anzeige
|
Arduino: if(String == "ein") funktioniert nicht
Gast
#6383045
Hier ist mein Code, welcher leider nicht funktioniert. Wo ist aber der Fehler?
Etitie schrieb: > Hier ist mein Code, welcher leider nicht funktioniert. Was erwartest du und was tut sich stattdessen? > Wo ist aber der Fehler? Welche Fehlermeldung bekommst du denn wofür?
Beitrag #6383047 wurde von einem Moderator gelöscht.
Gast
#6383048
Etitie schrieb: > leider nicht funktioniert. Wo ist aber der Fehler? Grundlagen von C(++). if(befehl == "ein" fragt, ob die Speicheradresse des ersten Zeichens in befehl identisch mit der Speicheradresse des ersten Zeichens des konstanten Strings "ein" ist. Natürlich niemals. Du brauchst eine Funktion wie strcmp oder befehl.compare MaWin schrieb: > Du brauchst eine Funktion wie strcmp oder befehl.compare Ich vermute mal, dass das ein C++ String ist und seit wann muss ich bei C++-Strings strncmp verwenden? if, else if, else
Gast
#6383052
Lothar M. schrieb: > Was erwartest du und was tut sich stattdessen? Wenn ich "ein" eingebe, passiert garnichts. Lothar M. schrieb: > Welche Fehlermeldung bekommst du denn wofür? Keine. MaWin schrieb: > Grundlagen von C(++). > > if(befehl == "ein" fragt, ob die Speicheradresse des ersten Zeichens in > befehl identisch mit der Speicheradresse des ersten Zeichens des > konstanten Strings "ein" ist. Natürlich niemals. > Du brauchst eine Funktion wie strcmp oder befehl.compare Ich glaube Arduino ist einwenig anders als reines C++ und C. Das geht das schon. MaWin schrieb: > if(befehl == "ein" fragt, ob die Speicheradresse des ersten Zeichens in > befehl identisch mit der Speicheradresse des ersten Zeichens des > konstanten Strings "ein" ist. Man könnte aber den "==" Operator so überladen, dass er so einen Stringvergleich auch tatsächlich beherrscht. Oder wie war das mit dem ++ in C++? In VHDL mache ich sowas auf jeden Fall ständig... ;-) Probier mal die strcmp funktion aus. Etitie schrieb: > Ich glaube Arduino ist einwenig anders als reines C++ und C. Nicht so sehr, wie du es dir erträumst. > Das geht das schon. Ja, offenbar doch eher nicht. Oder wie jetzt? Du musst also nachsehen, ob in der Stringklasse der Vergleich auf "==" tatsächlich so implementiert ist, wie du es willst. So wie ich das sehe ist das nämlich eine recht stupide Klasse: https://www.arduino.cc/reference/de/language/variables/data-types/stringobject/ Von Vergleichsoperatoren ist da keine Rede.... Lothar M. schrieb: > So wie ich das sehe > ist das nämlich eine recht stupide Klasse: So wie ich das sehe, sollte das funktionieren: https://www.arduino.cc/reference/de/language/variables/data-types/string/operators/comparison/ Ich denke eher, dass bei diesem mystischen und geheimen Code der Fehler an anderer Stelle liegt. Ben S. schrieb: > Ich denke eher, dass bei diesem mystischen und geheimen Code der Fehler > an anderer Stelle liegt. Der Fehler liegt eher an der anderen Seite der seriellen Leitung. Er muss ja ein "ein" ohne "\n" o.Ä. danach senden. Das können die meisten Seriellen Terminalprogramme nicht, die warten auf die Enter-Taste. Ich würde ein "befehl.trim()" nach dem readString empfehlen. Hallo Serial.avalable() geht schon beim ersten Zeichen in die if-Schleife. Dann liest Du schon den ser Buffer aus. Im ungünstigsten Fall steht da jetzt nur ein "e" drin. Das entspricht natürlich nicht dem "ein". Lass die doch die Variable befehl einfach mal direkt nach dem befehl = Serial.readString(); auf dem Monitor ausgeben. Gruß Ulf
Gast
#6383071
Dann erkennst du was dein System rein bekommt... Geschafft schrieb: > Dann erkennst du was dein System rein bekommt... Abzüglich irgendwelcher Steuerzeichen, die nicht übertragen werden. Ulf L. schrieb: > Serial.avalable() geht schon beim ersten Zeichen in die if-Schleife. > Dann liest Du schon den ser Buffer aus. Im ungünstigsten Fall steht da > jetzt nur ein "e" drin. Aber Serial.readString() wartet danach noch hardcoremäßig irgendein Timeout ab: https://www.arduino.cc/reference/de/language/functions/communication/serial/readstring/ > Lass die doch die Variable befehl einfach mal direkt nach dem befehl = > Serial.readString(); auf dem Monitor ausgeben. Ja, so ein richtiger Debugger ist schon echtes Gold wert. Und dessen Fehlen auch der Grund, warum ich diese Andruiden so ungern benutze. Da artet das Debuggen immer gleich in eine Ratestunde aus und man muss mit dem LA parallel nachmessen, was sich auf der Schnittstelle tut usw... Εrnst B. schrieb: > Er muss ja ein "ein" ohne "\n" o.Ä. danach senden. Das können die > meisten Seriellen Terminalprogramme nicht, die warten auf die > Enter-Taste. Mit dem "Seriellen Monitor" in der Andruiden-IDE kann man das auswählen: https://learn.sparkfun.com/tutorials/terminal-basics/arduino-serial-monitor-windows-mac-linux Ich nehme aber gern das alte OCConsole Terminal, das sendet einfach jedes Zeichen genau dann, wenn ich es tippe... ;-) Etitie schrieb: > leider nicht funktioniert Bei anderen funktioniert: https://youtu.be/MAnAc_t0OrM?t=1660
Gast
#6383082
Ulf L. schrieb: > Lass die doch die Variable befehl einfach mal direkt nach dem befehl = > Serial.readString(); auf dem Monitor ausgeben. Dann wird "ein" ausgegeben. Es wird immer das ausgegeben, was eingegeben wurde. Mich wunderts nur, dass eine Neue Zeile dazwischen eingefügt wird. wegen dem \n Terminator? Etitie schrieb: > Mich wunderts nur, dass eine Neue Zeile dazwischen eingefügt > wird. Eben. Mach statt dem println(befehl) ein print("["); print(befehl); println("]"); dann siehst du, dass nicht nur "[ein]" sondern "[ein ]" rauskommt. deshalb: befehl.trim().
Gast
#6383095
Εrnst B. schrieb: > deshalb: befehl.trim(). Jetzt funktionierts!!! Danke!
Gast
#6383104
Εrnst B. schrieb: > deshalb: befehl.trim(). Viel zu kompliziert. Einfach das "\n" anhängen: if(befehl == "ein\n"){ }else if(befehl == "aus\n"){ und schon läufts.
Gast
#6383118
Sein Problem ist auch das es in der Arduino IDE einen definierten String-Vergleich gibt: equalsIgnoreCase() myString.equalsIgnoreCase(myString2) Ohne GS/KS und: equals() myString.equals(myString2) mit GS/KS. Wenn er diese Funktionen verwenden würde, wäre auch ein richtiges true oder false für seine if/else Vergleiche vorhanden. Vielleicht sollte der TO mal hier lesen: https://www.arduino.cc/en/Tutorial/BuiltInExamples#strings Mit freundlichen Grüßen EGS Ich verstehe nicht warum Serial.readString(); die Steuerzeichen bekommt. Das Terminal sendet die Eingabe erst nach (einem klick auf) send. Anders wäre es, wenn jedes Zeichen einzeln live eingelesen würde. Oder ist das ein Bug in der Arduino IDE?
Gast
#6383279
Mister A. schrieb: > Ich verstehe nicht warum Serial.readString(); die Steuerzeichen bekommt. > Das Terminal sendet die Eingabe erst nach (einem klick auf) send. Das Terminal sendet den String mit Sicherheit einschließlich einem abschließenden Zeilenumbruch. Bei den meisten Terminalprogrammen kann man einstellen ob und womit die Zeilen abgeschlossen werden sollen.
Gast
#6383300
Schön, dass man Dir helfen konnte.
Hier die Anleitung zur Selbsthilfe, wenn sowas wieder auftritt:
Ich hätte auch geraten, die Eingabe im Sketch erstmal probehalber
auszugeben.
Das print("["); print(befehl); println("]"); geht auch - nunja, - ich
hätte in einer for-Schleife die Länge des Eingabestrings und die
Ascii-Codes jedes enthaltenen Zeiches ausgegeben.
Dann sieht man gseht genau, was eigentlich passiert.
hase
Frank schrieb: > Viel zu kompliziert. > Einfach das "\n" anhängen: > if(befehl == "ein\n"){ > }else if(befehl == "aus\n"){ > und schon läufts. Wenn Du Pech hast, kommt da aber "ein\r" oder "ein\r\n" zurück. Man sollte da schon so flexibel sein, dass man beliebige Whitespaces abschneidet. Dafür bietet sich trim() in einfachster Form an. Oder man schreibt etwas eigenes, denn trim() hat die Unart, auch "echte Spaces" (Leerzeichen) abzuschneiden, was unter Umständen auch unerwünscht sein kann.
Gast
#6383444
Sein Problem ist das er bisher auf Systeme programmiert hat, die Speicher satt haben. "Ein" und "aus" als String in einen Arduino das ist gruselig. Das macht man via True / False als Boolean. Der Grund ist einfach. Du verbrauchst wertvollen Speicherplatz. Wenn ich meine VB-Programme entwickele mache ich es manchmal genauso. Aber da sind mir 10 KB Programmcode/Variablenspeicher völlig egal. Da geht es um die Übersicht und die Möglichkeit spätere Änderungen zu machen ohne das Prg. neu zu schreiben. In einen Arduino ist Speicher Mangelware. Da solltest du von Anfang an lernen das so was Unsinn ist. Davon abgesehen ist, wie du gelernt hast, Stringverarbeitung im Arduino nicht gerade angenehm. Außer das ich Daten erstelle muss (für eine SD-Karte) kenne ich keine Anwendung die Strings braucht. Ausgaben an ein Display gehen auch ohne. Einfach den String als Text senden und gut ist. Deshalb kann man bei alles Displays die ich kenne die Position genau bestimmen. Wenn man den Text mit Leerzeichen auffüllt, wird auch ein möglicher alter Überhang gelöscht. ;) Kleiner Tipp. Schau mal beim Compilieren / Erstellen des Codes unten hin. Dann siehst du was du an Speicher von wie viel Speicher verbrauchst. Und 2 -3 Libs dazu und schon hast du ein großes Problem und fragst wie man Libs "Kürzen" kann ;) Schlaumaier schrieb: > "Ein" und "aus" als String in einen Arduino das ist gruselig. nö, man muss es nur richtig machen
ist noch etwas gemischt klappt aber seit Jahren auch auf dem nano Stefan ⛄ F. schrieb: > Bei den meisten Terminalprogrammen kann > man einstellen ob und womit die Zeilen abgeschlossen werden sollen. aber das Ende sollte schon erkannt werden if(incomingByte == 13) oder if(incomingByte == '/r') nur kommt das i.d.R. nicht in den "String" also manuell die 0 einsetzen zur Weiterverarbeitung
Beitrag #6383637 wurde von einem Moderator gelöscht.
Karl K. schrieb im Beitrag #6383637: > Und dann werden die ganzen Strings noch im RAM > vorgehalten, statt sie aus dem Flash zu holen. wo denn? der der eingelesen wird muss ins RAM der mit dem verglichen wird ist im flash falls noch einer kommt: OK du vermisst wohl: else if( strstr_P(serial_in_command, PSTR("hell")) ) keine Sorge, ist drin, habe nur ein altes Beispiel gezeigt, der TO darf auch noch lernen
Gast
#6383643
Schlaumaier schrieb: > In einen Arduino ist Speicher Mangelware. Noch nie einen Arduino in der Hand gehabt? Die gibts mittlerweile mit richtig viel Speicher; da kommts auf einige 100kB nicht mehr an... Frank schrieb: > Noch nie einen Arduino in der Hand gehabt? > Die gibts mittlerweile mit richtig viel Speicher; da kommts auf einige > 100kB nicht mehr an... zu dem bemängeltem Code war vom ESP der 512k SRAM hat deswegen fehlte auch strcmp_P und PSTR()
Gast
#6383672
Joachim B. schrieb: > } // if !(chr_cnt<(MAXBUFFER-2)) > } // if(isprint(incomingByte)) > } // if !(incomingByte == 13) > } // while (Serial.available()) Wenn man Kommentare dieser Art braucht, um nicht den Überblick zu verlieren, sollte man die Verschachtelung verringern. Joachim B. schrieb: > if(incomingByte == 13) { // Wenn das Enter ankommt Warum die 13 und nicht '\r'? Du ja auch '\0' statt 0. Bei der Gelegenheit kannst du dann auch den fehlerhaften Kommentar in der Zeile löschen.
Gast
#6383686
Joachim B. schrieb: > else if( strstr_P(serial_in_command, PSTR("hell")) ) > > keine Sorge, ist drin, habe nur ein altes Beispiel gezeigt, der TO darf > auch noch lernen Bei so kurzen Strings spart man womöglich nicht einmal was, weil der Zugriff auf den Flash aufwändiger ist, als RAM. mh schrieb: > Warum die 13 und nicht '\r'? nicht gelesen? ist alter Code im Schnellzugriff, ich lerne auch immer dazu Joachim B. schrieb: > aber das Ende sollte schon erkannt werden > if(incomingByte == 13) oder if(incomingByte == '/r') Stefan ⛄ F. schrieb: > Bei so kurzen Strings spart man womöglich nicht einmal was, weil der > Zugriff auf den Flash aufwändiger ist, als RAM. auch das ist mir schon aufgefallen, aber trotzdem gab es ja einen Kommentar und der wurde gelöscht! Joachim B. schrieb: > Karl K. schrieb im Beitrag #6383637: >> Und dann werden die ganzen Strings noch im RAM >> vorgehalten, statt sie aus dem Flash zu holen. aber ich prüfe ja wieviel Byte frei sind und kann entscheiden ob ich aus dem flash lese mit strxxx_P PSTR() oder nicht! Etitie schrieb: > if(befehl == "ein") Ich würde es mit
versuchen. https://www.c-howto.de/tutorial/strings-zeichenketten/string-funktionen/strings-vergleichn/
Gast
#6383849
Etitie schrieb: > if(befehl == "ein") Gerald K. schrieb: > Ich würde es mitif (strcmp(befehl,"ein") == 0) Möchte noch jemand diesen falschen Hinweis geben? strcmp() ist für C Zeichenketten vorgesehen, nicht für Arduino Strings, das sind C++ Objekte. Die String Klasse hat den Operator == überscheieben, so dass Etite sie bereits korrekt angewendet hat. Der Knackpunkt mit dem Zeilenumbruch wurde bereits geklärt.
Gast
#6383858
Stefan ⛄ F. schrieb: > Möchte noch jemand diesen falschen Hinweis geben? Ach, So ganz falsch ist das ja nicht, denn die Klasse verwendet schließlich intern strcmp(), genau für diesen Zweck. Also Thema korrekt erkannt, aber Kontext nicht verstanden. > if (strcmp(befehl.c_str(),"ein") == 0) würde sogar funktionieren. (wenn nicht das EndlineChar Drama bestehen würde) Stefan ⛄ F. schrieb: > Möchte noch jemand diesen falschen Hinweis geben? > > strcmp() ist für C Zeichenketten vorgesehen, jaaa
.c_str() https://www.arduino.cc/reference/en/language/variables/data-types/string/functions/c_str/ https://www.arduino.cc/en/Tutorial/BuiltInExamples#strings
Gast
#6383880
Ich benutze an solchen Stellen das Stream Interface, das auch die Serial Klasse unterstützt:
Innerhalb der Hauptschleife rufe ich wiederholt die Funktion appendUntil() mit dem selben Puffer auf. Wenn der erwartete Terminator (z.B. '\n') empfangen wurde, liefert die Funktion true zurück. Dann kann ich die bis dahin empfangene Zeichenkette verarbeiten. Der Terminator wird weg geschnitten. Achtung: Der Puffer muss vor Aufruf der Funktion als Leerstring initialisiert werden, als mit \0 beginnen.
Stefan ⛄ F. schrieb: > Achtung: Der Puffer sollte optimal auch min 2 Byte größer sein um evtl. '/r' & '/n' aufzunehmen und gleichzeitig der Pufferüberlauf verhindert werden, wer weiss was so alles kommen könnte! Manchmal kommt auch Müll bei "Empfangsstörungen" Die meiste Arbeit ist immer Fehler abzufangen. dazu gehört auch das Zeichen auf isprint() zu prüfen
Gast
#6383890
Stefan ⛄ F. schrieb: > Achtung: Der Puffer muss vor Aufruf der Funktion als Leerstring > initialisiert werden, also mit \0 beginnen. Wobei das im obigen Fall automatisch passiert, weil buffer eine globale Variable ist. Nach der Verarbeitung leert man ihn dann mit buffer[0]=0 so dass er für die nächste Eingabe bereit ist. Mit der String Klasse habe ich mir zu oft den Heap fragmentiert, darum verwende ich lieber eine offensichtlichere Speicherverwaltung, wo ich sehe, was passiert.
Gast
#6383913
Lothar M. schrieb: > Du musst also nachsehen, ob in der Stringklasse der Vergleich auf "==" > tatsächlich so implementiert ist, wie du es willst. > Von Vergleichsoperatoren ist da keine Rede.... Weil die Doku von Arduino unvollständig ist. Wenn man da wenigstens eine ordentliche IDE hätte, die einen das hin und her Springen im dokumentierten Quelltext ermöglichen würde, wäre das nur halb so wild. Aber das fehlt da ja auch. Ich benutze die IDE Qt Creator als "Externen Editor".
Gast
#6383914
Stefan ⛄ F. schrieb: > Mit der String Klasse habe ich mir zu oft den Heap fragmentiert, darum > verwende ich lieber eine offensichtlichere Speicherverwaltung, wo ich > sehe, was passiert. Der geschickte Einsatz von String::reserve() mildert das Problem. ------------ Lothar M. schrieb: > Von Vergleichsoperatoren ist da keine Rede.... Hier findet sich das Interface der Klasse: https://github.com/arduino/ArduinoCore-avr/blob/master/cores/arduino/WString.h
Beitrag #6383919 wurde von einem Moderator gelöscht.
Arduino Fanboy D. schrieb: > Der geschickte Einsatz von String::reserve() mildert das Problem. Der geschickte Einsatz einer Programmsprache, die Strings in der Länge begrenzt, mindert das Problem enorm. Beim Arduino gibts offenbar nichtmal eine Möglichkeit, die Buffergröße für Serial einzustellen. Stefan ⛄ F. schrieb: >> Ich würde es mitif (strcmp(befehl,"ein") == 0) > Möchte noch jemand diesen falschen Hinweis geben? Ich werfe folgendes in den Raum: if (strncmp(befehl.c_str(), "ein", 3) == 0) {...} Das löst auch das Problem mit nachfolgenden Zeichen (und ja, als Schönheitsfehler erkennt es "einander" auch als "ein").
Gast
#6384100
S. R. schrieb: > Ich werfe folgendes in den Raum: > if (strncmp(befehl.c_str(), "ein", 3) == 0) {...} Auch damit wechselst du zwischen C und C++., was unnötige Konvertierung erfordert und den eigenen Quelltext schlechter lesbar macht. Besser wäre in diesem Fall: if (befehl.indexOf("ein")==0) {...}
Beitrag #6384102 wurde von einem Moderator gelöscht.
Gast
#6384240
Stefan ⛄ F. schrieb: > Auch damit wechselst du zwischen C und C++., Das passiert nur in deinem Kopf. Stefan ⛄ F. schrieb: > was unnötige Konvertierung erfordert Das passiert nur in deinem Kopf. Stefan ⛄ F. schrieb: > und den eigenen Quelltext schlechter lesbar macht. Naja, dem kann ich zustimmen. Karl K. schrieb: > Der geschickte Einsatz einer Programmsprache, die Strings in der Länge > begrenzt, mindert das Problem enorm. Wenn einem die originale String Klasse nicht passt, baut man sich eine eigene, oder verwendet eine, welcher das gewünschte Feature auf dem Schirm hat. z.B. https://www.arduino.cc/reference/en/libraries/safestring/ Schwer vorstellbar, dass du damit überfordert bist. Auch wird so ganz schnell klar, dass es kein Problem der Programmiersprache ist.... Karl K. schrieb: > Beim Arduino gibts offenbar nichtmal eine Möglichkeit, die Buffergröße > für Serial einzustellen. Eine Nebelkerze? Denn mit dem Eingangsproblem hat das herzlich wenig zu tun. Vielleicht ist die Einstellung nicht einfach erreichbar... Aber dass es keine Möglichkeit gibt, ist schlicht falsch! Schwer vorstellbar, dass du damit überfordert bist, den richtigen Ort zu finden, und die Buffergröße nach Wunsch einzustellen. Aber wenn dem wirklich so sein sollte, kann ich dir den Punkt gerne zeigen. Karl K. schrieb: > Beim Arduino gibts offenbar nichtmal eine Möglichkeit, die Buffergröße > für Serial einzustellen. das ist falsch, es ist möglich aber nicht zielführend! für MICH (wohlgemerkt) war es OK die Buffergröße für Serial zu beizubehalten, in meinen Programmen einen eigenen Eingangsbuffer zu definieren und etwas Platz zu lassen für CR und LF und zeichenweise einzulesen, maximale Größe bestimmte ich nach den erwarteten Befehlen +2 und wenn ich 2 Byte unter der Länge war und kein CR oder LF kommt den Buffer zu verwerfen und auf NULL zu setzen, sonst eben, als Terminator wieder 0 am Ende anzuhängen. Somit ist Weiterverarbeitung mit strxxx problemlos möglich. Zu dem Code wäre noch anzumerken, dass auch readString() nicht ganz
unproblematisch ist, da diese Funktion – anders als istream::getline()
und std::operator>>(string) aus der Standardbibliothek – als einziges
Kriterium für das String-Ende einen Timeout (Default: 1 s) verwendet.
Sendet man den String mit einem gewöhnlichen Terminalprogramm, muss man
die Zeichen zügig eintippen, um zu vermeiden, dass der Timeout schon vor
dem Ende der Eingabe zuschlägt.
Beim Serial-Monitor der Arduino-IDE hat man dieses Problem nicht, da
dieser immer ganze Zeilen puffert. Aber auch hier muss man nach dem
Abschicken 1 s (oder was immer als Timeout eingestellt wurde) warten,
bis das Programm auf die Eingabe reagiert.
readStringUntil('\n') wäre hier evtl. die bessere Wahl, funktioniert
aber natürlich nur, wenn man im Terminal das Zeilendezeichen passend
eingestellt hat.
Gast
#6384259
Stefan ⛄ F. schrieb: >> Von Vergleichsoperatoren ist da keine Rede.... > > Weil die Doku von Arduino unvollständig ist. Aber sicher ist das dokumentiert: "The String comparison operators ==, !=,>, < ,>=, <= , and the equals() and equalsIgnoreCase() methods allow you to make alphabetic comparisons between Strings. They're useful for sorting and alphabetizing, among other things." https://www.arduino.cc/en/Tutorial/StringComparisonOperators leo Ich experimentierte auch mit malloc und free was aber den Speicher fragmentiert, somit entschied ich mich für konstante kurze Buffer als globale Variablen. Eine Garbage Collection wie beim CBM fand ich nicht! https://de.wikipedia.org/wiki/Garbage_Collection Stefan ⛄ F. schrieb: > Auch damit wechselst du zwischen C und C++., was unnötige Konvertierung > erfordert und den eigenen Quelltext schlechter lesbar macht. Da ein Arduino-String (wie auch std::string) ein ganz gewöhnlicher C-String mit ein paar zusätzlichen Methoden ist, findet überhaupt keine Konvertierung statt. Und was ich schrieb, sieht zwar wie C aus, ist aber C++ - weil C++ (fast) ein Superset von C ist. Ob es besser lesbar oder nicht, darüber lässt sich streiten. Und ja, du hast nach weiteren C-artigen Lösungen gefragt, also habe ich eine gegeben (ich widerspreche dir nur, dass es ein "falscher" Hinweis ist). :-)
Gast
#6384311
Yalu X. schrieb: > Sendet man den String mit einem gewöhnlichen Terminalprogramm, muss man > die Zeichen zügig eintippen, um zu vermeiden, dass der Timeout schon vor > dem Ende der Eingabe zuschlägt. der gemeine Arduino User wird auch nicht unbedingt das Verlangen haben, andere Terminal/Monitorprogramme zu benutzen. Bei externen Programmen muss man nämlich immer erst den Port zumachen bevor ein neues Programm geladen werden kann, es wird ja üblicherweise die selbe serielle Schnittstelle benutzt. Davon ab können aber viele alternative Programme auch eine Zeile am Stück oder per Makro Sequenzen auf Knopfdruck senden, das gute alte Br@y Terminal mal als Beispiel. Terminal Emulationen sind eher selten, seit MS kein Hyperterminal mehr mit ausliefert kenn das keiner mehr :) Johannes S. schrieb: > der gemeine Arduino User wird auch nicht unbedingt das Verlangen haben, > andere Terminal/Monitorprogramme zu benutzen. oh ich bin ein ungemeiner User? Ich nutze meine Arduino Projekte auch auch abgesetzt von der IDE und mache Terminal Programme auf um das Modul zu steuern, Uhrzeit Datum der RTC korrigieren, automatische Rolladen Zeiten anzupassen, oder Rolladen manuell fernzusteuern. Die Rolläden werden per 433 MHz fernbedient, auch mal Funksteckdosen, oder meine wordclock12h per wUSB. Wenn ich die umprogrammieren will nutze ich wUSB oder sharkoon 100/400 USB Server im LAN über die Ardunio IDE, was aber sehr selten ist das die SW im Wesentlichen steht.
Gast
#6384487
Arduino Fanboy D. schrieb: >> Auch damit wechselst du zwischen C und C++., >> was unnötige Konvertierung erfordert > Das passiert nur in deinem Kopf. Das mag sein. Du siehst: Es macht den Quelltext für mich schwieriger lesbar. Deswegen ist er nicht falsch oder schlecht. ich wollte nur sagen, dass es nicht mein Stil ist und eine Alternative vorschlagen. Yalu X. schrieb: > Zu dem Code wäre noch anzumerken, dass auch readString() ... > als einziges Kriterium für das String-Ende einen Timeout verwendet. Wie bei den HC-06 Modulen. Wer hat sich da wohl von wem inspirieren lassen? Sage mal kann es sein, dass Serial.readString() unf readStringUntil() beliebig viele Zeichen einliest? Ich hatte das Problem mal mit einem ESP8266 auf einem IP Socket, da schmierte mir der Chip immer ab, wenn die Strings länger als 5kB wurden. Vermutlich wegen Stack-Überlauf.
Gast
#6384489
leo schrieb: > Aber sicher ist das dokumentiert: > https://www.arduino.cc/en/Tutorial/StringComparisonOperators Ach guck mal, danke! Ich habe das direkt im Artikel der String Klasse erwartet.
Gast
#6384506
Stefan ⛄ F. schrieb: > leo schrieb: >> Aber sicher ist das dokumentiert: >> https://www.arduino.cc/en/Tutorial/StringComparisonOperators > > Ach guck mal, danke! Ich habe das direkt im Artikel der String Klasse > erwartet. Das ist jetzt schon mehrfach aufgekommen. Dabei steht das doch klar und deutlich in der Dokumentation unter https://www.arduino.cc/reference/en/language/variables/data-types/stringobject/
Gast
#6384514
Da steht es aber nicht: https://www.arduino.cc/reference/de/language/variables/data-types/string/ Und da auch nicht: https://www.arduino.cc/reference/en/language/variables/data-types/string/ Über wie viele Artikel haben die denn die Doku dieser einen Klasse verstreut? Ich werde bekloppt! Nee, bin ich schon. Ich habe ich daran gewöhnt, mit den Quelltexten zu arbeiten. Die sind überwiegend gut strukturiert und kommentiert. Stefan ⛄ F. schrieb: > Über wie viele Artikel haben die denn die Doku dieser einen Klasse > verstreut? ich hadere auch mit der Doku, aber egal es geht auch anders! Stefan ⛄ F. schrieb: > Da steht es aber nicht: > https://www.arduino.cc/reference/de/language/variables/data-types/string/ > > Und da auch nicht: > https://www.arduino.cc/reference/en/language/variables/data-types/string/ Das ist die Beschreibung der C-Strings, d.h. char-Arrays. Die String-Klasse schreibt sich mit einem großen S und wird in einem eigenen Kapitel beschrieben.
Gast
#6384527
Yalu X. schrieb: > Das ist die Beschreibung der C-Strings, d.h. char-Arrays. Nein. S. e.g. operators
Gast
#6384528
Stefan ⛄ F. schrieb: > Da steht es aber nicht: > https://www.arduino.cc/reference/de/language/variables/data-types/string/ > > Und da auch nicht: > https://www.arduino.cc/reference/en/language/variables/data-types/string/ > > Über wie viele Artikel haben die denn die Doku dieser einen Klasse > verstreut? Ich werde bekloppt! > > Nee, bin ich schon. > > Ich habe ich daran gewöhnt, mit den Quelltexten zu arbeiten. Die sind > überwiegend gut strukturiert und kommentiert. 2ter & 3ter Satz im ersten Link:
Inklusive Link zur Doku der String-Klasse. Was will man mehr? Im zweiten Link steht das gleiche auf englisch (wie zu erwarten, da es die englische Version der gleichen Seite ist)
Gast
#6384712
Ich verwende erfolgreich in der Loop folgenden Code: (gekürzt aufs Nötigste)
Gast
#6384726
Chregu schrieb: > Ich verwende erfolgreich in der Loop folgenden Code: > (gekürzt aufs Nötigste) Offenbar zu viel gekürzt. Wenn der String länger ist, als der Puffer, stürzt das Ding ab. Arduino Fanboy D. schrieb: > Schwer vorstellbar, dass du damit überfordert bist. Oh bitte, ich habe mir diese Spielzeugsprache gut 2 Stunden angesehen - und das hat mir gereicht. Arduino Fanboy D. schrieb: > Schwer vorstellbar, dass du damit überfordert bist, den richtigen Ort zu > finden, und die Buffergröße nach Wunsch einzustellen. #IchhabBessereszutun Jede vernünftige Seriel-Lib hat eine Möglichkeit, die Buffergröße einfach zu setzen, ohne im Code der Lib rumkrauchen zu müssen. Gerade bei Arduino ist das essentiell, weil sonst einfach der Stack überschrieben wird. Chregu schrieb: > Ich verwende erfolgreich in der Loop folgenden Code: > (gekürzt aufs Nötigste) Oh Glückwunsch. Ich mein, warum macht man sowas? Fehlerhafte Masseanbindung, falsche Baudrate, abweichender Baudratenquarz, falsch eingestelltes Terminal - oder eine Faxsoftware die nach einem Modem sucht... es gibt so viele Möglichkeiten einen RS232 mit falschen Daten zu fluten - und dabei jedesmal den Stack ins Nirwana zu schicken. Nur weil man sich eine Buffer Overflow oder String Overflow Prüfung sparen will. Stefan ⛄ F. schrieb: > Offenbar zu viel gekürzt. Wenn der String länger ist, als der Puffer, > stürzt das Ding ab. eben if(isprint(incomingByte)) { if(chr_cnt<(MAXBUFFER-2)) serial_in_buff[chr_cnt++] = incomingByte; else { Serial.println(F("serBUF ov-> DEL")); memset(&serial_in_buff[0], 0, sizeof(serial_in_buff)); memset(&serial_in_command[0], 0, sizeof(serial_in_command)); chr_cnt=0; } // if !(chr_cnt<(MAXBUFFER-2)) } // if(isprint(incomingByte))
Gast
#6385062
Karl K. schrieb: > Oh bitte, ich habe mir diese Spielzeugsprache gut 2 Stunden angesehen - > und das hat mir gereicht. C++ ist also eine "Spielzeugsprache"? Alles klar.... Keine Fragen mehr. Karl K. schrieb: > Jede vernünftige Seriel-Lib hat eine Möglichkeit, die Buffergröße > einfach zu setzen, ohne im Code der Lib rumkrauchen zu müssen. > > Gerade bei Arduino ist das essentiell, weil sonst einfach der Stack > überschrieben wird. Irrational! Wie du auf solche Ideen kommst, ist mir ein Rätsel. Die 2 Stunden haben offensichtlich nicht gerecht, für ordentliche Argumente. Arduino Fanboy D. schrieb: > C++ ist also eine "Spielzeugsprache"? Ich bin mir ziemlich sicher dass du weißt, ich meine damit das was unter Arduino drauß gemacht wurde. Aber bitte, wenn C++ so toll ist, warum wurde dann Rust entwickelt? Heise bringts aktuell mal wieder gut auf den Punkt: https://www.heise.de/hintergrund/Entwicklung-Warum-Rust-die-Antwort-auf-miese-Software-und-Programmierfehler-ist-4879795.html Stefan ⛄ F. schrieb: > S. R. schrieb: >> Ich werfe folgendes in den Raum: >> if (strncmp(befehl.c_str(), "ein", 3) == 0) {...} > > Auch damit wechselst du zwischen C und C++., was unnötige Konvertierung > erfordert und den eigenen Quelltext schlechter lesbar macht. > > Besser wäre in diesem Fall: > > if (befehl.indexOf("ein")==0) {...} String::indexOf hat 2 Overloads. Eins für char, also Einzelzeichen und eins für String, aber kein Overload für "const Char *", das funktioniert nur, weil einen nicht-expliziten Konstructor für String gibt, der aus "const char *" einen String macht. Und dabei wird erst mal ein neuer String angelegt (auf dem Heap). "small string optimization", wie es in "kompletten" C++-Libs zu finden ist, gibt es nicht, also werden für "ein" 3 Bytes allokiert. Ist natürlich mit 64Bit Ptr/Länge/Kapazität, also 24Byte Verwaltungdaten einfacher da notfalls den Inhalt direkt reinzuschreiben, als beim AVR mit nur 6Byte. Der String::operator==() hat ein Overload für "const char *" und kommt ohne temporären String aus. Und das eigentliche Problem waren ja das/die Whitespace(s) am Ende des Befehls. Allerdings kann man String leicht um fehlendes erweitern:
Bei String ist das offensichtlich vorgesehen, da alle internen Daten/Methoden protected sind, also für Ableitungen sichtbar.
Gast
#6385150
Karl K. schrieb: > Aber bitte, wenn C++ so toll ist, warum wurde dann Rust entwickelt? Oder python? Oder C#? oder Basic? Mich erinnert Rust an Pascal. Meist werden neue Programmiersprachen entwickelt, weil jemand "zu doof oder zu faul" für die herkommlichen ist oder sie etwas "Modernes" nicht einfach so unterstützen (GUI-Programmierung in C auf einem Windows-Rechner war damals ziemlich aufwendig). Oder sie einfach als alt und unmodern ("nicht mehr hip") angesehen werden.
Gast
#6385191
Karl K. schrieb: > Aber bitte, wenn C++ so toll ist, warum wurde dann Rust entwickelt? Rust wurde für Projekte gemacht, die Hosenträger + Gürtel brauchen.
Gast
#6385295
Stefan ⛄ F. schrieb: > Karl K. schrieb: >> Aber bitte, wenn C++ so toll ist, warum wurde dann Rust entwickelt? > > Rust wurde für Projekte gemacht, die Hosenträger + Gürtel brauchen. Der Kollege Karl hat schon lange eingesehen, dass seine Argumente an den Haaren herbei gelogen sind. Anstatt sich auf einen Dialog einzulassen, greift er zum Mittel, welches sich auf Neudeutsch "whataboutism" nennt. Oder einfach nur "Nebelkerzen". Karl K. schrieb: > Ich bin mir ziemlich sicher dass du weißt, ich meine damit das was unter > Arduino drauß gemacht wurde. Ja! Ich denke schon... C++ ist C++, und die Arduino Entwickler haben das nicht verändert. Es ist ok, wenn du C++ nicht magst. Es ist auch ok, wenn dir Arduino nicht schmeckt. Aber was mir nicht schmeckt, ist dein Arduinobashing mit solchen Scheinargumenten/Nebelkerzen/Lügen. Von mir aus können wir beide uns gerne sachlich über Arduino und die Zusammenhänge unterhalten. Oder es auch sein lassen...... Stefan ⛄ F. schrieb: > Rust wurde für Projekte gemacht, die Hosenträger + Gürtel brauchen. Klar, wir lieben sie doch alle: Die Angriffe, weil die Länge der Url im Eingabefeld nicht begrenzt ist - und ausführbarer Code in den Speicher geschrieben wird. Oder nicht sichtbare Zeichen, die dann Speicherbereiche überschreiben. Sowas gab es vor 25 Jahren - und sowas gibt es heute immer noch. Soviel zu STK500-Besitzer schrieb: > Meist werden neue Programmiersprachen entwickelt, weil jemand "zu doof > oder zu faul" für die herkommlichen ist Ja, weil viele Programmierer sich absurd überschätzen und glauben nur die anderen machen Fehler. Siehe oben: Auf Buffer Overflow prüfen brauch ich nicht, ich schick ja immer nur 3 Zeichen. Und dann rumheulen, wenn man tagelang einen Fehler nicht findet, der µC schon immer abstürzt bevor man überhaupt zum Testen kommt - weil der Stack überschrieben wird. Weil man ein if sparen wollte. Karl K. schrieb: > Und dann rumheulen, wenn man tagelang einen Fehler nicht findet, der µC > schon immer abstürzt bevor man überhaupt zum Testen kommt - weil der > Stack überschrieben wird. Weil man ein if sparen wollte. ist leider so musste ich auch erst lernen, deswegen kommt nach Serial.begin erst mal Mist auslesen! Serial.begin(19200); // while(Serial.available()) // Serial.read(); Serial.flush(); offensichtlich steht schon vorher was im Empfangsbuffer, woher? keine Ahnung denn ich sende vorher ja nichts, kann also Einstrahlung sein! Das betrifft bei mir übrigens mehrere AVR, auch der NETIO von Pollin hat mit Arduino nichts zu tun! Das führt am NETIO mit Radig SW regelmäßig zu einem Pufferüberlauf! Die habe ich aber nie angepasst und dürfte auch nie den Pufferüberlauf prüfen oder gar auf isprint testen! Arduino Fanboy D. schrieb: > Aber was mir nicht schmeckt, ist dein Arduinobashing mit solchen > Scheinargumenten/Nebelkerzen/Lügen. Oh bitte, lern erstmal Datentypen. Beitrag "AVR Inline Optimierung kaputt?" Genau diese Scheisse. Immer wieder. Seit zig Jahren. Und wird verteidigt bis aufs Messer. Joachim B. schrieb: > offensichtlich steht schon vorher was im Empfangsbuffer, woher? Ein AVR liefert gern erstmal ein $00 einfach durch den Pegelwechsel beim Einstecken, weil am Uart ein Startbit erkannt wird. Je nachdem ob die Uart Fehlerbits ausgewertet werden, landet das dann im Buffer. Andere Gründe hab ich oben schon genannt, alles erlebt. Und nur deswegen unkritisch - weil man sich halt als Erstes Gedanken macht wie man Daten so behandelt, dass der Controller nicht dadurch lahmgelegt wird. Ich mein, dass ist seit zig Jahren Praxis, aber dennoch schlagen immer wieder Leute auf, die meinen es besser zu wissen. Und wiederholen die Fehler von vor zig Jahren. Karl K. schrieb: > Beitrag "AVR Inline Optimierung kaputt?" > > Genau diese Scheisse. Immer wieder. Seit zig Jahren. Und wird verteidigt > bis aufs Messer. Naja, Thema war dort schlussendlich Undefined Behaviour (UB). Davon kann sich Rust auch nicht freisprechen: https://doc.rust-lang.org/reference/behavior-considered-undefined.html C ist darauf optimiert, - schnell zu sein - auf möglichst vielen Plattformen zu laufen Beides kann man nur unter einen Hut bekommen, wenn man einiges schlichtweg als UB deklariert. Frank M. schrieb: > Naja, Thema war dort schlussendlich Undefined Behaviour (UB). Davon kann > sich Rust auch nicht freisprechen: Ja, aber wenn Du den Artikel bei Heise gelesen hättest, würdest Du verstehen: UB ist bei C(++) Standard, bei Rust muss man es wollen. Du kannst mit Rust alle Fehler machen, die Du auch mit C(++) machen kannst. Aber eben nicht aus Versehen, sondern weil Du es willst. Frank M. schrieb: > C ist darauf optimiert, > - schnell zu sein > - auf möglichst vielen Plattformen zu laufen Ich hab mal ne Weile Ada programmiert, das erzeugte asm-Listing für AVR war nicht viel anders als von C für gleiche Funktionen. Wie schnell ein Programm am Ende ist hängt nicht davon ab, wie sehr Dir der Kompiler auf die Finger haut. Karl K. schrieb: > Ich hab mal ne Weile Ada programmiert, das erzeugte asm-Listing für AVR > war nicht viel anders als von C für gleiche Funktionen. Wie schnell ein > Programm am Ende ist hängt nicht davon ab, wie sehr Dir der Kompiler auf > die Finger haut. Einfaches Beispiel: C/C++ reduziert den Ausdruck
einfach zu x. Das kann Rust nicht so einfach machen, weil hier ein etwaiger Überlauf zu berücksichtigen ist. Aber okay, der Anspruch, auf möglichst vielen Plattformen zu laufen, wirkt da vermutlich schwerer. Rust garantiert zum Beispiel bei Integer-Overflows ein Wrapping mit 2er Komplement im Release-Mode (Panic im Debug-Mode). Wenn das eine CPU nicht kann, muss der Rust-Compiler per Code nachhelfen. Dem C-Compiler ist das vollkommen egal, für ihn ist der Overflow von Signed Integers einfach UB, fertig. Und so kann ich mir auch andere Beispiele vorstellen, wo die Portierung von Rust auf eine andere CPU durchaus mehr Arbeit machen kann als die Portierung eines C-Compilers. Interessante Lektüre: http://huonw.github.io/blog/2016/04/myths-and-legends-about-integer-overflow-in-rust/
Gast
#6385670
Karl K. schrieb: > Du kannst mit Rust alle Fehler machen, die Du auch mit C(++) machen > kannst. Aber eben nicht aus Versehen, sondern weil Du es willst. Die Rust Regeln können einen stark einschränken, wie man etwas lösen kann. Dann kann es viele einfache Lösungen geben, aber nutzt man die, statt das halbe Programm neu zu designen, ist es "es falsch machen wollen". Ich bezweifle mal stark, dass das immer zu gutem Programmdesign führt. Ausserdem, werden Stack overflows in ach so safem Rust Code mittlerweile endlich im vornherein abgefangen? Ich sag nur Box::new([-1; 3000000]). So viel zum Thema Rust und Fehlersicherheit...
Gast
#6385674
Karl K. schrieb: >> Rust wurde für Projekte gemacht, die Hosenträger + Gürtel brauchen. > > Klar, wir lieben sie doch alle: Die Angriffe, weil die Länge der Url im > Eingabefeld nicht begrenzt ist - und ausführbarer Code in den Speicher > geschrieben wird. Oder nicht sichtbare Zeichen, die dann > Speicherbereiche überschreiben. > > Sowas gab es vor 25 Jahren - und sowas gibt es heute immer noch. Genau. Manche Projekte brauchen eher Sicherheit als Performance, und da macht Rust Sinn. Karl K. schrieb: > Aber bitte, wenn C++ so toll ist, warum wurde dann Rust entwickelt? Weil "Fortschritt" erstmal einen "Schritt" braucht. Ob der nach vorne, zur Seite oder sogar nach hinten geht, lässt sich vorher oft nicht vorhersehen. Es ist heutzutage erstaunlich einfach, mal eben schnell eine Programmiersprache aus dem Boden zu stampfen... und es gibt viele davon.
Gast
#6386161
S. R. schrieb: > Ob der nach vorne, zur Seite oder sogar nach hinten geht, lässt sich > vorher oft nicht vorhersehen. Ist auch eine Frage des Anwendungsfalls. Die Möglichkeit, sehr dünne Scheiben herzustellen, ist zum Beispiel für Smartphones eine gute Sache, aber für Fensterscheiben nutzlos.
Gast
#6386221
Stefan ⛄ F. schrieb: > Die Möglichkeit, sehr dünne Scheiben herzustellen, ist zum Beispiel für > Smartphones eine gute Sache, aber für Fensterscheiben nutzlos. Dünne Scheiben sind auch beim Smartphone eine schlechte Sache, wenn sie bei jeder Erschütterung einen Sprung bekommt. Bei meinen Fenstern wären dünnere Scheiben praktisch, da das Gewicht der Dreifachverglasung ein echtes Problem ist. Stefan ⛄ F. schrieb: > Die Möglichkeit, sehr dünne Scheiben herzustellen, ist zum Beispiel für > Smartphones eine gute Sache, aber für Fensterscheiben nutzlos. Mehrscheiben-Sicherheitsglas. Bruchsicheres Vitrinenglas. Ein Bekannter hat jahrelang Fenster eingebaut - und wäre über dünnere und damit leichtere Scheiben sehr erfreut gewesen. Man denkt ja häufig nur nicht über seinen Tellerrand hinaus... 🐧 DPA 🐧 schrieb: > So viel zum Thema Rust und Fehlersicherheit... Du hast offenbar das Problem nicht verstanden: Es wird nicht behauptet, dass Rust eine fehlerfreie Programmiersprache wäre. Es geht darum, dass man bei Rust typische Fehler nur machen kann, wenn man die Sicherheit ABschaltet. Während man bei C(++) um diese Fehler sicher auszuschließen die Sicherheit EINschalten muss. so gehts String befehl; void setup() { Serial.begin(9600); pinMode(LED_BUILTIN, OUTPUT); } void loop() { if(Serial.available() > 0){ befehl = Serial.readString(); } befehl.trim(); if(befehl == "ein"){ digitalWrite(LED_BUILTIN, HIGH); Serial.println("ein"); }else if(befehl == "aus"){ digitalWrite(LED_BUILTIN, LOW); Serial.println("aus"); } befehl = ""; } Vielleicht ist der gelesene String länger? Um ein CR und/oder LF vielleicht? Dann funktioniert Vergleich auf Identität nicht. LG Jochen
Soweit waren wir schon am 25.08.2020. befehl.trim() hat's behoben, auch wenn die Arduino-Dokumentation auf Deutsch behauptet, es entfernt nur Leerzeichen: es arbeitet wie in der Englischen Dokumentation beschrieben und entfernt "Whitespace". Antwort schreibenBitte melde dich an, um einen Beitrag zu schreiben. |
Anzeige
|