Zum Inhalt springen

www.hotcar.de

Modellbau, Robotik, Mikrocontroller

Archiv

Kategorie: Arduino

DFRobot bietet auch einstellbare Infrarot Sensoren an. Mit ihren runden, schraubbaren Gehäuse sehen sie schon fast aus als wären sie für die Industrie gefertigt. Die Elektronik ist fest vergossen und hinten befindet sich ein Trimer mit dem man die Empfindlichkeit von 3-80cm einstellen kann. Sie passen in die mit dem 4WD Chassis mitgelieferten Haltern.

Ganz wichtig, sie Sensoren sind LOW aktiv, heißt wenn sie schalten ziehen sie den Ausgang auf GND. Ein Tatsache wegen der ich mich lange über das verhalten von Julia gewundert habe. :-)

Erwähnenswert ist noch das sie ein Problem mit der Erkennung  von dunklen Oberflächen haben. Das ist bei Infrarotsensoren ja auch normal und man kann es ihnen erst einmal nicht vorwerfen. Wir haben aber einen schwarzen Blumentopf der für die Sensoren nahezu unsichtbar ist. Der Sharp GP2D12 erkennt ihn allerdings problemlos.

Aufgrund dessen, der Größe und dem Stromverbrauch von 100mA werde ich in Zukunft aber wieder auf die Eigenbausensoren mit einem ISF471 zurückgreifen.

Viel mehr gibt es darüber nicht zu berichten, an einem Digitaleingang angeschlossen liest man die Sensoren einfach mit "digitalRead(portpin);" aus. Hier wieder ein Auszug aus Julias Arduino Code (diesmal nur ein Teil des Code, also nicht funktionsfähig):

for(int i=11;i< =13;i++)
  {
    pinMode(i, INPUT);
  }
...
  int right = digitalRead(11);
  int middle = digitalRead(12);
  int left = digitalRead(13);
...
 if((left==1&&middle==1&&right==0)||(left==1&&middle==0&&right==0))
  {
    turn_L (140,140);
  }
  else if ((left==0&&middle==1&&right==1)||(left==0&&middle==0&&right==1))
  {
    turn_R (140,140);
  }
 
...

Auf meinem Roboter Julia habe ich auch das DFRobot DHT11 Luftfeuchtigkeit und Temperatur Modul verbaut. Da hat Julia zwar nichts von, aber ich mag alle Arten von Sensoren :-)

Der DHT11 ist ein 1-Wire Sensor mit digitalem Ausgang. Er verbraucht also nur einen Portpin. In meinem Fall ist es Pin3, eigentlich einer der Analogeingänge, man kann ihn aber auch als digitalen Eingang verwenden.

Näheres zum Sensor findet ihr im Datenblatt .

Bei DFRobot gibt es auch ein ZipFile mit Beispiel Code für den Arduino. Diesen Code verwende ich auch, ich spreche den Sensor alle 5 Sekunden über die Metro library an.

Bei einer Messgenauigkeit von +/- 5% bei der Luftfeuchte und +/-2C bei der Temperatur darf man natürlich keine wunder erwarten.

Verglichen mit einer digitalen Wetterstationen arbeitet er, zumindest bei der Temperatur recht genau.Bei der Luftfeuchtigkeit sieht das allerdings anders aus. Hier mal ein Bild der seriellen Konsole, die Wetterstation zeigt gleichzeitig 45% und 23,4 °C.

Der Unterschied bei der Luftfeuchtigkeit ist doch schon deutlich, dabei traue ich der Wetterstation ein wenig mehr. Aber wie gesagt, bei dem Preis des Sensors erwarte ich kein Wunder an Genauigkeit.

Hier ein funktionierender Auszug aus Julias Code:

 
#include
#define DHT11_PIN 3
 
Metro dhtl11Metro = Metro(5000); 
 
void setup(void)
{
 Serial.begin(115200);
 Serial.print ("** DHT11 "); Serial.print (__DATE__); Serial.print (" "); Serial.println (__TIME__);
 delay(500);
}
 
