Arduino: Servos ansteuern

Damit sich meine kleine Roboter-Platform auch aus etwas komplizierteren Lagen selbstständig heraus navigieren kann, muss sie nicht nur feststellen, ob sich vor ihr ein Hindernis befindet. Sie muss auch nachsehen, ob sich neben ihr Hindernisse befindet. Deshalb habe ich den den GP2D12 Entfernungssensor kipp- und schwenkbar montiert. Das Kippen und Schwenken des Sensors erfolgt über zwei Servos.

Meine Recherche zum Ansteuern von Servos mit dem Arduino ergab zunächst etwas verwirrende Ergebnisse. Offenbar war in der Entwicklungsumgebung früher (vor Version 0017) keine Servo-Library enthalten. Die Library, die damals zum Download bereit stand, musste etwas anders angesprochen werden als die Version, die seit 0017 im der Entwicklungsumgebung enthalten ist. Näheres hier: Arduino Playground – Servo.

In meinem kleinen Beispiels-Sketch werden zwei Servos (Pin 8 und Pin 9) über die Tasten 8, 4, 6, 2 (am Besten auf dem Nummernblock) gesteuert. Damit die im Roboter verbauten Servos nirgends anstoßen ist die Drehrichtung in beide Richtungen begrenzt.

— schnipp —

#include <Servo.h>

// Pins festlegen
int pin1 = 9;
int pin2 = 8;

// Servo-Objekt erzeugen
Servo servo1;
Servo servo2;

// Ausgangsposition in Winkelgraden
int pos1 = 90;
int pos2 = 45;

void setup()
{ servo1.attach(pin1);
  servo2.attach(pin2);
  Serial.begin(9600);
}

void loop()
{ // Drehung begrenzen
  if(pos1 < 0) pos1 = 0;
  if(pos1 > 180) pos1 = 180;
  if(pos2 < 45) pos2 = 45;
  if(pos2 > 130) pos2 = 130;

  // Position setzen
  servo1.write(pos1);
  servo2.write(pos2);

  delay(50);

  if(Serial.available())
  { char ch = Serial.read();

    switch(ch)
    { case '4': pos1-=45; break; // schwenken
      case '6': pos1+=45; break; // schwenken
      case '8':  pos2-=10; break; // kippen
      case '2':   pos2+=10; break; // kippen
    }
  }
}

— schnapp —

Siehe auch:

Arduino: The Documentary

Und wenn ich nun schon mal dabei bin Iframes in dieses Blog einzubinden (was ich eigentlich eher ungern mache), dann kann ich ja auch gleich die niegelnagelneue Dokumentation zur Geschichte des Arduino einbinden.

Arduino The Documentary (2010) English HD from gnd on Vimeo.

Inzwischen besitze ich zwei Stück von diesen Arduinos – einen Arduino Uno und einen Arduino Romeo. Ich muss also wohl nicht besonders betonen, dass ich dieses Open Source Hardware und Software Bündel ziemlich Klasse finde.

Die Hobbywerkstatt Facebook Page

Ich weiß nicht, kann man heute eigentlich noch irgendwie beweisen, dass man existiert, wenn man keine Facebook Seite hat? Ach ja, Personalausweis! Naja, nach meinem Personalausweis hat allerdings schon lange niemand mehr gefragt. Nach meiner Facebook-Seite dagegen schon.

Egal, jedenfalls hat dieses Werkstatt-Blog nun auch eine Facebook Page. Wenn Du also gerade nichts anderes zu tun hast, dann solltest Du jetzt unbedingt den “Gefällt mir Button” klicken ;-)

Arduino: GP2D12 Distance Measuring Sensor

Mit dem Entfernungssensor GP2D12 von Sharp lässt sich relativ sicher der Abstand zu Hindernissen ermitteln – zumindest im Bereich zwischen 10 und 80 Zentimeter. Der Anschluss des Sensors an den Arduino ist denkbar einfach – die Datenleitung wird mit einem der analogen Eingänge (in diesem Fall Pin 0) verbunden.

Etwas komplizierter ist es, die Messergebnisse in einen lesbaren Wert (z.B. Zentimeter) umzuwandeln. Der Werte des Sensors sind nicht linear, sondern sie müssen interpretiert werden. Ein brauchbarer Ansatz dafür stammt von Javier Valencia und ist an dieser Stelle dokumentiert.

Hier ein kleiner Sketch, mit dem ich die Werte vom Entfernungsmesser in lesbarer Form auf die serielle Schnittstelle ausgebe:

— schnipp —

/*
 * Read values from GP2D12 infrared distance sensor; convert readings to centimeters
 *
 * Version: 0.1 2011.01.05
 * Weblinks:
 *   http://www.hobby-werkstatt-blog.de/
 *   http://www.arduino.cc/playground/Main/ReadGp2d12Range
 */

int pinGp2D12=0;

/*
 * This sensor should be used with a refresh rate of 36ms or greater.
 * Inspired by: Javier Valencia, http://www.arduino.cc/playground/Main/ReadGp2d12Range
 */

float read_gp2d12()
{ int val = analogRead(pinGp2D12);
  if (val < 3) return -1; // invalid value
  float ret = (6787.0 /((float)val - 3.0)) - 4.0;
  if(ret > 80.0)
  return(80.0);
  else
  if(ret < 9.6) return(0.0);
  else return(ret);
} 

void setup()
{ pinMode(pinGp2D12, INPUT); // initialize the digital pin as an output
  Serial.begin(9600);
}

void loop()
{ Serial.println( read_gp2d12());
  delay(1000);
}

— schnapp —

Siehe auch:

Weblinks:

Arduino: Wheel Encoders (Rotary Encoders)

Wheel-Encoder in der 4WD Roboter Platform

Meine 4WD Robotor Platform wurde mit zwei sogenannten Drehimpulsgeber (Wheel Encoder, auch Rotary Encoder) geliefert. Mit diesen Encodern kann man feststellen, um wie viel sich die Räder gedreht haben. Letztlich ist es damit also möglich aus der gefahrenen Strecke den Standort des Roboters zu bestimmen.

Soweit ich es einschätzen kann, ist der Schlupf der Reifen beim Wenden der Platform nicht genau reproduzierbar. Letztlich geben die Encoder also wohl nur zuverlässige Positionsdaten, bis die Platform zum ersten Mal gewendet wurde. Aber wenn man schon solche Sensoren an den Rädern hat, dann möchte man natürlich auch wissen, wie man deren Daten auslesen kann.

Die in der 4WD-Platform verwendeten Wheel Encoder (SEN0038) liefern ein digitales Signal, das ich auf die beiden Interrupt-Eingänge des Arduino (Digital Pin 2 und Digital Pin 3) gelegt habe. In den entsprechenden Interrupt Service Routinen (ISR) kann dann aus der Drehrichtung des Motors der aktuelle Fahrweg berechnet werden.

Bei einem Durchmesser der Räder von 65 Millimeter ergibt sich ein Umfang von etwa 204,2 Millimeter. Der Wheel-Encoder hat eine Auflösung von 20 PPR (points per revolution). Jeder Pegelwechsel beim Encoder entspricht also etwa einem Fahrweg von einem Zentimeter. Die Drehrichtung kann von den beschriebenen Encodern nicht bestimmt werden. Sie ergibt sich deshalb aus der Drehrichtung des Motors.

Hier ein kleiner Arduino-Sketch, in dem ich auf komplizierte weitergehende Berechnungen verzichte. Es werden einfach die Pegeländerungen von zwei Inkrementalgebern gezählt und über die serielle Schnittstelle ausgegeben.

— schnipp —

/*
 * Simple example of analysis of the 4WD Platform wheel encoder
 *
 * Die Dateleitungen (grün) der Encoder gehören in Digital-Pin 2 und 3
 * Die Richtung ergibt sich aus der Motordrehrichtung
 *
 * Version: 0.1 2011.01.05
 * Copyleft: 2011 Heiner Otterstedt
 * Weblinks: http://www.hobby-werkstatt-blog.de/
 */
volatile int cnt0 = 0;
volatile int cnt1 = 0;

void setup()
{ attachInterrupt(0, doCount0, CHANGE);
  attachInterrupt(1, doCount1, CHANGE);
  Serial.begin(9600);
}

void loop()
{ Serial.print(cnt0);
  Serial.print(" - ");
  Serial.println(cnt1);
  delay(1000);
}

// Dummy interrupt functions
void doCount0() { cnt0++;  }
void doCount1() { cnt1++;  }

— schnapp —

Siehe auch:

Arduino: Infrarot-Receiver Module

IR-Sensor

Infrarot-Receiver Module (DFR0094)

