Hallo,
ich möchte an den Arduino über einen PC daten senden und diese
entsprechend auswerten.
Es soll z.B. P13_ON vom pc gesendet werden, worauf der Arduino Pin 13
einschaltet.
Ich habe auch schon ein Programm für den Arduino geschrieben, nur leider
reagiert es nur auch einstellige befehle, also 0-9, oder a-z.
Wie muss ich meine Variable deklarieren dass ich wörter auswerten kann?
Hier mein Code, der auch funktioniert, nur will ich halt statt 1 oder 0
P13_ON bzw. P13_Off senden.
max2d schrieb:> Ich habe auch schon ein Programm für den Arduino geschrieben, nur leider> reagiert es nur auch einstellige befehle, also 0-9, oder a-z.> Wie muss ich meine Variable deklarieren dass ich wörter auswerten kann?
Dann lies mal in deinem C++ oder C Buch im Kapitel über 'String' nach.
@ Karl Heinz (kbuchegg) (Moderator)
>Dann lies mal in deinem C++ oder C Buch im Kapitel über 'String' nach.
Oder ein Buch über Quantenphysik, Kapitel "Stringtheorie" ;-)
Über einen Kommunikationskanal, hier die serielle werden oft "nur
einstellige Befehle" übertragen. Macht aber nix... Man überlegt sich ein
Protokoll, oder benutzt ein bestehendes.
Einzelne Befehle werden dann z.B. zu Nachrichten/Messages
Vorteilhaft sind fixe Start und Endmarkierungen.
Z.B: #PxxE+
Könnte heißen # start
P Port
xx Portnummer
E ein, oder A aus
und + Ende
Nun liest du am uc die Einzelbefehle und speicherst sie in einem array,
oder du fütterst gleich eine Statemachine damit, die das Zeichen
verarbeitet.
So wie, wenn # dann start, dann muss P kommen usw... wenn die message
fertig ist port schalten.. wenn dazwischen # wieder von vorne.
embrio schrieb:> Hab mal wieder zu schnell abgesendet.>> Die String-Deklaration muss 'String' nachtürlich groß geschrieben werden> (zumindest in der Arduino-IDE):>
1
String cmd;
>>> und am Ende vom Code fehlt noch ein '}'
Dein gesamter Code funktioniert nicht, er wird zwar fehlerfrei
Übertragen, jedoch bleibt dieser ohne funktion
K. M. H. schrieb:> Dein gesamter Code funktioniert nicht, er wird zwar fehlerfrei> Übertragen, jedoch bleibt dieser ohne funktion
Ohne Funktion ist er sicher nicht. Nur ist sowas
1
if(Serial.available()>0){
2
inth=Serial.available();
3
4
for(inti=0;i<h;i++){
5
cmd+=(char)Serial.read();
6
}
7
}
dann halt schon etwas naiv programmiert. Da muss alles 100% klappen.
Beim kleinsten Fehler kommt dieses 'Protokoll' nie wieder auf die
'Füsse'.
Mir ist schon klar, dass nach der Möglichkeit der Übertragung von
Wörtern gefragt war. Und das erfüllt dieser Code eindeutig. Nur gibt es
bei Übertragungen noch mehr, worauf man achten muss. Aber im Grunde
stimmt es schon: Ein Wort wird übertragen, indem man Buchstabe für
Buchstabe überträgt. Klarerweise muss es einen Mechanismus ergeben, mit
dem der Empfänger feststellen kann, dass ein Wort zu Ende ist. Da gibt
es mehrere Möglichkeiten, von denen die Vorab-Übertragung der Wortlänge
sicherlich eine ist.
Am besten Du packst das Ganze in ein einfaches Protokoll.
Also z.B. Jeder Befehl besteht aus ???? gefolgt von einem Zeilenumbruch.
Deine Empfangsroutine empfängt dann "endlos" bis ein Zeilenumbruch
vorbeikommt. Natürlich kann es an dieser Stelle nicht schaden ein paar
Überprüfungen der Zeichen und der Anzahl zu machen.
Das Zeilenende Zeichen kannst Du zum Start der Erkennung der
Zeichenfolge nutzen.
Ab hier gibt es zwei Möglichkeiten:
1. Du zerlegst die Zeichenketten in z.B. "P", "13", "_" und "ON".
Damit erschlägst Du Ähnlichkeiten wie: "P", "8", "_" und "ON".
oder "P", "13", "_" und "OFF".
2. Du legst feste Zeichenketten im FLASH ab und nutzt die
Vergleichsfunktionen, die C bietet
ist natürlich ziemlicher Unsinn. Man kann nicht davon ausgehen, dass dem
Programm mittels 'available' die Wortlänge zugespielt wird. In den
meisten Fällen wird das nicht der Fall sein. 'available' erlaubt
lediglich eine Aussage darüber, wieviele Zeichen zum Zeitpunkt des
Funktionsaufrufs bereits übertragen wurden. Aber das müssen ja beileibe
nicht alle sein. available interessiert sich ja nicht dafür, ob der
Sender noch Zeichen hat, die er übertragen möchte, die also noch gar
nicht auf dem Arduino eingelangt sind. Datenübertragung benötigt Zeit!
Und zwar wesentlich mehr Zeit als Rechenarbeit. Der Ardunio wird also
viele tausend male drauf kommen, dass 0 Zeichen übertragen wurden,
unterbrochen von ein paar einzelnen Fällen, in denen 1 Zeichen
übertragen wurde. Warum? Weil der Rest des Wortes (die restlichen
Buchstaben) vom Sender noch gar nicht auf die Leitung gegeben wurde.
Karl Heinz schrieb:> Ohne Funktion ist er sicher nicht. Nur ist sowas> ...> dann halt schon etwas naiv programmiert.
Nein, ich als Arduino-Programmierer sage:
Der Code ist völlig ohne Funktion.
Ein Code nach der Logik
1
if(Serial.available()>0){
2
// Verarbeite ganz viele Zeichen
3
}
ist direkt zum Scheitern verurteilt. Damit kann immer nur genau ein
einziges Zeichen verarbeitet werden, so wie er es macht.
Einen anfängergeeigneten Einlesecode für serielle Befehle unter Arduino
kann man so machen:
1
if(Serial.available()>0){
2
delay(25);
3
while(Serial.available()>0){
4
// Verarbeite bis zu 25 Zeichen
5
}
6
}
Wenn das Protokoll dann so aussieht, dass zwischen den einzelnen
"Befehlen" immer Sendepausen sind, sorgt man mit dem "delay(25)" nach
dem Empfang des ersten Zeichens dafür, dass noch weitere Zeichen im
seriellen Eingangspuffer eintreffen. Nach Ablauf von 25 Millisekunden
kann man diese Zeichen dann aus dem seriellen Eingangspuffer in einem
Rutsch weg verarbeiten.
Der weiter oben gepostete Code ist ziemlich daneben.
Die unter Arduino möglichen "String-Objekte" wie bei seiner Variablen
"cmd" verwendet man üblicherweise nicht einmal als
Arduino-Programmierer, da diese String-Objekte zum Rest der Libraries
vollkommen inkompatibel sind, und zwar sowohl zur AVR libc Library als
auch zu fast allen Funktionen der speziellen Arduino-Libraries.
> Einen anfängergeeigneten Einlesecode für serielle Befehle unter Arduino> kann man so machen:>
1
>if(Serial.available()>0){
2
>delay(25);
3
>while(Serial.available()>0){
4
>// Verarbeite bis zu 25 Zeichen
5
>}
6
>}
7
>
Also mein Programm sieht jetzt wie folgt aus:
1
if(Serial.available()>0)
2
{
3
delay(25);
4
5
while(Serial.available()>0)
6
{
7
if(Serial.read)==='13On')
8
{
9
led=true;
10
}
11
}
12
13
}
Leider tut sich nichts. Muss ich also doch noch was ändern? Also in
einen String schreiben wobei:
> Die unter Arduino möglichen "String-Objekte" wie bei seiner Variablen> "cmd" verwendet man üblicherweise nicht einmal als> Arduino-Programmierer, da diese String-Objekte zum Rest der Libraries> vollkommen inkompatibel sind, und zwar sowohl zur AVR libc Library als> auch zu fast allen Funktionen der speziellen Arduino-Libraries.
mir ja was anderes sagt.
Jürgen S. schrieb:> Einen anfängergeeigneten Einlesecode für serielle Befehle unter Arduino> kann man so machen:>
1
>if(Serial.available()>0){
2
>delay(25);
3
>while(Serial.available()>0){
4
>// Verarbeite bis zu 25 Zeichen
5
>}
6
>}
7
>
>> Wenn das Protokoll dann so aussieht, dass zwischen den einzelnen> "Befehlen" immer Sendepausen sind,
Ich will dir nicht zu nahe treten, aber das ist immer noch Quatsch.
In dem Moment, in dem eine serielle Übertragung auf Sendepausen zur
Synchronisierung beruht, ist das nicht mehr anfängertauglich.
Nicht ohne Grund wird seit Urzeiten auf jedem Keyboard die
'Return'-Taste verbaut, mit der man dem Rechner andeutet "Ich habe meine
Eingabe fertig, jetzt bist du dran, sie auszuwerten".
Das ist auch für einen Anfänger der vernünftigste Weg: Jede Übertragung
wird mit einem speziellen Zeichen als "Jetzt ist alles fertig
übertragen" markiert. Ob das dann 'Return' ist, oder irgendein anderes
Zeichen, welches normalerweise nicht vorkommt (HPGL verwendet zb einen
';' um ein Kommando zu begrenzen), darüber kann man diskutieren. Aber
nicht über die grundsätzliche Vorgehensweise, wenn Kommandos in Textform
übertragen werden.
max2d schrieb:> Also mein Programm sieht jetzt wie folgt aus:>
1
>
2
>if(Serial.available()>0)
3
>{
4
>delay(25);
5
>
6
>while(Serial.available()>0)
7
>{
8
>if(Serial.read)==='13On')
9
>{
10
>led=true;
11
>}
12
>}
13
>
14
>}
15
>
>> Leider tut sich nichts.
Das wundert mich nicht. Das compiliert noch nicht einmal.
Dieser Code ist sowohl aus Sicht der Behandlung der UART Unsinn, als er
auch aus ganz banaler C-Syntaxsicht Unsinn ist. Tu dir selbst einen
Gefallen und kauf dir ein C-Buch (oder ein C++-Buch) und arbeite das
erst mal auf einem PC durch. Solange du wesentliche Sprachelemente von C
(bzw. C++) nicht sicher anwenden kannst und einfache 'Algorithmen'
umsetzen kannst, hat das doch keinen Sinn. Ich schreib 'Algorithmen'
absichtlich in Hochkomma, weil das ja eigentlich noch kein wirklicher
Algorithmus ist, der irgendwie schwer ist. Das ist einfach nur: sammle
Zeichen, bis die Endekennung kommt und wenn die da ist, dann werte die
gesammelten Zeichen (vulgo: den String) aus, wobei dir die C++ Klasse
'string' schon mal einen Löwenanteil der tatsächlich schwierigen Arbeit,
nämlich das Verwalten des Speichers in dem Zeichen gesammelt werden,
abnimmt. Egal ob das jetzt auf einem kleinen Arduino für den µC
Schwerarbeit ist oder nicht, für dich als Anfänger ist das erst mal eine
große Hilfe, also benutze sie auch.
Aus dem Vorschlag von embrio kann man sich schon einiges herleiten bzw.
ansehen. Wenn auch die Logik etwas verquert ist.
Und lös dich von der Vorstellung, dass irgendwie magisch dein 'Wort' in
einem Rutsch übertragen wird. Dein 'Wort' wird ganz normal Buchstabe für
Buchstabe übertragen. Dein Arduino Programm muss die Buchstaben wieder
zusammensetzen, bis die Kennung kommt 'Wort zu Ende'. Danach kann die
übertragene Zeichenkette ausgewertet werden. Ja, nicht für alles gibt es
auf dem Arduino fertige Funktionen, die man einfach nur aufrufen
braucht. Manchmal muss man doch tatsächlich richtig programmieren.
1
stringcmd;//Befehlsbuffer
2
3
voidloop()
4
{
5
charnextChar;
6
7
if(Serial.available()>0){
8
9
nextChar=Serial.read();
10
11
Serial.print("Zeichen: '");
12
Serial.print(nextChar);
13
Serial.print("'\n");
14
15
if(nextChar==';'){
16
Serial.print("Kommando vollständig '");
17
Serial.print(cmd);
18
Serial.print("'\n");
19
20
if(cmd=="LEDon")
21
digitalWrite(led,HIGH);
22
elseif(cmd=="LEDoff")
23
digitalWrite(led,LOW);
24
25
26
cmd="";
27
}
28
29
else{
30
cmd+=nextChar;
31
32
Serial.print("Kommando bis jetzt ");
33
Serial.print(cmd);
34
Serial.print("\n");
35
}
36
}
37
}
Noch ein Tip (der im Code schon ein wenig eingearbeitet ist): Um das
Stochern im Dunkeln zu vermeiden, was denn eigentlich der µC macht, ist
es ab und an ganz hilfreich, wenn man sich einfach mal ein paar Dinge
ausgeben lässt, damit man am Terminal sieht, was der µC empfangen hat
und was er mit dem Zeichen anstellt.
Im obigen hab ich ein ';' als Trennzeichen benutzt. Kommandos werden
also zb. in der Form
1
LEDon;LEDoff;
eingegeben, wobei der ';' das Ende der Eingabe markiert. Du kannst auch
jedes andere Trennzeichen benutzen (zb einen '\n'). Aber um Probleme mit
der Carriage_Return / Line_Feed Problematik zu vermeiden, hab ich der
Einfachheit halber erst mal einen ';' gewählt.
max2d schrieb:> Also mein Programm sieht jetzt wie folgt aus:>
1
>
2
>if(Serial.available()>0)
3
>{
4
>delay(25);
5
>
6
>while(Serial.available()>0)
7
>{
8
>if(Serial.read)==='13On')
9
>{
10
>led=true;
11
>}
12
>}
13
>
14
>}
15
>
>> Leider tut sich nichts. Muss ich also doch noch was ändern?
Damit es einen gruselt, brauchst Du nichts ändern. Es IST GRUSELIG!
Damit es funktioniert, mußt Du mehrere Dinge ändern.
Du hast extreme Defizite, selbst für einen Anfänger mit
C/C++-Programmierung.
Erstens hast Du nicht verstanden, wie man eine Funktion aufruft:
Wenn Du im Code schreibst "Serial.read", dann ist das die Adresse im
RAM, wo die Funktion liegt. Wenn Du die Funktion aufrufen und ausführen
möchtest, gehören die Parameter in Klammern dahinter, auch wenn die
Parameterliste leer ist. Also Funktionsaufruf mit "Serial.read()".
Als nächstes sind Dir offenbar die Variablentypen und Objekte vollkommen
unklar, mit denen Du hantierst. Eine char-Variable ist ein einzelnes
Zeichen, und einzelne Zeichen stehen in einzelnen Hochkommas!
Was machst Du? '13On' ist kein einzelnes Zeichen.
Einzelne Zeichen wären '1' oder '3' oder 'n' oder sowas.
Strings stehen dagegen zwischen DOPPELTEN HOCHKOMMAS.
Eine Stringkonstante sieht im Quelltext daher aus wie "13On" zwischen
doppelten Hochkommas.
Dir fehlt es an den allerkleinsten Grundlagen der Programmiersprache.
Vielleicht solltest Du mal ein Anfänger-Tutorial durcharbeiten!
Als Code für Arduino und den seriellen Monitor habe ich Dir mal das
vorbereitet:
1
Stringcmd;// ==> ein String-Objekt, der verkackteste Datentyp überhaupt!!!
2
3
voidsetup(){
4
Serial.begin(9600);
5
}
6
7
voidloop(){
8
if(Serial.available()>0)// Es ist ein Zeichen im Puffer
9
{
10
delay(25);// Warten bis alle Zeichen im Puffer
11
cmd="";
12
while(Serial.available()>0)// Alle Zeichen einzeln auslesen
13
{
14
charc=Serial.read();
15
if(c>=32)cmd=cmd+c;// Nur Zeichen mit ASCII-Code >=32
16
}
17
// Jetzt ist der empfangene String komplett und wird ausgewertet
Wenn Du mit Zeichen und Strings arbeitest, solltest Du Dir auch ein paar
Grundlagen über den ASCII-Code aneignen. Steuerzeichen und sichtbare
Zeichen.
Den seriellen Monitor von Arduino kannst Du nämlich so einstellen, dass
er nach jeder Eingabe als "Zeilenende" noch zusätzliche Steuerzeichen
sendet, die Du nicht einzugeben brauchst, und zwar CR (Zeilenumbruch)
oder NL (New Line) oder beides.
Mit diese Zeile in meinem Code:
if (c>=32) cmd=cmd+c; // Nur Zeichen mit ASCII-Code >=32
werden diese Steuerzeichen am Ende herausgefiltert und nicht in den
empfangenen String eingebaut, so dass dieser Code funktioniert, egal wie
Du den seriellen Monitor eingestellt hast, wie er das Zeilenende senden
soll, ob als CR, NL oder CR+NL.
Ach ja: Die Eingabe der Kommandos erfordert die Beachtung von Groß- und
Kleinschreibung. Wenn die Kommandos auch in Abweichender
Groß-/Kleinschreibung erkannt werden sollen, müßte man den Code etwas
ändern.
Die Auswertung nach dem Vorschlag von Karl Heinz, mit dem eindeutigen
ASCII-Zeichen als Befehlsende-Zeichen und ohne auf die vollständige
Befehlsübertragung zu warten, ist für Anfänger natürlich auch möglich.
Am besten filterst Du dann aber entweder die Steuerzeichen aus, ohne sie
in den String aufzunehmen, oder Du konfigurierst den seriellen Monitor
in Arduino so, dass keine Zeilenende-Zeichen gesendet werden. Sonst
bekommst Du nämlich bei den Debugausgaben über Serial das Problem, dass
Du die unsichtbaren Steuerzeichen nicht korrekt dargestellt bekommst.
Jürgen S. schrieb:> Die Auswertung nach dem Vorschlag von Karl Heinz, mit dem eindeutigen> ASCII-Zeichen als Befehlsende-Zeichen und ohne auf die vollständige> Befehlsübertragung zu warten, ist für Anfänger natürlich auch möglich.> Am besten filterst Du dann aber entweder die Steuerzeichen aus, ohne sie> in den String aufzunehmen,
Ich wollte es mal nicht zu kompliziert machen.
Je nachdem, wer am anderen Ende der Leitung sitzt, kann man da noch
einiges an Aufwand investieren. Vor allen Dingen, wenn ein Mensch am
anderen Ende der Leitung sitzt. Denn dann müssen vorlaufende und
nachlaufende Leerzeichen, Tabulatoren ausgefiltert werden, während sie
aber mitten im Text erhalten bleiben sollen. Und eine Behandlung von
Backspace wär auch nicht schlecht.
Alles in allem sind das aber Grundfertigkeiten, die jeder beherrschen
muss, egal ob er dann in einem realen Programm eine vorgefertigte
Parsing-Komponente benutzt oder nicht. Hier geht es einfach in erster
Linie um eine Grundtechnik. So wie jeder Mechaniker am Anfang seiner
Ausbildung den Umgang mit Säge und Feile lernt, egal ob er später dann
an einer CNC Maschine steht oder nicht.
Karl Heinz schrieb:> Ich wollte es mal nicht zu kompliziert machen.> Je nachdem, wer am anderen Ende der Leitung sitzt, kann man da noch> einiges an Aufwand investieren. Vor allen Dingen, wenn ein Mensch am> anderen Ende der Leitung sitzt. Denn dann müssen vorlaufende und> nachlaufende Leerzeichen, Tabulatoren ausgefiltert werden, während sie> aber mitten im Text erhalten bleiben sollen. Und eine Behandlung von> Backspace wär auch nicht schlecht.
Der serielle Monitor von Arduino ist kein richtiges Terminalprogramm.
Sondern der serielle Monitor hat einen Zeileneditor, in dem man eine
Befehlszeile vor dem Absenden manuell editieren kann wie man möchte, und
erst beim Drücken von Return oder auf den Senden-Button wird die ganze
eingegebene Zeile in einem Rutsch gesendet.
Daher funktioniert für Anfänger auch der oben von mir gepostete Code mit
dem delay(25), der nach dem Empfang des ersten Zeichens etwas wartet.
Dein Code ist auch für die Verwendung mit manueller Bedienung über ein
klassisches Terminalprogramm geeignet: Die Zeichen werden so lange
gesammelt bis das spezielle abschließende Zeichen kommt. Egal wie lange
es dauert.
Mit Ausfilterung von Steuerzeichen und den fehlenden Deklarationen für
die setup() Funktion und "led" als OUTPUT gesetzt. Dein Code als
kompletter Arduino-Sketch:
1
Stringcmd;
2
byteled=13;
3
4
voidsetup(){
5
Serial.begin(9600);
6
pinMode(led,OUTPUT);
7
}
8
9
voidloop()
10
{
11
charnextChar;
12
if(Serial.available()>0)
13
{
14
nextChar=Serial.read();
15
Serial.print("Zeichen: '");
16
Serial.print(nextChar);
17
Serial.print("'\n");
18
19
if(nextChar==';'){
20
Serial.print("Kommando vollstaendig '");
21
Serial.print(cmd);
22
Serial.print("'\n");
23
24
if(cmd=="LEDon")
25
digitalWrite(led,HIGH);
26
elseif(cmd=="LEDoff")
27
digitalWrite(led,LOW);
28
cmd="";
29
}
30
31
elseif(nextChar>=32){
32
cmd+=nextChar;
33
Serial.print("Kommando bis jetzt ");
34
Serial.print(cmd);
35
Serial.print("\n");
36
}
37
}
38
}
> Alles in allem sind das aber Grundfertigkeiten
ACK.
Die Verwendung von String-Objekten, wie es der TO mit der Variablen
"cmd" beabsichtigt, ist aber auch unter Arduino kontraproduktiv. Die
Dinger sind voll die Pest: Es gibt eine handvoll Funktionen, die man
damit einem Anfänger supereinfach erklären kann. Zum Beispiel ein
Zeichen oder einen String mit dem Pluszeichen hinten dranhängen. Aber zu
den zig Libraryfunktionen der AVR libc sind diese Stringobjekte genau so
inkompatibel wie zu den Arduino eigenen Libraries. Da sollte er lieber
gleich lernen, wie C-Strings in Form von char-Arrays funktionieren.
Jürgen S. schrieb:> Karl Heinz schrieb:>> Ich wollte es mal nicht zu kompliziert machen.>> Je nachdem, wer am anderen Ende der Leitung sitzt, kann man da noch>> einiges an Aufwand investieren. Vor allen Dingen, wenn ein Mensch am>> anderen Ende der Leitung sitzt. Denn dann müssen vorlaufende und>> nachlaufende Leerzeichen, Tabulatoren ausgefiltert werden, während sie>> aber mitten im Text erhalten bleiben sollen. Und eine Behandlung von>> Backspace wär auch nicht schlecht.>> Der serielle Monitor von Arduino ist kein richtiges Terminalprogramm.> Sondern der serielle Monitor hat einen Zeileneditor, in dem man eine> Befehlszeile vor dem Absenden manuell editieren kann wie man möchte, und> erst beim Drücken von Return oder auf den Senden-Button wird die ganze> eingegebene Zeile in einem Rutsch gesendet.
Ah. Das wusste ich nicht.
Ich dachte, das wäre ein ganz normales Terminal.
Nun denn - wenn dieser serielle Monitor das so handhabt, dann wundert es
mich nicht mehr, dass Arduino Programme zwar mit diesem Werkzeug
funktionieren, im realen Einsatz mit beliebigen anderen Progammen aber
kläglich scheitern.
Karl Heinz schrieb:> Nun denn - wenn dieser serielle Monitor das so handhabt, dann wundert es> mich nicht mehr, dass Arduino Programme zwar mit diesem Werkzeug> funktionieren, im realen Einsatz mit beliebigen anderen Progammen aber> kläglich scheitern.
In Arduino-Programmen funktioniert genau das, was man programmiert.
Der von mir mit Posting um 12:34 gepostete Sketch empfängt Befehle, die
"in einem Rutsch" gesendet werden, aber mit Sendepausen dazwischen. Und
das funktioniert auch, wenn der Befehl zum Beispiel von einem
PC-Programm gesendet wurde, das mit Java, Visual Basic, Delphi, Wiring
oder sonstwas programmiert wurde.
Der von mir mit Posting um 13:24 gepostete Sketch mit Deiner Logik und
einem Semikolon als abschließendes Zeichen nach dem Befehl funktioniert
auch bei manueller Eingabe mit Terminalprogrammen.
Allerdings ist der Sketch mit Deiner Logik anfällig für
"Denial-of-Service" Attacken. Während mein vorher geposteter Code in 25
Millisekunden bei 9600 Baud nur 25 Zeichen empfangen kann, womit das
String-Objekt auf maximal 25 Zeichen Länge begrenzt wird, würde bei
Deiner Logik ein Datenstrom ohne Semikolon dazu führen, dass immer noch
ein und noch ein Zeichen an das String-Objekt drangehängt wird, bis der
RAM-Speicher überläuft.
Aber das ist ja hier nicht das Thema, Fehleingaben vernünftig
abzufangen, der TO wollte ja überhaupt nur einmal so etwas wie Befehle
empfangen können. Und dazu hat er jetzt zwei Codes zur Auswahl.
Ich habe jetzt mal diesen Code genommen.
Funktioniert auch soweit, wenn ich im Serial Monitor das entsprechende
Kommando setze (LEDon;).
Wenn ich jetzt aber mit meinem Programm, dass ich über Visual Studio in
C# geschrieben habe den gleichen Befehl sende tut sich nichts!
Erst wenn ich das ; durch einen buchstaben ersetze funktioniert es.
Warum?!
max2d schrieb:> Ich habe jetzt mal diesen Code genommen.> Funktioniert auch soweit, wenn ich im Serial Monitor das entsprechende> Kommando setze (LEDon;).> Wenn ich jetzt aber mit meinem Programm, dass ich über Visual Studio in> C# geschrieben habe den gleichen Befehl sende tut sich nichts!> Erst wenn ich das ; durch einen buchstaben ersetze funktioniert es.
Das kann ich irgendwie nicht glauben.
Hast Du vielleicht in Deinem C#-Programm Semikolon und Doppelpunkt
verwechselt?
Der Arduino-Sketch erzeugt jedenfalls umfangreiche Debug-Ausgaben.
Kopiere mal die Ausgabe aus dem seriellen Monitor heraus, wenn Du
dreimal nacheinander von Deinem Programm aus den Befehl mit
abschließendem Semikolon gesendet hast!
Jürgen S. schrieb:> Der Arduino-Sketch erzeugt jedenfalls umfangreiche Debug-Ausgaben.
erstens das (nur müsste er die eben in seinem C# Programm auch sichtbar
machen oder sonst irgendeine Möglichkeit haben, sich die relevanten
Informationen anzeigen zu lassen)
zweitens kommt an dieser Stelle der Tip mit der Installation eines
'Serial Port Monitors' auf dem PC ins Spiel, der einem Byte für Byte
exakt anzeigt, was eigentlich über die Serielle Schnittstelle rausgeht
bzw. rein kommt.
Ich empfehle, das Programm "HTerm" zu benutzen (ja, ich weiß, ist kein
Terminal im engen Sinne).
Da siehst du genau was auf der Leitung passiert, und kannst dir die
Werte auch in verschiedenen Darstellungen anzeigen lassen (Hex, bin,
ASCII, dez).
Wenn du mit diesem Tool festgestellt hast, dass dein Arduino-Programm
stabil läuft kannst du beginnen dein C# Programm zu schreiben.
Dieses Vorgehen ist einfacher als der Versuch, zwei Programme zu
verheiraten von denen du bei beiden nicht weißt, ob sie funktionieren.
Benutzt du erstmal HTerm oder ein anderes fertiges PC-Tool kannst du dir
im Fehlerfall sicher sein, dass sich der Fehler im Arduino-Programm
befindet.
=> systematisches Vorgehen
Man kann die Kommandos auch empfangen und ausführen ohne diese
Zwischenspeichern zu müssen. Zudem könnte man die Kommandos in einer
Liste speichern, um das Hinzufügen neuer Kommandos einfacher zu machen.
Ich habe für alle interessierten ein kleines Beispiel geschrieben.
Daniel A. schrieb:> Man kann die Kommandos auch empfangen und ausführen ohne diese> Zwischenspeichern zu müssen. Zudem könnte man die Kommandos in einer> Liste speichern, um das Hinzufügen neuer Kommandos einfacher zu machen.> Ich habe für alle interessierten ein kleines Beispiel geschrieben.
Danke für den Code, funktioniert einwandfrei!
Für Arduino-Interessierte habe ich mal kurz einen über Serial laufenden
Arduino-Sketch draus gemacht.
Hallo,
auch wenn der Thread schon ein paar Jahre alt ist, hat er mir sehr
geholfen, meine eigenen Routinen für das Auslesen des Seriellen Monitors
zu schreiben.
Nachdem hier ja echte Profis unterwegs sind, möchte ich meine Routinen
mal online stellen und freue mich sowohl über Kritik als auch Lob.
Das Zusammenfassen der Befehle bitte ich zu entschuldigen, ist für mich
übersichtlicher.
Hallo,
vielen Dank für die Antwort.
Das Tutorial zu Serial.Event habe ich verstanden, allerdings tut es im
wesentlichen ja auch nichts anderes als mein Code, fragt lediglich
zusätzlich auf Zeilenende ab. Mir war der Ansatz wichtig, die Abfrage in
Subs zu lösen und nicht im Hauptprogramm.
Deinen Code habe ich nicht verstanden, der ist mir viel zu komplex. Ich
vermute, Du baust auf irgendwelchen Objekten auf. Nachdem mein einfacher
Code aber auch funktioniert, würd ich mir diese mühsame Einarbeitung
sparen, aber vielen Dank trotzdem.
Josef N. schrieb:> vielen Dank für die Antwort.
kein Problem aber da bei dir überall
1
do{}while(Serial.available()<1);charnextChar;
steht was umständlich und überflüssig ist,
hatte ich auch mal, nutze doch einfach Serial.event
Das läuft im Interrupt nur wenn ein Zeichen eintrudelt!
Mein Code ist eine Mischung aus C und Arduino, weil ich das mit der
Arduino Stringklasse noch nicht verstanden habe.
Ich definiere einen Buffer
1
charserial_in_command[MAXBUFFER]={0};
2
charserial_in_buff[MAXBUFFER]={0};
3
chars_out_str[MAX_S_OUT_BUFF]={0};
4
unsignedcharchr_cnt=0;
lese solange Serial.event aufgerufen wird, sammele Zeichen in
serial_in_buff ein bis zum Enter,
kopiere die in serial_in_command[MAXBUFFER]
und springe zur Auswertung
Joachim B. schrieb
> kein Problem aber da bei dir überall> do {} while (Serial.available() <1); char nextChar;> steht was umständlich und überflüssig ist,> hatte ich auch mal, nutze doch einfach Serial.event> Das läuft im Interrupt nur wenn ein Zeichen eintrudelt!
Vielen Dank, jetzt hab ich's begriffen und die Interrupt-Lösung ist
natürlich schon wesentlich eleganter.
Dein Code wird mir inzwischen auch etwas klarer, ist halt ein universell
einsetzbarer Code, der vorallem Sinn macht für störbehaftete
Übertragungen. Werd ich später mal genauer anschauen, aber ich brauch
den seriellen Monitor derzeit nur zum Debugging meiner Alarmanlage, um
zu schauen, wann die Infrarot- und Radarsensoren auslösen, weil ich
derzeit noch zu viel Fehlalarme habe. Und die Routinen waren eigentlich
nur dazu gedacht, die jeweils aktuelle Uhrzeit beim Hochladen des
Sketches etwas eleganter einzugeben als jeweils im Code die
Uhrzeitvariablen manuell zu setzen.
Vielen Dank nochmal für Deine Mühe, wenns Dich interessiert, meine
Alarmanlage ist auf
https://youtu.be/KvP90prt6rM zu sehen.