void loop(void)
{
 if (dhtl11Metro.check() == 1) {
 outdht11();
 }
}
 
byte read_dht11_dat()
{
 
 byte i = 0;
 byte result=0;
 for(i=0; i< 8; i++)
 {
 while(!(PINC & _BV(DHT11_PIN)));  // wait for 50us
 delayMicroseconds(30);
 if(PINC & _BV(DHT11_PIN))
 result |=(1<<(7-i));
 while((PINC & _BV(DHT11_PIN)));  // wait '1' finish
 }
 return result;
}
 
void outdht11(void)
{
 DDRC |= _BV(DHT11_PIN);
 PORTC |= _BV(DHT11_PIN);
 
 byte dht11_dat[5];
 byte dht11_in;
 byte i;// start condition
 // 1. pull-down i/o pin from 18ms
 PORTC &= ~_BV(DHT11_PIN);
 delay(18);
 PORTC |= _BV(DHT11_PIN);
 delayMicroseconds(40);
 DDRC &= ~_BV(DHT11_PIN);
 delayMicroseconds(40);
 
 dht11_in = PINC & _BV(DHT11_PIN);
 if(dht11_in)
 {
 Serial.println("dht11 start condition 1 not met");
 return;
 }
 delayMicroseconds(80);
 dht11_in = PINC & _BV(DHT11_PIN);
 if(!dht11_in)
 {
 Serial.println("dht11 start condition 2 not met");
 return;
 }
 
 delayMicroseconds(80);// now ready for data reception
 for (i=0; i&lt;5; i++)
 dht11_dat[i] = read_dht11_dat();
 DDRC |= _BV(DHT11_PIN);
 PORTC |= _BV(DHT11_PIN);
 byte dht11_check_sum = dht11_dat[0]+dht11_dat[1]+dht11_dat[2]+dht11_dat[3];// check check_sum
 if(dht11_dat[4]!= dht11_check_sum)
 {
 Serial.println("DHT11 checksum error");
 }
 Serial.print("Current humdity = ");
 Serial.print(dht11_dat[0], DEC);
 Serial.print(".");
 Serial.print(dht11_dat[1], DEC);
 Serial.print("%  ");
 Serial.print("temperature = ");
 Serial.print(dht11_dat[2], DEC);
 Serial.print(".");
 Serial.print(dht11_dat[3], DEC);
 Serial.println("C  ");
}

Mit  der Lieferung von DFRobot bekam ich auch einen 6DoF Robotarm. Im Shop ähnelte er sehr den Armen von Lynxmotion, nur das er deutlich Preiswerter war. Also ging ich das Risiko ein und wurde nicht enttäuscht.

Geliefert wurde eine große Tüte mit allen Teilen, darunter sogar eine original Lynxmotion Base und die Blechteile sehen den dortigen auch sehr ähnlich. An Servos liegen drei von Hitec und drei mit DFRobot Label bei. Bei letzteren zwei sehr Starke  mit Metallgetriebe. Eine Anleitung fehlt und die ist auch im Web nicht zu finden.

Die Base ist, wie gesagt, ein Original, das Servo DF05bb wird im Fuß  und die Drehplatte direkt, wie ein Servohorn verschraubt. Gelagert ist das ganze auf mehreren Lagern, Kunststoffkugeln die mit einer Metallachse im Fuß liegen.

Den weiteren Aufbau könnt ihr in den Bildern sehen. An Schulter und Ellenbogen sind die 15KG DFRobot Servos verbaut, die Hitec Servos bilden Greifer und Handgelenk. Erwähnenswert sind noch die Gegenlagern die mit Bundkugellager versehen sind. Das Ganze macht einen sehr Passgenauen und wertigen Eindruck.

