Pages: [1] 2   Go Down
Author Topic: Servo ansteuern mit Serial Monitor  (Read 426 times)
0 Members and 1 Guest are viewing this topic.
Offline Offline
Newbie
*
Karma: 3
Posts: 8
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

Hallo!
Versuche zur Zeit, einen kleinen Servo (Modelcraft ES 05) über die serielle Schnittstelle anzusteuern.
Das Signalkabel ist am Pin5 angeschlossen, ein Signal kommt auch vom PC am Arduino Uno an.

Das Problem: Der Servo bewegt sich auch leicht, aber nie in der Gradzahl, die ich im Serial Monitor eingebe.
Ich habe die Servo library importiert. Daher müsste sich der Servo doch um 90° drehen, wenn der input 90 ist oder?
Kann aber auch Buchstaben über den seriellen Monitor schicken, was sogar zu einer Servobewegung führt.

Hier der Code:
Code:
#define DSERVO_TWO_PIN 5
#include <Servo.h>

Servo horz;
int val;

void setup()
{
  horz.attach(DSERVO_TWO_PIN);
  Serial.begin(9600);
}

void loop()
{
  if(Serial.available() > 1)
  {
    val = Serial.read();
    horz.write(val);   
    Serial.write(val);   
    delay(15);
  }
}

Es gibt viele Beispiele aus Büchern, deren Code ich auch abgetippt habe. Habe aber immer dieses beschriebene Problem, dass der Servo nicht die Gradzahl des Inputs anfährt smiley-confuse. Würde mich über Rückmeldungen freuen. Danke!!
Logged

Forum Moderator
BZ (I)
Offline Offline
Brattain Member
*****
Karma: 269
Posts: 21839
+39 349 2158303
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

was siehst Du am terminal?
Serial.write(val);  
Hast Du am Ende der Übertragung ein newline oder carrige return?

Grüße Uwe
« Last Edit: July 26, 2014, 08:48:36 am by uwefed » Logged

Offline Offline
Newbie
*
Karma: 3
Posts: 8
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

Hallo Uwe,
beim Terminal sehe ich genau das, was ich in die Sendeleiste eintippe und abschicke. Zahlen werden als Zahlen wiedergegeben, aber auch Buchstaben werden als Buchstaben wiedergegeben.
Ich kann ein 'a' senden und bekomme ein 'a' vom UNO zurückgesendet. Komischerweise dreht sich daraufhin sogar der Servo um ein Stück.
Muss ich dem Board noch auf andere Weise erklären, dass es Zahlen zwischen 0 und 180 bekommt und der Servo daraufhin die entsprechende Gradzahl anfahren soll?
Ich habe einen Newline return (glaube ich:-)). Habe nichts eingetellt im Code, alle Inputs werden aber als neue Zeile ausgegeben.
Logged

Offline Offline
Jr. Member
**
Karma: 11
Posts: 62
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset


Hallo!
Du sendest ja ASCII..
! = 33,  ~ = 126,  Z= 90...

Code:
#define DSERVO_TWO_PIN 5
#include <Servo.h>

Servo horz;
int val;

void setup()
{
  horz.attach(DSERVO_TWO_PIN);
  Serial.begin(9600);
}

void loop()
{
  if(Serial.available() > 0)
  {
    val = Serial.read();
    horz.write(val);   
    Serial.write(val);   
   Serial.println(val);
  }
}

Mit dem Sketch wird nach dem ASCII-Code der Stellwinkel ausgegeben und natürlich am Servo gestellt(mit eingeschränktem Bereich).
Hier wirds genauer erklärt:
http://forums.trossenrobotics.com/tutorials/how-to-diy-128/complete-control-of-an-arduino-via-serial-3300/


mfg Martin

 




Logged

Offline Offline
Faraday Member
**
Karma: 127
Posts: 4098
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

