Ein paar sehenswerte Videos von "Prallplatte".
Die Entwicklung des I-Sobot Roboters könnt ihr im Roboternetz verfolgen.
...sind schon unter uns. Gefunden bei Golem. Der Kleine heißt Romo und wird von einem I-Phone gesteuert. Ich wusste schon immer das die Böse sind
Nein, wie so oft steckt der Mensch dahinter, denn Romo wird ferngesteuert.
Weitere Infos findet ihr beim Hersteller: http://romotive.com
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<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.
Wie schon im letzten Beitrag erwähnt wollte/habe ich mir den RA-1 Pro zugelegt. Roboterarme faszinieren mich schon lange und die Gelegenheit einen fertigen, noch dazu aus Alu zu bekommen war verlockend.
Geliefert wird er Teilmontiert in drei großen Baugruppen, Einmal der Sockel, einmal der Arm und einmal der Greifer.
Schon auf den ersten Blick konnte man sehen wie schlampig er verarbeitet ist. Keine Schraube war vernünftig angezogen und die ganze Konstruktion scheint irgendwie nicht zu passen. Dazu kommt das die Servos schon deutliches Spiel haben, auch nicht sehr vertrauenswürdig aussehen und das gesamte Gewicht des Arms auf der Achse des Drehservos lastet. Das kann auch die Dauer nicht funktionieren.
Ich habe ihn dann doch weiter zusammengebaut, als die Mechanik soweit fertig war und es ans anschließen der Servos ging, stellte ich fest das die nicht in die entsprechenden Buchsen auf der Platine passten. Mit etwas Gewalt ging es dann doch, jedoch ist nirgendwo beschreiben wie herum sie angeschlossen werden. Das Durchmessen der Masseleitung zeigte mir zumindest mal wie sie angeschlossen werden.
Soweit sah das nun also gut aus und ich legte Spannung an. Die nächste Hürde war der Einschalter, der diesen Namen nicht verdient, ein wackeliges etwas das man am besten gleich austauscht. Spannung lag nun also an, es blinkt etwas und von den Servos ist nichts zu hören. Aus meiner Modellbauerfahrung weiß ich das die Servos nach einschalten der Spannung ein klein wenig bewegen. Hier kam aber nichts. Ein genauer Blick auf die Platine zeigte das wohl dem Transistor der die Servospannung einschaltet ein Bein fehlt. Kann also nicht funktionieren.
Das könnte man auch noch beheben also weiter, die Software installiert, den Programmieradapter angeschlossen, der auch gleich erkannt wird. Das nun angeschlossene Board aber nicht. Hier war meine Geduld dann auch am Ende. Ich habe das ganze wieder zerlegt und es ging am nächsten Tag zurück. Wie ich im Nachhinein im Arexx Forum gelesen habe bin ich wohl auch nicht der erste der sehr enttäuscht vom RA1-Pro ist.
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.
Als ersten Schritt habe ich das Arduino Board mit der Firmata Firmware bestückt. Die findet man im Examples Ordner der Arduino IDE.
Die nächsten Schritte betreffen die Vorbereitung des Eclipse Projekts:
import processing.core.*; import cc.arduino.*; public class arduino_blink extends PApplet { public void setup() { //TODO } public void draw() { //TODO } }
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.
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); } }
...