Nachdem er dann vor mir stand stellte ich aber fest das die Bewegung des Greifers sehr eingeschränkt und der Greifer durch die drei Servos sehr schwer war.  Um die ganze Konstruktion und somit auch die Programmierung zu vereinfachen, beschloss ich  ihn fürs erste auf 5DoF umzubauen. Hierzu fräste ich mir eine Aluplatte zur Verbindung des Ellenbogen und Handgelenk Servos, sowie eine Kunststoffplatte um den Greifer mit Handgelenk zu verbinden. Bei dem Umbau wurden keine Originalteile verändert, so das ich jederzeit auch wieder umrüsten kann. Den Arm habe ich dann zusammen mit einem Arduino und IO-Shield auf eine Holzplatte verschraubt.

Ein erster Test mittels Servo-Firmata und einer Firmata Testsoftware (Firmata.org) sah sehr gut aus. Die Servos haben kein Problem den Arm zu heben, der Greifer hält einen Kugelschreiber und euch mit einem deutlich schwereren Schraubendreher hat er keine Probleme. Nur die Stromversorgung über den Spannungsregler des Arduino bricht natürlich gnadenlos zusammen. Ein Labornetzteil mit 6V/3A versorgt ihn aber ausreichend.

Ziel soll es sein ihn mittels Inverser Kinematik (link: 1,2), aus dem PC heraus zu steuern. Das muss aber noch etwas warten, im Moment beschäftige ich mich eher mit "Julia".

Kürzlich habe ich die Webseite von DFRobot gefunden. Ich hatte schon früher über Ebay einige ihrer Arduino Shields und das Arduino kompatible Romeo Board gekauft. Laut Webseite sind sie die größten Lieferanten von Hobby Roboter Teilen in China und die Auswahl ist wirklich gut.

Kurzum ich habe bestellt. Via Paypal bezahlt, hatte ich die Teile nach gut 10Tagen in Händen. Dabei habe ich selbst noch für einige Tage Verzögerung gesorgt weil ich meine Telefonnummer nicht angegeben hatte, die braucht der Versender aber wohl. Das Paket wurde durch DHL geliefert und dabei war dann noch die Einfuhrumsatzsteuer fällig.

Mit dabei die 4WD Roboter Platform und einiges Zubehör.

Das Chassis besteht aus sechs robusten Aluminiumteilen und ist ca 200x100 groß. Der Antrieb besteht aus vier Getriebemotore die einen nicht ganz so robusten Eindruck machen. Die Räder entsprechen von der Größe her 1:10 Moddelbaurädern haben aber eine direkte Aufnahme für die Motorenachsen. Daneben noch ein paar Kleinteile zur Sensorbefestigung und alles benötigte um es zu verdrahten. Eine Anleitung liegt nicht bei, es gibt aber entsprechende Anleitungsvideos welche  keine Fragen offen lassen.

Ich habe gleich passende  Radencoder mitbestellt. Dies sind zwei Gabellichtschranken mit digitalem Ausgang und einer Schlitzscheibe die direkt an den Getrieben an der Radachse befestigt wird. Leider passen sie nicht ganz in das Chassis so das ich sie über einen  selbst gebauten Adapter/Abstandhalter um 90Grad versetzt angebaut habe. Nachdem ich noch das Chassis etwas bearbeitet habe passt es perfekt.

Nachdem ich dann das schon vorhandene Romeo Board aufgebaut habe gab es eine ersten Test. Leider zeigte sich das der mit Eneloop Akkus bestückte fünf AA Batteriehalter zu wenig Strom liefert und der Roboter auf Teppich somit nicht drehen konnte.  Als Ersatz gab es einen LifePo4 Empfängerakku aus einem meiner Großmodelle. Der hat mit 6,6 Volt auch noch eine etwas höhere Spannung kann aber auf jeden Fall auch den benötigten Strom liefern.

Mit dem zum Romeo Board gehörenden Beispielprogramm zur Motorsteuerung gab es erste Bewegungen. Fernsteuerung des jetzt "Julia" getauften Roboters,  über die Serielle Schnittstelle. Mit dem verbauten Bluetooth Adapter auch über Funk.