Ein ASCII Zeichen ist nur eine Zahl zwischen 0 und 9. Wenn man mehr will, wird es komplizierter. Du kannst nicht "180" eingeben und das mit einem read() lesen. Leider versuchen das Leute immer wieder smiley-sad

Am einfachsten, aber auch am unschönsten geht es hiermit:
http://arduino.cc/en/Serial/ParseInt
Das statt read() verwenden
Logged

Offline Offline
Full Member
***
Karma: 5
Posts: 216
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

Hallo,

Ein ASCII Zeichen ist nur eine Zahl zwischen 0 und 9.

kannst Du das bitte näher erklären ?

Danke
Logged

Es gibt nur 10 Arten von Menschen: die, die das Binär-System verstehen und die, die es nicht verstehen.

Offline Offline
Faraday Member
**
Karma: 127
Posts: 4098
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

War vielleicht etwas unschön ausgedrückt. Allgemein ist es eine Zahl zwischen 0 und 127:
http://www.asciitable.com/

Und jeder Zahl ist ein Zeichen zugeordnet. Wenn du in C '0' eintippst, dann ist das nichts anderes als 48. Deshalb kann man chars auch voneinander subtrahieren. Um von dem ASCII Zeichen '0' auf die Zahl 0 zu kommen macht man z.B. - '0'

Wenn du jetzt im Serial Monitor "012" eintippst werden drei Zahlen gesendet: 48, 49 und 50.
Also kann man mit read() jeweils nur eine Ziffer zwischen 0 und 9 einlesen (bzw. einen Buchstaben oder was anderes wenn man das wollte). Das meinte ich "ist nur eine Zahl zwischen 0 und 9". Das war auf diese Anwendung bezogen, wo man pro ASCII Zeichen nur eine Ziffer hat, aber nicht eine mehrstellige Zahl.

« Last Edit: July 26, 2014, 08:31:17 am by Serenifly » Logged

Offline Offline
Full Member
***
Karma: 5
Posts: 216
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset


DANKE !!

Gruss Kurti
Logged

Es gibt nur 10 Arten von Menschen: die, die das Binär-System verstehen und die, die es nicht verstehen.

Offline Offline
Newbie
*
Karma: 3
Posts: 8
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

Ha, das hört sich logisch an!
Vielen Dank für die Tips und den Link, das ist genau das passende Tutorial! Melde mich, wenn ich´s ausprobiert habe.
« Last Edit: July 26, 2014, 12:37:38 pm by Glitsch » Logged

Offline Offline
Faraday Member
**
Karma: 127
Posts: 4098
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

Das hier funktioniert für positive Zahlen (bis zum Maximalwertes eines signed long):
Code:
void setup()
{
  Serial.begin(9600);
}

void loop()
{
  long number = readSerial();
  if(number > 0)
  {
    Serial.print(F("Received: "));
    Serial.println(number);
  }
}

long readSerial()
{
  static long number;
 
  while(Serial.available())
  {
    char c = Serial.read();

    if(c >= '0' && c <= '9')
    {
      number *= 10;
      number += c - '0';
    }
    else if(c == '\n')
    {
      long tmp = number;
      number = 0;
      return tmp;
    }
  }
  return -1;
}

Dazu musst du den Serial Monitor zu einstellen, dass er ein Linefeed/Newline am Ende schickt!
Logged

Offline Offline
Newbie
*
Karma: 3
Posts: 8
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

Hallo Serenify,
habe den Code mit parseInt() verändert und es funktioniert super. Zumindest über die Serial-Console. Warum ist es am unschönsten? Weil es mehr Leistung beansprucht oder weil man nicht richtig sieht, was es im Hintergrund tut?
Morgen versuche ich, einen processing-sketch Daten über die Serial-Verbindung schicken zu lassen und den Servo anzusteuern. Ist gerade nicht mehr meine Zeit:-)
Vielen Dank nochmal für die vielen schnellen Antworten, ist ja unglaublich, dass man an einem Tag soviele Problemlösungen bekommt!
Logged

Offline Offline
Faraday Member
**
Karma: 127
Posts: 4098
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

Weil parseInt() blockiert. Das wartet standardmäßig eine ganze Sekunde ob was da ist. Das umgehst du immerhin durch available(). Du rufst es also nur auf wenn wirklich was da ist. Danach wartet es aber auch eine Sekunde bis die Eingabe fertig ist. Die Zeit kann man durch setTimeout() anpassen und da würde auch wesentlich weniger reichen:
http://arduino.cc/en/Serial/ParseInt
http://arduino.cc/en/Reference/StreamSetTimeout

Man kann nicht einfach direkt mehrmals hintereinander read() machen, da die serielle Übertragung langsam ist. Bei 9600 Baud sind es 1ms pro Zeichen! Selbst bei 115200 Baud sind es 86µs. Was bei einem Prozessortakt von 62,5ns immer noch relativ lange ist. Bei 9600 Baud reicht also eine Timeout Zeit von 5ms für 3 Zeichen.

Warten ist eine einfache Lösung und es muss nicht unbedingt sofort negative Auswirkungen haben (vor allem wenn es nur ein paar ms statt 1s sind). Deine Servos werden über einen Timer gesteuert. Wenn du also sonst nichts machst, bekommst du das gar nicht mit.
Wenn du aber daneben noch anderen Code in loop() hast der schnell laufen muss, wird das problematisch. Und man weiß nicht immer wie lange die maximale Übertragung dauert. Der Code oben schaut daher einfach nach ob was im seriellen Eingangspuffer ist und kehrt sofort wieder zurück wenn nichts mehr da ist. Und das Ende der Übertragung wird nicht durch die Zeit festgelegt, sondern durch ein Endzeichen.
« Last Edit: July 26, 2014, 06:15:27 pm by Serenifly » Logged

Offline Offline
Newbie
*
Karma: 3
Posts: 8
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

Stimmt! Das war wirklich langsam und ist für meine Anwendung also unbrauchbar. Gut zu wissen - da hätte ich wieder ewig herumgesucht smiley-roll-sweat
Das Senden der Servopositionen über den Processing-Sketch ist damit also nicht sinnvoll. Habe ich vorhin ausprobiert.

Ich finde es übrigens etwas schwierig, mit der ArduinoReference zu lernen, weil es kaum Codebeispiele gibt. Da ist die Processing-Seite etwas anfängerfreundlicher gestaltet.

Nagut, dann werd ich wohl doch noch eine Weile das Tutorial lesen und versuchen, den Code anzupassen. Melde mich bei Fortschritten:-)
Logged

Offline Offline
Faraday Member
**
Karma: 127
Posts: 4098
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

Du kannst wie gesagt mal die Zeit mit setTimeout() auf ein paar ms setzen. Dann wartet die Funktion nicht so lange. Die Baudrate auf 115200 hochzuschrauen machst das ganze auch schneller und erlaubt es dir mehrere Zeichen innerhalb 1ms zu empfangen.

Oder eben Reply #9 hier
Logged

Offline Offline
Newbie
*
Karma: 3
Posts: 8
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

Hallo,

gerade kann ich mich wieder motivieren, an dem Projekt zu arbeiten. Ich habe den Code aus reply#9 benutzt und ein paar Zeilen zugefügt, sodass ich den Servo ansteuern kann. Über den Serial Monitur der IDE funktioniert das super.

Das Problem ist glaube ich, dass Processing nicht richtig sendet. Ich bin mir aber sicher, dass Processing den COM3-Port benutzt, denn während der Processing Scetch ausgeführt wird, kann ich den Serial Monitor der IDE nicht benutzen. Es meldet: "Der serielle Port COM3 wird bereits verwendet...".

Im kommenden Post schicke ich mal einige Processing-Zeilen, damit man sieht, was processing tun soll.
Logged

Pages: [1] 2   Go Up
Jump to: