Forum: Mikrocontroller und Digitale Elektronik Arduino Serielle Schnittstelle PC --> Arduino


von Flo D. (floflovaldo)


Lesenswert?

Hallo,

ich würde gerne Testweise etwas mit einem Arduino Nano ausprobieren. Ich 
würde gern vom Seriellen Monitor zum Arduino Zeichen schicken. In meinem 
Fall zum Beispiel "1_ON" und 1_OFF". Dann soll ein bestimmter DigitalPin 
auf HIGH bzw. auf LOW geschaltet werden.

Leider habe ich es bis jetzt nur hinbekommen eine eingegebene Zahl 
direkt wieder ausgegeben. Habe schon einiges im Internet darüber 
gesucht, aber leider nicht weiteres gefunden was mit helfen könnte.

Würde mich über Hilfe sehr freuen.

Viele Grüße
Florian

von Max H. (hartl192)


Lesenswert?

Florian D. schrieb:
> Leider habe ich es bis jetzt nur hinbekommen eine eingegebene Zahl
> direkt wieder ausgegeben.
Du kannst also den String über die Serielle empfangen nur nicht 
auswerten?
Zeig mal was du bis jetzt hast…

von Bestromer (Gast)


Lesenswert?

wenn >Du< es hinbekommen hast, eine Zahl zu empfangen und wieder 
auszugeben, wo liegt dann das Problem eine Aktion beim Empfang einer 
Bytefolge zu realisieren??

von Flo D. (floflovaldo)


Lesenswert?

1
char var;
2
3
void setup() {
4
  Serial.begin(9600);
5
  pinMode(2, OUTPUT);
6
  Serial.println("Test:");
7
 }
8
9
void loop() {
10
  if(Serial.available())
11
  {
12
    var=Serial.read();
13
    Serial.println(var);
14
  }
15
}

Das habe ich bis jetzt. Das mit dem Abfragen hab ich aber nicht 
hinbekommen, um somit wenn eben die Zeichenkette "1_ON" bzw. "1_OFF" 
entweder den D2 HIGH oder LOW zu schalten

von Max H. (hartl192)


Lesenswert?

Als erstes musst du mal die empfangenen Zeichen zu einem String 
zusammensetzten. Am einfachsten ist wenn du am Ende jeder Nachricht z.B. 
ein '\n' anhängst um zu wissen wenn sie fertig ist, und danach musst 
diesen String auswerten.

: Bearbeitet durch User
von Flo D. (floflovaldo)


Lesenswert?

Wo genau muss ich das '\n' hinsetzten?

Und wie werte ich den String dann eben aus?

Viele Grüße

von Max H. (hartl192)


Lesenswert?

Florian D. schrieb:
> Wo genau muss ich das '\n' hinsetzten?
Am Ende deiner Nachricht, damit du weißt das fertig ist. Du würdest dann 
z.B. "1_ON\n" senden.
> Und wie werte ich den String dann eben aus?
Bei deinem Beispiel würde ich es so machen:
1
uint8_t pin_nr = string[0] - '0'
2
if(!strcmp(string + 1, "_ON"))
3
  digitalWrite(pin_nr, HIGH);
4
else if(!strcmp(string + 1, "_OFF"))
5
  digitalWrite(pin_nr, LOW);

von Flo D. (floflovaldo)


Lesenswert?

Also muss ich bei jedem "Befehl" den ich am PC im Serien Monitor ein 
'\n' eingeben?

Und sorry das ich nochmal frage, aber ich weiß nicht genau wie ich das 
so in meinen Code einbauen soll.

von Max H. (hartl192)


Lesenswert?

Florian D. schrieb:
> Also muss ich bei jedem "Befehl" den ich am PC im Serien Monitor ein
> '\n' eingeben?
Viele Terminals können das auch automatisch mitsenden.

> Und sorry das ich nochmal frage, aber ich weiß nicht genau wie ich das
> so in meinen Code einbauen soll.
Als erstes musst du mal die empfangenen Zeichen in einen String packen.

von Chefkoch (Gast)


Lesenswert?

Witzig, ich fuhrwerke gerade an der selben Sache rum.

Ich habe den Klassen etwas unter die Haube geschaut, weil ich in der 
Ardu-Referenz bei einigen Readfunktionen etwas von Timeout gelesen habe.
Und siehe da, letztenende wird an einer while-Schleife rumgenudelt - 
entweder bis der erwartete String da ist, oder eben der Timeout 
zuschlägt. Find ich nicht so gut.

Ich habe jetzt LämpchenAn-LämpchenAus realisiert, indem ich ganz bewusst 
nur die einfachen Funktionen der Serial Klasse benutzt habe.
Ist zwar auch eine while drin, aber die wartet nicht auf etwas konkretes 
sondern läuft solange, wie im Buffer noch nicht gelesene Zeichen 
enthalten sind.

Kleiner Hinweis, ich habe für meinen Test nicht mit einer \0 
Terminierung gearbbeitet, sondern mit einem $ Starttoken. Ist ja nicht 
in Zement gegossen.
1
int readUart();
2
int res = 0;
3
4
char buffer[9];
5
int head = 0;
6
int tail = 0;
7
8
9
10
void setup() {
11
  // put your setup code here, to run once:
12
  Serial.begin(9600);
13
  pinMode(13, OUTPUT); 
14
  digitalWrite(13, HIGH);
15
  
16
}
17
18
void loop() {
19
20
  // put your main code here, to run repeatedly:
21
22
  res = readUart();
23
  if(res == 1)digitalWrite(13, LOW);
24
  if(res == 2)digitalWrite(13, HIGH);
25
26
}
27
28
int readUart()
29
{
30
  char tmpChar;
31
  while(Serial.available() > 0)
32
  {
33
    tmpChar = Serial.read();
34
    
35
    if(tmpChar == '$') head = 0;
36
    else
37
    {
38
      buffer[head++] = tmpChar;
39
      if(head == 8)
40
      {
41
        Serial.write(buffer[0]);
42
        Serial.write(buffer[1]);
43
        Serial.write(buffer[2]);
44
        Serial.write(buffer[3]);
45
        Serial.write(buffer[4]);
46
        Serial.write(buffer[5]);
47
        Serial.write(buffer[6]);
48
        Serial.write(buffer[7]);
49
        head = 0;
50
        if( (buffer[0] == 'S') &&
51
            (buffer[1] == 't') &&
52
            (buffer[2] == 'r') &&
53
            (buffer[3] == 'i') &&
54
            (buffer[4] == 'n') &&
55
            (buffer[5] == 'g') &&
56
            (buffer[6] == ' '))
57
            {
58
              
59
              if(buffer[7] == '1') return 1;
60
              if(buffer[7] == '2') return 2;
61
            }
62
            
63
      }
64
    }
65
    return 0;
66
  }
67
}

von Max H. (hartl192)


Lesenswert?

Chefkoch schrieb:
> Ist ja nicht in Zement gegossen.
Wenn man auf den empfangen String dann irgendwelche Stringfunktionen 
verwenden will aber schon.

von Bastler (Gast)


Lesenswert?

Chefkoch schrieb:
> Serial.write(buffer[0]);
>         Serial.write(buffer[1]);
>         Serial.write(buffer[2]);
>         Serial.write(buffer[3]);
>         Serial.write(buffer[4]);
>         Serial.write(buffer[5]);
>         Serial.write(buffer[6]);
>         Serial.write(buffer[7]);

Bei Deinen Programmierkünsten wird mir schlecht.

von Mel Gibson (Gast)


Lesenswert?

...naja, was willst du von den Arduinopfuschern auch erwarten?

von Bestromer (Gast)


Lesenswert?

Mel Gibson schrieb:
> ...naja, was willst du von den Arduinopfuschern auch erwarten?

....auf jeden Fall haben diese "Arduinopfuscher" sinnvollere Beiträge 
als Ihr Superhelden der Bitschubserei, also kommt mal wieder runter...
Ich möchte gern mal Eure ersten Programmierversuche sehen!
Wenn es Euch nicht gefällt, warum zeigt ihr nicht wie man es besser 
machen kann statt Euch den Heldenstatus auf die Brust zu drücken...

von Chefkoch (Gast)


Lesenswert?

Seh ich auch so. Jetzt hat man schon das Pech, dass einer 
"Arduinopfuscher" die mitgelieferten Klassen auf bestimmte 
Eigenschafften untersucht und dann noch entsprechend handelt. Dann 
werden eben Offensichtlichkeiten aus einem für Testzwecke 
zusammengeworfenem Programm hergenommen um rumzubashen.
Hope, this made your day...

von STK500-Besitzer (Gast)


Lesenswert?

Bastler schrieb:
> Chefkoch schrieb:
>> Serial.write(buffer[0]);
>>         Serial.write(buffer[1]);
>>         Serial.write(buffer[2]);
>>         Serial.write(buffer[3]);
>>         Serial.write(buffer[4]);
>>         Serial.write(buffer[5]);
>>         Serial.write(buffer[6]);
>>         Serial.write(buffer[7]);
>
> Bei Deinen Programmierkünsten wird mir schlecht.

Es gibt Leute, die so eine Laufschrift programmiert haben - damals in 
TurboPascal.
Arduino ist halt für Anfänger ein guter Einstieg.
Dass Serial.write auch anders funktioniert, kann man in dessen Doku 
nachlesen - wenn man denn will.

von Bastler (Gast)


Lesenswert?

> Es gibt Leute, die so eine Laufschrift programmiert haben - damals in
> TurboPascal.
> Arduino ist halt für Anfänger ein guter Einstieg.
> Dass Serial.write auch anders funktioniert, kann man in dessen Doku
> nachlesen - wenn man denn will.

Mein Hinweis es besser zu machen wurde anscheinend in keinster Weise 
verstanden oder überdacht. Macht nix, popelt weiter rum.

von ??? (Gast)


Lesenswert?

>Bei Deinen Programmierkünsten wird mir schlecht.

Würdest du dir Wünschen, dass Lehrer und Erziehungsberechtigte auf diese 
Auszubildenden (seien es Schüler, Kinder, Lehrlingen) Hinweise geben?

von Lute (Gast)


Lesenswert?

Wenn es die Wahrheit ist: Ja.

von Karl H. (kbuchegg)


Lesenswert?

Florian D. schrieb:
> Also muss ich bei jedem "Befehl" den ich am PC im Serien Monitor ein
> '\n' eingeben?


Du gibst kein '\n' ein.
\n ist die C++ Schreibsweise für das Zeichen, das gesendet wird, wenn du 
auf 'Return' drückst. Das ist die große Taste rechts ,die aussieht wie 
ein Tetris Baustein und auf der manchmal 'Enter' steht, bei manchen 
Herstellern ist da aber auch abgewinkelter Pfeil drauf.

> Und sorry das ich nochmal frage, aber ich weiß nicht genau wie ich das
> so in meinen Code einbauen soll.

Indem du erst mal einen STring zusammenbaust.
Ein String ist eine Abfolge von Zeichen, die mit einem '\0' endet. Das 
Ende der Übertragung erkennst du daran, dass ein \n eintrifft. Dann ist 
dein String komplett.
1
int nrChars = 0;
2
char inputLine[80];
3
4
void loop() {
5
6
  if( Serial.available() ) {
7
    char nextChar = Serial.read();
8
9
    if( nextChar != '\n' )
10
      inputLine[nrChars++] = nextChar ;
11
12
    else {
13
      inputLine[nrChars] = '\0';   // String vollständig machen
14
      nrChars = 0;
15
16
      Serial.write( "Kommando: " );
17
      Serial.writeln( inputLine );
18
19
      if( strcmp( inputLine, "Juhu" ) == 0 )
20
        ; // Kommando "Juhu" bearbeiten
21
22
      else if( strcmp( inputLine, "Hamsti" ) == 0 )
23
        ; // Kommando "Hamsti" bearbeiten
24
25
    }
26
  }
27
}

und kauf dir ein C++ Buch oder ein C Buch.
C++ deswegenm weil du eigentlich in C++ programmierst. Auf der anderen 
Seite sind viele Arduino Programme sehr C lastig, weil man viele Dinge 
aus C++ nicht verwenden möchte (wie zb eine String-Klasse), deshalb 
greift man da auf die C Variante zurück und daher solltest du die 
ebenfalls beherrschen.
Auch wenn immer wieder gesagt wird: Um Arduino zu programmieren muss man 
nichts können - es stimmt nicht.

Fehlerbehandlung musst du in den Code noch einbauen. Im speziellen musst 
du dafür sorgen, dass dir ein Benutzer, der auf der Tastatur 
eingeschlafen ist, dir nicht das Array überfährt.

: Bearbeitet durch User
von Karl H. (kbuchegg)


Lesenswert?

Lute schrieb:
> Wenn es die Wahrheit ist: Ja.

Leider ist es heutzutage nicht mehr politisch korrekt zu einer 
drastischen Ausdrucksweise zu greifen. Die lieben Kleinen könnten davon 
ja einen psychischen Knacks erhalten und dann laufen sie Amok wenn sie 
17 sind. Wie hat es meine Generation nur geschafft, erwachsen zu werden?

von chris_ (Gast)


Lesenswert?

Beim Arduino gibt es fast für jedes Problem eine Library, so auch hier:

http://playground.arduino.cc/Code/TextFinder

von Alex Z. (alexander_z49)


Lesenswert?

Warum schickst du nicht einfach eine Zahl rüber und benutzt die Funktion 
toInt() um aus dem String einen Integer zu machen. Dann kannst du das 
ganze sogar noch in einer Case-Abfrage verwursten und hast 32k 
verschiedene komandos zur Verfügung.

https://www.arduino.cc/en/Tutorial/StringToIntExample

von Karl H. (kbuchegg)


Lesenswert?

Alex Z. schrieb:
> Warum schickst du nicht einfach eine Zahl rüber und benutzt die Funktion
> toInt() um aus dem String einen Integer zu machen.

Weil er noch keinen String hat. Ganz einfach

: Bearbeitet durch User
von Alex Z. (alexander_z49)


Lesenswert?

Dafür gibt es Serial.readString()

https://www.arduino.cc/en/Serial/ReadString

oder er nimmt gleich Serial.parseInt()

: Bearbeitet durch User
von Max H. (hartl192)


Lesenswert?

Karl H. schrieb:
> inputLine[nrChars++] = nextChar ;
Was mit hier noch fehlt, wäre etwas um zu verhindern dass über die Array 
Grenzen hinausgeschrieben wird, z.B.:
1
  inputLine[nrChars] = nextChar;
2
  if(nrChars < 80 - 1)
3
    nrChars++;

Für die 80 würde ich dann aber ein
1
#define BUFFER_SIZE  80
machen.

: Bearbeitet durch User
von Joachim B. (jar)


Lesenswert?

vielleicht hilft euch das?
1
// --------------- serial in ---------------
2
    if (Serial.available() > 0) 
3
    { char incomingByte = (char)Serial.read();
4
      if(incomingByte == 13)  // Wenn das Enter ankommt
5
      { strcpy(serial_in_command, serial_in_buff);
6
        chr_cnt = 0;
7
        strcpy(serial_in_buff,"");
8
        //memset(&serial_in_buff[0], 0, sizeof(serial_in_buff));
9
      }
10
      else // Falls kein Enter kommt muss der Text gespeichert werden in dem inText Array
11
      { if(isprint(incomingByte))
12
          serial_in_buff[chr_cnt++] = incomingByte;
13
      }
14
    } // if (Serial.available() > 0) 
15
  
16
    if(strlen(serial_in_command))
17
    { Serial.println(F("")); Serial.print(serial_in_command);  Serial.println(F(" -> erkannt")); *serial_in_buff=0; chr_cnt=0; 
18
    }
19
          
20
    if( strstr(serial_in_command, "help") || ( strstr(serial_in_command, "?") && strlen(serial_in_command)==1 ) )
21
    { // help screen
22
      Serial.println(F("\ncommands: \n"));
23
      Serial.println(F("setdate2015/01/15"));
24
      Serial.println(F("getdate"));
25
      Serial.println(F("settime17:22:30"));
26
      Serial.println(F("gettime"));
27
      Serial.println(F("ledpower"));
28
      Serial.println(F("ledpower?"));
29
      Serial.println(F("ledhell?"));
30
      Serial.println(F("dcf77"));
31
      Serial.println(F("dcf77?"));
32
      Serial.println(F("reset"));
33
      Serial.println(F(""));
34
      memset(&serial_in_command[0], 0, sizeof(serial_in_command));
35
      memset(&serial_in_buff[0], 0, sizeof(serial_in_buff));
36
    }
37
38
39
    if( strstr(serial_in_command, "gettime") )
40
    { // "gettime"
41
      sprintf((char *)serial_in_buff,"%02d:%02d:%02d", RTC.hour, RTC.minute, RTC.second);
42
      Serial.print(serial_in_buff); Serial.println(F(" Uhr"));
43
      memset(&serial_in_command[0], 0, sizeof(serial_in_command));
44
      memset(&serial_in_buff[0], 0, sizeof(serial_in_buff));
45
    } // if( strstr(serial_in_command, "gettime") )
46
47
    if( !strcmp(serial_in_command, "ledpower") )
48
    { // "ledpower"
49
      off();
50
      memset(&serial_in_command[0], 0, sizeof(serial_in_command));
51
      memset(&serial_in_buff[0], 0, sizeof(serial_in_buff));
52
    } // if( !strcmp(serial_in_command, "ledpower") )
53
  
54
    if( !strcmp(serial_in_command, "ledhell?") )
55
    { // "ledhell?"
56
      Serial.print(F("ledhell= ")); Serial.println(led_hell);
57
      memset(&serial_in_command[0], 0, sizeof(serial_in_command));
58
      memset(&serial_in_buff[0], 0, sizeof(serial_in_buff));
59
    } // if( !strcmp(serial_in_command, "ledpower?") )
60
61
    if(strlen(serial_in_command))
62
    { memset(&serial_in_command[0], 0, sizeof(serial_in_command));
63
      memset(&serial_in_buff[0], 0, sizeof(serial_in_buff));
64
    }
65
// --------------- serial in ---------------

Bitte melde dich an um einen Beitrag zu schreiben. Anmeldung ist kostenlos und dauert nur eine Minute.
Bestehender Account
Schon ein Account bei Google/GoogleMail? Keine Anmeldung erforderlich!
Mit Google-Account einloggen
Noch kein Account? Hier anmelden.