Momentan steuere ich meinen 4WD-Platform mit einer handelsüblichen Universal-Fernbedienung. Dafür habe ich mir ein digitales Infrarot Receiver Modul (DFR0094) besorgt. Dieses Modul besitzt einen IR-Detektor, der die Signale der Fernbedienung für den Arduino empfangbar macht. So ein Infrarot Receiver Modul kostet gerade mal 3.30 Euro – da konnte ich einfach nicht widerstehen.

Mit Hilfe der Multi-Protocol Infrared Remote Library for the Arduino (Download) von Ken Shirriff war es überhaut kein Problem den Fernbedienungs-Teil der 4WD-Platform zu realisieren. Damit kann ich die Platform nun einfach hin und her steuern. Und natürlich kann ich nun auch komplexere Funktionen aus der Entfernung starten.

Der Sensor erkennt die Signale der Fernbedienung bis zu einer Entfernung von etwa 6 bis 8 Meter sicher. Wenn die IR-Diode der Fernbedienung und der Sensor genau ausgerichtet sind, dann funktioniert es natürlich noch viel weiter.

Hier ein kleiner Beispiels-Sketch für die Verwendung des Infrarot Receiver Moduls:

— schnipp —

/*
 * Receiving IR codes
 *
 * An IR detector/demodulator must be connected to the input pin 11
 * IRremote library must be in place
 * -> see http://www.arcfn.com/2009/08/multi-protocol-infrared-remote-library.html
 *
 * Version: 0.1 2011.01.05
 * Copyleft: 2011 Heiner Otterstedt
 * Weblinks: http://hobby-werkstatt-blog.de/
 */

#include <IRremote.h>

int pinReceifer = 11;

IRrecv irrecv(pinReceifer);

decode_results results;

// Dummy motor control functions
void goForward() { Serial.println("going forward..."); }
void goBackward() { Serial.println("going backward..."); }
void goLeft() { Serial.println("turning left..."); }
void goRight() { Serial.println("turning right"); }
void goStop() { Serial.println("full stop!"); }

void setup()
{ Serial.begin(9600); // Start Serial communication
 irrecv.enableIRIn(); // Start the receiver
}

void loop()
{ int result;

 if (irrecv.decode(&results))
 { result = results.value & 0x00ff;

    switch(result)
    { case 0x0020: goForward(); break;
      case 0x0021: goBackward(); break;
      case 0x0010: goLeft(); break;
      case 0x0011: goRight(); break;
      case 0x000d: goStop(); break;
      default:
        goStop();
        Serial.print("Unknown result: 0x");
        Serial.print(result, HEX);
        Serial.print(" (");
        Serial.print(result, DEC);
        Serial.println(")");
        break;
    }
    irrecv.resume(); // Receive the next value
  }
}

— schnapp —

4WD Platform

Nachdem ich schon einige praktische Anwendungen für den Arduino zusammen und wieder auseinander gebaut habe (Kamera-Fernauslöser, Blumengießautomat usw.), soll das Teil nun mobil werden. Dafür habe ich mir eine DFRobot 4WD Roboter Platform zugelegt.

Es gibt eine Reihe von Videos und Forenbeiträgen, die sich mit dem Zusammenbau dieser Platform beschäftigen (siehe bei den Weblinks unten). Offenbar handelt es sich bei meiner Platform aber um ein neueres Modell, dass einige Unterschiede zu den beschriebenen Versionen aufweist. Deshalb hier ein paar Fotos vom Zusammenbau:

Zugegeben, der Aufbau sieht noch nicht so ganz hundertprozentig professionell aus, aber das Teil fährt schon fröhlich auf dem Tisch herum.

Weblinks:

Arduino-IDE Version 0022

Zufällig sehe ich gerade, dass es eine neue Version der Arduino-IDE gibt. Hier die Release-Notes und hier die Download-Seite.

Programmierbarer Fernauslöser für Digitalkameras

Mein niegelnagelneuer Arduino ist da. Sofort nach dem Test mit der obligatorischen “Hello-World” Applikation “Blink” habe ich damit mein erstes praktisch nutzbares Projekt gebastelt – einen programmierbaren Fernauslöser für meine Digitalkamera.

Der TV-Fernbedienungs-Fernauslöser, den hier vorgestellt hatte, funktioniert natürlich bestens wenn man einzelne Aufnahmen auslösen will, aber er versagt, wenn man regelmäßig Aufnahmen für Zeitraffer (Time-Lapse) Filme machen möchte.Auch sensorgesteuerte Aufnahmen (Bewegungsmelder, Akustikmelder etc.) sind mit der einfachen Fernbedienung natürlich nicht so einfach realisierbar. Hier kann der Arduino Abhilfe schaffen.

