Servosteuerung vs. SoftwareSerial.h

Meinem kleinen Roboterarm aus Lego möchte ich als nächstes einen Sensor verpassen, der die Entfernung zu Gegenständen messen kann. Den habe ich an anderer Stelle bereits beschrieben. Angeschlossen wir der Sensor an einer seriellen Schnittstelle.

Wenn man nicht dauernd zwischen Sensor und USB umstecken möchte, greift man in diesem Fall dann wohl zur SoftwareSerial Library, mit deren Hilfe sich weitere serielle Ports auf (nahezu) beliebigen Pins anlegen lassen. Einizger Haken dabei ist, dass die Einbindung von SoftwareSerial.h sich negativ auf das Timing der Servoansteuerung mittels Servo.h auswirkt.

„…negativ auswirkt…“ bedeutet soviel wie: Die Servos zucken unkontrolliert in einem Maß, dass sich mein Lego Modell auch schon mal zerlegt :-o

Problem ist (nach Web Recherche) wohl, dass SoftwareSerial.h ganz uneigennützig Timer und Interrupts verwendet, die auch von Servo.h genutzt werden und so das Chaos entsteht.

Ich habe verschiedene Tipps und Hinweise bekommen (unter anderem beim Arduino Stammtisch Hannover) um mit dem Thema umzugehen.

Q1: Warum nimmst Du nicht Pin 0 und 1 (Hardware RX/TX)?
A1a: Siehe oben, zu faul dauernd zwischen USB und Sensor umzustecken.
A1b: Der Sensor, den ich seriell anschließen möchte, bringt nicht genug Pegel und/oder Strom, um dem USB/Seriellwandler Paroli bieten zu können. Über Pin 0 und 1 kann ich nichts einlesen.

Q2: Wieso kaufst Du Dir keinen Pegelwandler (MAX232 oder ähnlich) um dann doch Pin 0 und 1 nutzen zu können?
A2: Den kriege ich so schnell nicht ran. Außerdem muss das doch irgendwie gehen?!

Q3: Weshalb nutzt du keinen zweiten Arduino, um die Sensorsignale zu verarbeiten und dann über einen Digitalpin ein einfaches Ergebnis einzulesen?
A3:  Ist das nicht ein wenig viel Aufwand? Gleich einen „Koprozessor“ zu bemühen?

Q4: Weshalb schreibst Du Dir keine eigene Servoansteuerung und verzichtest auf Servo.h?
A4: Na, das klingt, als sei es einen Versuch wert!

Was wird gebraucht? Ein Signal mit 50Hz, bestehend aus einem Puls mit zwischen einer und zwei Millisekunden Breite und einer entsprechenden Pause zwischen 18ms und 19ms. So sieht der (leicht idealisierte) Code dafür aus:

void moveServo(int servo, int Winkel)
{
  //Winkel in Mikrosekunden umrechnen
  Pulsweite = map(Winkel,0,180,1000,2000);
  // Ansteigende Flanke, Beginn des Pulses
  digitalWrite(servo, HIGH);
  // Impulsdauer abwarten
  delayMicroseconds(Pulsweite);
  // Fallende Flanke, Puls Ende
  digitalWrite(servo, LOW);
  // für 50Hz Wiederholrate: 20ms Pause (unter der Annahme,
  // dass der restliche Code in Null zeit abläuft :-)
  delay(10);
  delayMicroseconds(10000-Pulsweite);
}

Die Servoansteuerung funktioniert damit auch, allerdings geht das ganze Timing wieder zum Teufel, wenn ich SoftwareSerial.h einbinde. Also alles für die Katz? Wir werden sehen…

Schreibe einen Kommentar

Deine E-Mail-Adresse wird nicht veröffentlicht. Erforderliche Felder sind mit * markiert.