Mit der Android App "BlueTerm" dann auch über mein HTC Legend. Im Bild seht ihr noch wie ich die Analog Ports auslese und über einen DHT11 Temperatur und Luftfeuchtigkeit anzeige.

Zuletzt verbaute ich noch eine  Pan-Tilt Einheit mit einem Sharp gp2d12 Sensor. Sobald ich aber die Servos benutzte wurde einer der Motoren nicht mehr angesteuert. Hier habe ich eine alte Version des Romeo Boards bei dem Pin 9 für die Motorsteuerung benutzt wird.  Wie schon früher (Artikel) festgestellt kann man Pin 9 aber nicht mehr als PWM nutzen wenn man die Servo Lib benutzt. Aus dem Grund modifizierte ich das Board so das nun Pin5 genutzt wird.

So fährt Julia nun via Handy Fernsteuerung durch die Wohnung, überträgt Messwerte und verhindert das ich irgendwo gegen fahre. Details zur Software kommen in einem weiteren Artikel.

Angeregt durch eine Kommentar von Kucky habe ich mich mit der Kombination Eclipse und Arduino beschäftigt. Eine Suche in Google zeigt das ich da nicht der erste war. Ich konnte also mal wieder auf das geballte wissen des WWW zurückgreifen.

Gestartet wird normalerweise mit der Installation von Java, WinAvr, Eclipse  und den benötigten Plugins. Das hatte ich alles schon, daher hier nur der Link zu einem guten Tutorial: Eclipse Tutorial

Die nächsten Schritte sind dann das Erstellen eines Projektes, Arduino Header und Lib hinzufügen und schon sollte das ganze laufen.
Auch hier hat schon jemand Vorarbeit geleistet und stellt sogar seine Eclipse Projekte zum Download bereit. Er geht dabei sogar soweit das er ein eigenes Projekt zum erstellen der Arduino Library erstellt hat. Das ist sicherlich auch nicht verkehrt, kann man so ja auch mal schnell in den Source schauen oder vielleicht auch mal etwas "verbessern" :-) Hier geht es zum Beitrag

Die Projekte werden einfach in den Eclipse Workspace entpackt und mittels Import/Existing Projects... importiert. Bei einem ersten Versuch zu compilieren ist natürlich Ersteinmal alles rot. Es müssen einige Pfadangaben in den Projekteigenschaften angepasst werden. Auch das ist auf der Seite erklärt, ich habe es aber ein wenig abgewandelt.

Im Projekt zum erzeugen der Core Library werden Include Pfade auf den Arduino Installations Ordner gesetzt. Da aber auch alle Sourcen und Header im Projekt liegen ist das nicht nötig.  Nachdem die Include Pfade für Compiler und LInker auf "${workspace_loc:/ArduinoCore}" gesetzt sind kann man die libArduinoCore.a auch schon erzeugen.

Beim zweiten Blinky Demoprojekt sieht es ähnlich aus. Auch hier habe ich den Include Pfad des Compilers nach "${workspace_loc:/ArduinoCore}" geändert. Der Linker bekommt die neu erstellte Lib (nur "ArduinoCore" ) aus "${workspace_loc:/ArduinoCore/Release}" So konnte ich schon eine Blinky Applikation erstellen.

Probleme gab es aber beim Upload auf den Arduino.

stk500_getsync(): not in sync: resp=0x00

Selbst nachdem ich die Einstellungen aus dem Artikel übernommen hatte bekam ich Fehler. Grund war hier eine zu alte Version von AVRDude. Den Hinweis darauf habe ich hier gefunden:

"The Arduino environment issues a reset command prior to uploading. Newer versions of AVRDude (such as the one shipped with CrossPack) will also do this. If you have an older version and are using Windows, you can overcome this problem with this little app"

Der Upload lief aber noch immer nicht. Auf meinen "Roboduino Duemilanove" Boards ist ein Atmega 168 verbaut, die Anleitung/Projekte waren aber für den Atmega328 ausgelegt dessen Bootloader eine andere Bautrate benutzt und meine Lib und App würden vermutlich auch nicht laufen.
Auch dies lässt sich aber schnell in den Projekteingenschaften unter AVR/Target Hardware berichtigen.  Dazu noch unter AVR/AVRDude die Bautrate auf  19200Baud und der Upload auf das Arduino Target lief problemlos.

Meine letzten versuche ein eigenes einfaches  Message Protokoll zur Datenübertragung PC <> Arduino zu schreiben waren nicht besonders erfolgreich. Diverse Probleme mit der Fehlererkennung brachten mich dazu doch lieber im Netz nach einer fertigen Lösung zu suchen.

Gefunden habe ich Firmata, ein auf MIDI basierendes Protokoll, für das es auch fertige Libraries für Arduino und Processing gibt.

Processing basiert auf Java und da ich lieber in Eclipse programmiere, habe ich die Processing libraries dort eingebunden und verzichte so auf die mitgelieferte  IDE.

Arduino Firmware

Als ersten Schritt habe ich das Arduino Board mit der Firmata Firmware bestückt. Die findet man im Examples Ordner der Arduino IDE.

Eclipse Projekt

Die nächsten Schritte betreffen die Vorbereitung des Eclipse Projekts:

  1. Erstellen eines Java Projekts
  2. Den Java Buildpath um die benötigten Libs erweitern
    1. Prozessing Core  (\processing-1.0.9\lib\core.jar)
    2. Serial  (\processing-1.0.9\libraries\serial\library\serial.jar)
    3. RXTXcomm (\processing-1.0.9\libraries\serial\library\RXTXcomm.jar)
    4. Arduino  (download von http://www.arduino.cc/playground/uploads/Interfacing/processing-arduino-0017.zip )
    5. Die reichen erst einmal für anfängliche Tests, vermutlich braucht man später noch mehr.
  3. Die eigene Klasse erweitert processing.core.PApplet und überschreibt die setup() und die draw() Methode.  So ist es schon lauffähig  und man bekommt ein kleines Applet Fenster.
import processing.core.*;
import cc.arduino.*;
 
public class arduino_blink extends PApplet
{
	public void setup()
	{
	   //TODO
	}
 
	public void draw()
	{
	   //TODO
	}
}

Blink App

Jetzt eine einfache kleine Blink Applikation in Eclipse.

import processing.core.*;
import cc.arduino.*;
 
public class arduino_blink extends PApplet
{
	private Arduino arduino = null;
	private int ledPin = 13;
	private int state = Arduino.LOW;
 
	public void setup()
	{
		arduino = new Arduino(this, Arduino.list()[1], 57600);
		arduino.pinMode(ledPin, Arduino.OUTPUT);
	}
 
	public void draw()
	{
		try
		{
			if (state==Arduino.LOW)	state = Arduino.HIGH;
			else state = Arduino.LOW;
 
			arduino.digitalWrite(ledPin, state);
			Thread.sleep(1000);
		}
		catch (InterruptedException e)
		{
			e.printStackTrace();
		}
	}
}

Eigentlich schon selbsterklärend. In der setup Methode wird ein Arduino Objekt erzeugt. Dem wird über this eine Instanz von PApplet, der Serielle Port und die Bautrate übergeben.

Über das Arduino Objekt kann man dann den LED Pin 13 auf Ausgang stellen.

Weiter geht es in der draw Methode, die kontinuierlich durchlaufen wird. In einer if/else abfrage wird der "state" zwischen High und Low  gewechselt und im Arduino gesetzt. Zuletzt wird noch eine Sekunde in einem Thread.sleep gewartet. Da dieser auch eine Exception werfen kann muss noch ein try/catch drumherum und fertig ist die Blink Applikation.

SWT Applikation

Zuletzt dann noch eine SWT Anwendung. Die SWT Lib (swt-win32-3139.jar) muss noch zum Buildpath hinzugefügt werden. Im Beispiel schaltet ein Toggle Button die LED des Arduino an und aus.

import org.eclipse.swt.SWT;
import org.eclipse.swt.events.SelectionAdapter;
import org.eclipse.swt.events.SelectionEvent;
import org.eclipse.swt.layout.RowLayout;
import org.eclipse.swt.widgets.Button;
import org.eclipse.swt.widgets.Display;
import org.eclipse.swt.widgets.Shell;
 
import processing.core.*;
import cc.arduino.*;
 
public class Arduino_test2
{
	private Arduino mArduino = null;
	private int mLedPin = 13;
	private PApplet mPApplet=null;
	private int mState=Arduino.LOW;
	private Button mButton= null;
 
	public static void main(String[] args)
	{
		Arduino_test2 a= new Arduino_test2();
	}
 
	private Arduino_test2()
	{
		Display display = new Display();
	    Shell shell = new Shell(display);
	    shell.setText("Arduino_test2");
	    shell.setSize(200, 150);
	    initArduino();
	    initGui(shell);
	    shell.open();
	    while(! shell.isDisposed()) {
	      if(! display.readAndDispatch())
	      {
	        display.sleep();
	      }
	    }
	    mPApplet.exit();
	    display.dispose();
	}
 
	private void initGui(Shell shell) {
		shell.setLayout(new RowLayout());
	    mButton = new Button(shell, SWT.TOGGLE);
	    mButton.setText("on");
	    mButton.addSelectionListener(new SelectionAdapter() {
	          public void widgetSelected(SelectionEvent e) {
	        	  if (mButton.getSelection())
	        		  mState=Arduino.HIGH;
	        	  else
	        		  mState=Arduino.LOW;
 
	        	  updateArduino();
	            };
	          });
	}
 
	private void updateArduino() {
		mArduino.digitalWrite(mLedPin, mState);
	}
 
	private void initArduino()
	{
		mPApplet = new PApplet();
		mPApplet.init();
		mArduino = new Arduino(mPApplet, Arduino.list()[1], 57600);
		mArduino.pinMode(mLedPin, Arduino.OUTPUT);
	}
}
 

...

IMG_3872Darf ich vorstellen: "Daisy" mein neuster Streich. Komplett aus drei und 8mm starkem Makrolon gebaut. Als Antrieb zwei gehackte Standardservos ohne eigene Elektronik. Das Stützrad oder besser gesagt die Stützkugel hatte ich noch von Donald übrig.

Wie schon in einem früheren Beitrag beschrieben hat Daisy Wegstreckensensoren vom Typ CNY70 die direkt an einem analog Port des Atmega 168 hängen. Vorne gibt es noch zwei LEDs (neben dem blauen Wannenstecker) von denen ich mir erhofft hatte das sie das Makrolon zum strahlen bringen und mir optische Rückmeldungen geben sollen (dummerweise habe ich genau die Schraubenlöcher getroffen :-( ).

Auf dem kleinen Turm eine Pan&Tilt Einheit an der im Moment nur ein GP2D12 befestigt ist. Hier hatte ich eigentlich auch eine Pollin Funkkamera geplant. Die war aber von der Bildqualität und Übertragungsweite so schlecht das sie gleich wieder zurück geschickt habe.

IMG_3955Als Akku dient ein 6Zellen Pack AA Zellen 7,2V 2000mA. An diesem hängen direkt die Fahrservos. Ein Spannungsregler LM2940 für die beiden anderen und die Sensoren. Zuletzt noch der auf dem Arduino Board befindliche Spannungsregler der die Elektronik versorgt.

Die Elektronik besteht aus drei, eigentlich sogar fünf einzelne Boards. Erste ebene, vorne zwischen den Rädern.  Hier sind die Fahrservos, die Wegsensoren, und die beiden LEDs angeschlossen. In Zukunft werde ich den L293 auch noch hier hin setzen. Von hier geht es über ein Zehnpoliges Kabel zur zweiten Ebene. Hier liegen die Treiberstufen für die LEDs und der LM2940.
Darüber dann das "Roboduino Motor Shield" welches mit seinem L293 die Fahrmotoren ansteuert.
Es folgt das Herz, das Arduino kompatible "Roboduino Duemilanove" mit seinem Atmega 168 mit stolzen 16Mhz. Leicht modifiziert, ich habe nach unten Buchsenleisten angelötet.
Den Abschluss nach  oben bildet das  "Roboduiono I/O Expansion" Shield, an dem die beiden "Kopf" Servos und der Sharp GP2D12 sowie ein kleiner Piezo Lautsprecher angeschlossen sind. Hier findet auch das Bluetooth Modul seinen Platz welches dann die seriellen Daten bis 115200 Baud an den Rechner überträgt.

Aktuell habe ich ein kleines Selbsttest Programm geschrieben welches Daisy auf der Stelle drehen und mittels des Sharp Sensors die Umgebung scannt. Jetzt bin ich dabei ihr das geradeaus fahren bei zu bringen sowie ein Liniensensor ist in der Mache. Wenn denn mal alles funktioniert wird das Elektronik Türmchen gegen ein einzelnes Board ausgetauscht.
Dazu arbeite ich mich im Moment auch in Eagle ein. Aber das ist wieder ein anderes Thema.

PS: Die Bilder zeigen zwei Entwicklungsstufen.




IMG_3851Odometrie die Wissenschaft der Wegmessung/Positionsbestimmung. In meinem Fall dem Zählen der Radumdrehungen meines neuen Roboters "Daisy".

Ich verwende dazu einen CNY 70 Reflexkoppler (Datenblatt Vorsicht, es gibt zwei Typen die nicht Pin kompatibel sind), da dieser recht preiswert ist und sich einfach auswerten lässt. Näheres dazu könnt ihr hier nachlesen. Da ich den Sensor direkt mit einem Analogport auswerten will sind nur zwei Widerstände nötig. Mit meiner selbst gedruckten (Laserjet) Encoderscheiben (Vorlagen bekommt man z.b. hier) bekomme ich aus dem AD/Wandler des Atmega werte von 30 bis 900.  Also deutliche Unterschiede die man gut auswerten kann.

Hier mal meine Schaltung. Da ich selten lange plane nur eine einfache Skizze,  ich denke aber man kann etwas erkennen :-) Der ganze "Schaltplan" stellt die Basis von Daisy dar.  Hier werden die zwei Servomotoren, zwei LEDs und die beiden CNY 70 mit dem Arduino verbunden. Rechts die Belegung des 10pol Flachbandkabel.

IMG_3855



Hier noch ein Teil meines  Testprogramms, die Motoren werden gegenläufig angesteuert, die Odometrie Daten an die serielle Schnittstelle gesendet und bei Werten größer 400 eine LED eingeschaltet. Die selbst geschriebenen Funktionen   spare ich mir, deren Namen sind aussagekräftig genug:

  1.  
  2. motorR (150,0);
  3. motorL (150,1);
  4. Serial.print(" Odometrie Rechts/Links ");
  5. for (int i = 0; i &lt;= 20; i++)
  6. {
  7. int valR = readOdoR();
  8. int valL = readOdoL();
  9. Serial.print(" ");Serial.print(valR,DEC);Serial.print("/");
  10. Serial.print(valL,DEC);Serial.print(";");
  11. delay (50);
  12. if (valR > 400)
  13. {
  14. digitalWrite(PinLedR,HIGH);
  15. }
  16. else {
  17. digitalWrite(PinLedR,LOW);
  18. }
  19. if (valL > 400)
  20. {
  21. digitalWrite(PinLedB,HIGH);
  22. }
  23. else {
  24. digitalWrite(PinLedB,LOW);
  25. }
  26. }
  27. Serial.println(" ");
  28. motorR (0,0);
  29. motorL (0,0);
  30. delay (1000);
  31.  

In der seriellen Konsole sieht das Ganze dann so aus. Unten noch die Ausgabe des Sharp GP2D12, dabei wird er von einem  Serv0 in der Vertikalen bewegt.


daisyselbsttest



IMG_3871Da ich die Arduino Shields komplett ohne Dokumentation bekommen habe, musste ich mal wieder Google bemühen und fand hier zumindest eine grobe Übersicht mit einigen Beispielprogrammen. Wie man dort auf Seite 12 sieht ist es doch nicht so einfach alle Shields zusammen zu stecken und davon auszugehen das alles läuft. Das Arduino Board hat "nur" 13 digitale Pins die sich alle Shields teilen müssen.

Probleme bekam ich aber auch noch von anderer Seite. Für Roboter "Daisy" verwende ich das Motor und das I/O Shield um mit letzterem ein paar Servos anzusteuern. Sobald ich aber ein Servo.attach(x) aufrief, lief einer der Motoren nur noch in eine Richtung.
Nachdem ich mir den Schaltplan der Schaltung aufgemalt hatte sah ich auch warum. Für enable1 des L293 wird Pin 9 verwendet. Die Pins 9 und 10 kann man zusammen mit der Servo Lib aber nicht verwenden.

Hier ein Auszug aus der Doku:

"This library uses a 16 bit timer for each group of 12 servos so PWM output with analogWrite() for pins associated with these timers are disabled when the first servo is attached to the timer. For example on a standard Arduino board, Timer1 is used, so once you attach a servo, analogWrite on pins 9 and 10 are disabled."

IMG_3881Da ja noch einige PWM Ausgänge übrig sind verwende ich statt Pin9 nun Pin3. So arbeiten Servos und Motor Shield zusammen, nur nach einem Reset läuft der Motor gleich los bis ich ihn ausschalte. Aber damit kann ich ersteinmal leben.

Jetzt kommt das nächste Problem, zwei Servos mit dem Spannungsregler des Arduno Boards versorgen funktioniert nicht. Es gibt sporadische Resets weil die Spannung zusammenbricht. Ist aber auch kein großes Problem,  ich muss nur eine extra Spannungsversorgung in Form eines weiteren 7805/2940 einbauen oder sie einfach nacheinander ansteuern.


Hier noch ein preview auf "Daisy", mehr in kürze.

IMG_3873



IMG_3840

Schon an Roboter Donald hatte ich einen Entfernungssensor Sharp GP2D12 verbaut. Ein Infrarotsensor der in einem Bereich von 10-80cm eine nicht lineare Spannung liefert. Diese kann über den in den AVRs verbauten AD Wandler recht einfach eingelesen werden.

So bekommt man, je nach Entfernung, einen digitalen Wert zwischen 0 und 1023. Bei Donald habe ich mit diesen Wert gearbeitet, schöner wäre natürlich die Umrechnung in cm.

Da die Werte nicht linear sind ist dazu noch ein wenig Mathematik nötig. Auch hier hilft natürlich wieder das Web, auf der Seite acroname.com oder auch kreatives-chaos.com ist es sehr gut erklärt. Kurz gesagt und für meinen Sensor:

R = (6787 / (V - 3)) - 3


Hier noch das passende Programm für einen Arduino. Einlesen des Signals über den Analogen Eingang 3 und Ausgabe auf dem LCD bzw via Bluetooth/serielle Schnittstelle auf dem PC.

// SharpRangeTest
#include &lt;LCD4Bit_mod.h&gt;
LCD4Bit_mod lcd = LCD4Bit_mod(2);
int val;
int distance;
{
Serial.begin(115200);
lcd.init();
lcd.clear();
lcd.printIn("sharp Range Test");
}
void loop()
{
val = analogRead(3);
distance = (6787 / (val - 3)) - 3;
Serial.print("Range: ");
Serial.print(distance, DEC);
Serial.println(" cm  ");
lcd.cursorTo(2,0);
char buf[6];
itoa (distance,buf,10);
lcd.printIn("Range: ");
lcd.printIn(buf);
lcd.printIn(" cm ");
delay(1000);
}