Die Hardware:

Fernauslöser

IR-Leuchtdiode an Pin 13 und GND

Als Hardware benötigt man eine IR-Leuchtdiode und einen Arduino (in meinem Fall ein Arduino Uno). Die Leuchtdiode wird einfach (richtig herum) direkt auf dem Arduino-Board in Pin 13 und GND gesteckt. Der Ausgang an Pin 13 ist schon mit einem Vorwiederstand ausgerüstet. Ich habe die IR-Leuchtdioden TSAL6200 (940nm) und TSFF5210 (870nm) getestet, beide funktionieren bestens als Fernauslöser für Nikon Kameras.

Das Timing:

Zunächst einmal muss man wissen, welches Signal die Kamera dazu bringt, eine Aufnahme zu auszulösen. Dafür kann man einigen Aufwand betreiben und das IR-Signal des original Fernauslösers (hier zum Beispiel der Nikon Fernauslöser ML-L3) analysieren. Oder man sieht im Internet nach, ob das vielleicht schon mal jemand gemacht hat. Natürlich hat das längst vor mir jemand analysiert. Hier die Arbeit von bigmike.it: OML-L3 : the open hardware project to build an inexpensive and customizable infrared remote control for Nikon cameras. Darauf aufbauend gibt es eine Menge Arbeiten, die sich mit dem Timing der IR-Fernauslöser der unterschiedlichen Kamera-Hersteller beschäftigen. Eine Übersicht findet sich zum Beispiel in diesem Fred im DSLR-Forum.

Die Software:

Auch dafür sollte sich im Netz eigentlich genügend Beispielscode finden lassen – zum Beispiel hier:

Leider verstehe ich solchen Code meist erst wirklich, wenn ich ihn auseinander nehme und selbst nachprogrammiere. Ich habe mir dafür vor allem die Multi Camera IR Control Library von Sebastian Setz als Vorbild genommen. Daraus habe ich mir einen schlanken Fernauslöser für meine Nikon D50 gezimmert. Sebastians Library unterstützt übrigens neben Nikon Kameras auch Geräte von Canon, Olympus, Pentax, Sony und Minolta.

Hier also der Sourcecode meines Fernauslösers für Nikon Kameras (D90, D80, D70, D70s, D60, D50, D40, D40x, D3000, D5000, D7000, Coolpix 8800, 8400, P6000 usw.):

— schnipp —

#include "WProgram.h"

int pin = pin;
int freq = 40;

void wait(unsigned int time)
{ unsigned long start = micros();
  while(micros()-start<=time)
  {
  }
}

void high(unsigned int time, int freq, int pinLED)
{ int pause = 1000/freq/2/2;
  unsigned long start = micros();
  while(micros()-start<=time)
  { digitalWrite(pinLED,HIGH);
    delayMicroseconds(pause);
    digitalWrite(pinLED,LOW);
    delayMicroseconds(pause);
  }
}
void shotNow(void)
{ high(2000,freq,pin); wait(27830);
  high(390,freq,pin);  wait(1580);
  high(410,freq,pin);  wait(3580);
  high(400,freq,pin);
}

void setup()
{ pinMode(pin, OUTPUT);
}

void loop()
{ shotNow();
  delay(5000);
}

— schnapp —

Dieses Programm löst zuverlässig etwa alle fünf Sekunden eine Aufnahme aus. Zuvor muss die Kamera natürlich in den Fernauslöser-Modus versetzt worden sein (Siehe zum Beispiel in den Kommentaren zum TV-Fernbedienungs Fernauslöser)

Werbung:

Weblinks:

Arduino bestellt

Ich habe mir einen Arduino bestellt.

Blöderweise streiken streikten die spanischen Fluglotsen, was offenbar dazu geführt hat, dass mein Arduino in irgendeiner Kiste am Flughafen Madrid vor sich hin idled. Sei’s drum, dann kann ich mich wenigstens schon mal in Ruhe auf seine Ankunft vorbereiten.

Beim Programmieren erwarte ich eher keine Probleme (C ist sozusagen meine Muttersprache) aber ob ich immer die richtigen Strippen in die richtigen Löcher stecke, bleibt noch abzuwarten. Hier ein kurzer Vorgeschmack auf das, was mich erwartet: “Start mit Arduino 1/2” und “Start mit Arduino 2/2

Werbung: