Du schreibst dein MC hat nicht genug Flash. Hast du vor die berechnung mauf dem MC zu machen und nciht auf dem Pi?
Ich hätte das auf dem Pi gemacht und nur die gewünschte Trajektorie (Bewegungsablauf) an den MC gesendet der sich dann um die Motoren kümmert.
Entwicklung: RoPi - Autonomer Roboter mit RaspberryPI
-
meigrafd -
7. Juli 2014 um 20:10 -
Erledigt
L
I
V
E
Stammtisch ab 20:30 Uhr im Chat
-
-
Entwicklung: RoPi - Autonomer Roboter mit RaspberryPI? Schau mal ob du hier fündig wirst!
-
Naja so ganz genau weiß ich das noch nicht wie ich das mache... Insbesondere weil ich noch nicht weiß wie viele Datenmengen dabei zusammen kommen und welcher Bus dafür dann am geeignetsten wäre.
Im roboternetz.de Forum war jemand so nett und hat mir ein Tutorial bezüglich Pathfinding gepostet: http://www.roboternetz.de/community/thre…ll=1#post602139
Ich tendiere mittlerweile aber auch dazu mir den meisten Kram selber zu bauen, ich brauch eigentlich keine fertigen Libs usw um Abläufe zu basteln bzw ist bei dem RP6 zum Beispiel ein Problem das in einigen Abläufen waits bzw delays genutzt werden und es somit kein echtes Realtime geben kann.
Der Rover5 Unterbau bzw die Motoren wiederum sind mir zu langsam, der schleicht überwiegend herum - wobei ich anfangs natürlich auch erst mal nur langsam umher fahren werde usw aber später hätt ich schon gerne ein bisschen Speed
Das Problem mit einem Kettenantrieb hab ich ja schon erwähnt, leider sorgt der Schlupf dafür das Encoderdaten verfälscht werden und es dadurch ungenau wird. Besser wären also richtige Reifen.
Ich brauch also ein Chassis wie den MakeBlock nur mit Reifen, mind. 2 Motoren sowie 2 Encoder - aber leider finde ich nirgends die Encoder von MakeBlock...
Aber auch das würde recht teuer werden: Mit passendem Driver usw käme man auf gut 120eu (MakeBlock + Timing Pulley + Reifen + Encoder + Driver)
Eine bessere Alternative hab ich bisher leider nicht gefunden - im ersten Beitrag hatte ich hier aber ja schon einige Einzelteile gepostet wie Motor Driver, die gut geeignet wären... Nur das passende Chassis fehlt weiterhin
Ich würd halt gern schon mal anfangen mir die Firmware usw zu basteln und erste Gehversuche zu unternehmen - ich denk wenn ich erstmal sehe wie die Daten aussehen die ich da von den Sensoren kriege fällt es mir auch leichter eine GUI usw zu entwickeln
-
Hi, alter Bastler ...
so was -> hier <- tut es nicht?
Wie schon mal erwähnt, evtl. Stepper mit Getriebe?
cu,
-ds- -
Ist der Motor denn auch passend für den MakeBlock?
-
Hi,
ich weiss nicht ... hm ... mir ist auch nicht so ganz klar, was Du Dir da genau vorstellst :s
Muss es denn dieses -> MakeBlock <- Chassis sein? Das ist - lt. Link - imho eh relativ primitiv ...
Hast Du schon mal in den Modellbau-Ecken rumgestöbert?
Ich hab' hier - allerdings nicht für den RPi gedacht - einen Buggy von Ansmann ... das Chassis wäre sicher auch in Verbindung mit einem RPi zu verwenden. Oder einen Monstertruck als Fahrgestell?
Es ist halt ziemlich schwierig so aufs Geratewohl das was zu finden ...cheers,
-ds- -
Ich hab schon mal angefangen ein bisschen am Code zu basteln und wie üblich poste ich meine bisherigen Erkenntnisse damit auch ich selber hier später eine Übersicht hab
Wie bereits erwähnt hab ich mir den TB6612FNG Motor Driver bestellt, da der aus meiner sicht die einfachste Funktionalität bietet:
(die Reihenfolge der Pins meines von Sparkfun ist etwas anders aber die selben Pins)Oben links angefangen:
- GND -> Microcontroller GND
- VCC -> VCC vom Microcontroller (2.7V - 5.5V)
- AO1 -> Output zum Minuspol (-) des A Motor's (links)
- AO2 -> Output zum Pluspol (+) des A Motor's (links)
- BO2 -> Output zum Pluspol (+) des B Motor's (rechts)
- BO1 -> Output zum Minuspol (-) des B Motor's (rechts)
- VMOT -> Pluspol der Stromversorgung für die Motoren (max 15V)
- GND -> Minuspol der Stromversorgung für die Motoren
Oben rechts angefangen:
- PWMA -> PWM pin vom Microcontroller für Motor A
- AIN2 -> digital pin vom Microcontroller für Motor A
- AIN1 -> digital pin vom Microcontroller für Motor A
- STBY -> digital pin vom Microcontroller (muss auf OUTPUT, HIGH gestellt werden damit der Driver an ist. Auf LOW bedeutet das der Driver im Standby ist und kein Strom verbraucht. Kann auch auf VCC gelegt werden für 'immer an')
- BIN1 -> digital pin vom Microcontroller für Motor B
- BIN2 -> digital pin vom Microcontroller für Motor B
- PWMB -> PWM pin vom Microcontroller für Motor B
- GND -> GND vom Microcontroller
Zum Vorwärts fahren müsste man AIN1 auf HIGH und AIN2 auf LOW stellen damit sich Motor A in eine Richtung dreht. Für die andere Richtung dann eben umgedreht: AIN1 auf LOW und AIN2 auf HIGH.
Über den jeweiligen PWM pin kann die Geschwindigkeit festgelegt werden. Aufgrund von unterschiedlichen Motoren (auch selben Models) kann es vorkommen dass der eine Motor auf 255 und der andere auf zB 249 laufen muss damit der Roboter gerade aus fährt - diesen Umstand muss man leider in der Feinabstimmung jeder für sich vornehmen.Nun hab ich angefangen zu coden und hab erstmal eine RoPi_config.h erstellt:
Spoiler anzeigen
C
Alles anzeigen// // RoPi - global config // #include <arduino.h> //------------------------------------------------------------------------------ #define SERIAL_BAUD 115200 // HC-SR04 //5V on Arduino to VCC of HC-SR04 //Pin 10 of Arduino to TRIG of HC-SR04 //Pin 11 of Arduino to ECHO of HC-SR04 //GND of Arduino to GND of HC-SR04 #define ULTRASONIC_TRIG 10 #define ULTRASONIC_ECHO 11 #define MAX_DISTANCE 500 /**< maximum distance to track with sensor (in centimeters). Maximum sensor distance is rated at 400-500cm. */ #define MIN_DISTANCE 0 /**< minimum distance to track with sensor */ #define PING_INTERVAL 33 // Milliseconds between sensor pings (29ms is about the min to avoid cross-sensor echo). // TB6612FNG Motor Driver /*Pins for the left track*/ #define PWMA 3 #define AIN1 0 #define AIN2 1 /*Pins for the right track*/ #define PWMB 5 #define BIN1 2 #define BIN2 4 #define STBY 6 #define LED 7
Da ich den Motor Driver an einen Arduino anschließen werde (vermutlich nehme ich einen UNO oder PRO MINI) hab ich dafür einen vorläufigen Sketch motor_driver.ino erstellt:
(UNVOLLSTÄNDIG!)Spoiler anzeigen
C
Alles anzeigen/* Um Befehle vom RaspberryPI zu empfangen und fuer den MotorDriver umzusetzen version 0.3 by meigrafd */ //------------------------------------------------------------------------------ #include <stdint.h> #include "RoPi_config.h" #include <NewPing.h> // http://code.google.com/p/arduino-new-ping/ //------------------------------------------------------------------------------ NewPing sonar(ULTRASONIC_TRIG, ULTRASONIC_ECHO, MAX_DISTANCE); // NewPing setup of pins and maximum distance char string[25]; char id[2]; char direct[2]; int ii=0; unsigned long pingTimer; unsigned int distanceCM; //------------------------------------------------------------------------------ static void motorDriverState (byte state) { pinMode(STBY, OUTPUT); digitalWrite(STBY, state); } // http://robotic-controls.com/learn/arduino/splitting-string void splitString(char* chars) { char val1[15]={}; char val2[15]={}; int i=0; int cnt_id,cnt_val1,cnt_val2; //get identifier while(chars[i] != ':' && i<25) { i++; if (chars[i] == ':' || chars[i]=='\0') { for(int j=0;j<i;j++) { id[j] = chars[j]; cnt_id=j; } id[cnt_id+1]='\0'; //Serial.println(id); } } i++; //skips the ":" while(chars[i] != '\0' && i<25) { i++; if (chars[i] == ':' || chars[i]=='\0') { for(int j=cnt_id+2;j<i;j++) { direct[j-(cnt_id+2)] = chars[j]; cnt_val1=j-2; } direct[cnt_val1+1]='\0'; //Serial.println(direct); } } } //unused String getValue(String data, char separator, int index) { int found = 0; int strIndex[] = {0, -1}; int maxIndex = data.length()-1; for(int i=0; i<=maxIndex && found<=index; i++){ if(data.charAt(i)==separator || i==maxIndex){ found++; strIndex[0] = strIndex[1]+1; strIndex[1] = (i == maxIndex) ? i+1 : i; } } return found>index ? data.substring(strIndex[0], strIndex[1]) : ""; } void goFWD(int pwmWert) { digitalWrite(AIN1, HIGH); digitalWrite(AIN2, LOW); digitalWrite(BIN1, HIGH); digitalWrite(BIN2, LOW); analogWrite(PWMA, pwmWert); analogWrite(PWMB, pwmWert); } void goREV(int pwmWert) { digitalWrite(AIN1, LOW); digitalWrite(AIN2, HIGH); digitalWrite(BIN1, LOW); digitalWrite(BIN2, HIGH); analogWrite(PWMA, pwmWert); analogWrite(PWMB, pwmWert); } void rotateLeft(int pwmWert) { digitalWrite(AIN1, LOW); digitalWrite(AIN2, HIGH); digitalWrite(BIN1, HIGH); digitalWrite(BIN2, LOW); analogWrite(PWMA, pwmWert); analogWrite(PWMB, pwmWert); } void rotateRight(int pwmWert) { digitalWrite(AIN1, HIGH); digitalWrite(AIN2, LOW); digitalWrite(BIN1, LOW); digitalWrite(BIN2, HIGH); analogWrite(PWMA, pwmWert); analogWrite(PWMB, pwmWert); } //only one side, left track void rotateLeft1f(int pwmWert) { digitalWrite(AIN1, LOW); digitalWrite(AIN2, HIGH); digitalWrite(BIN1, LOW); digitalWrite(BIN2, LOW); analogWrite(PWMA, pwmWert); analogWrite(PWMB, pwmWert); } //only one side, left track void rotateRight1f(int pwmWert) { digitalWrite(AIN1, HIGH); digitalWrite(AIN2, LOW); digitalWrite(BIN1, LOW); digitalWrite(BIN2, LOW); analogWrite(PWMA, pwmWert); analogWrite(PWMB, pwmWert); } //only one side, right track void rotateLeft1r(int pwmWert) { digitalWrite(AIN1, LOW); digitalWrite(AIN2, LOW); digitalWrite(BIN1, LOW); digitalWrite(BIN2, HIGH); analogWrite(PWMA, pwmWert); analogWrite(PWMB, pwmWert); } //only one side, right track void rotateRight1r(int pwmWert) { digitalWrite(AIN1, LOW); digitalWrite(AIN2, LOW); digitalWrite(BIN1, HIGH); digitalWrite(BIN2, LOW); analogWrite(PWMA, pwmWert); analogWrite(PWMB, pwmWert); } void Stop() { digitalWrite(AIN1, LOW); digitalWrite(AIN2, LOW); digitalWrite(BIN1, LOW); digitalWrite(BIN2, LOW); analogWrite(PWMA, 0); analogWrite(PWMB, 0); } /* void drive(byte Aone, byte Atwo, byte Bone, byte Btwo, int pwmWert) { digitalWrite(AIN1, Aone); digitalWrite(AIN2, Atwo); digitalWrite(BIN1, Bone); digitalWrite(BIN2, Btwo); analogWrite(PWMA, pwmWert); analogWrite(PWMB, pwmWert); } */ //------------------------------------------------------------------------------ void setup() { Serial.begin(SERIAL_BAUD); motorDriverState(HIGH); // turn driver ON pinMode(PWMA,OUTPUT); pinMode(AIN1,OUTPUT); pinMode(AIN2,OUTPUT); pinMode(PWMB,OUTPUT); pinMode(BIN1,OUTPUT); pinMode(BIN2,OUTPUT); pinMode(LED,OUTPUT); pingTimer = millis() + PING_INTERVAL; // ping starts at PING_INTERVAL ms, gives time for the Arduino to chill before starting. } // cmd: f:255 --> vorwaerts mit pwm 255 //This routine is run between each time loop() runs void serialEvent() { int i=0; if (Serial.available()) { delay(50); while(Serial.available()) { string[i++] = Serial.read(); } string[i++]='\0'; splitString(string); if (id[0] == 's') { Stop(); Serial.print(id[0]); Serial.print(" "); Serial.print(direct[0]); } if (id[0] == 'f') { goFWD(direct[0]); Serial.print(id[0]); Serial.print(" "); Serial.print(direct[0]); } if (id[0] == 'r') { goREV(direct[0]); Serial.print(id[0]); Serial.print(" "); Serial.print(direct[0]); } if (id[0] == 'll') { rotateLeft(direct[0]); Serial.print(id[0]); Serial.print(" "); Serial.print(direct[0]); } if (id[0] == 'rr') { rotateRight(direct[0]); Serial.print(id[0]); Serial.print(" "); Serial.print(direct[0]); } } } void loop() { if (millis() >= pingTimer) { // Is it time to ping? pingTimer += PING_INTERVAL; // Set next time this sensor will be pinged. sonar.timer_stop(); // Make sure previous timer is canceled before starting a new ping (insurance). distanceCM = 0; // Make distance zero in case there's no ping echo for this sensor. sonar.ping_timer(echoCheck); // Do the ping (processing continues, interrupt will call echoCheck to look for echo). } } /// If ping received, set the sensor distance. void echoCheck() { if (sonar.check_timer()) { distanceCM = sonar.ping_result / US_ROUNDTRIP_CM; } if (distanceCM >= MAX_DISTANCE || distanceCM <= MIN_DISTANCE){ /* Send a negative number to computer and Turn LED ON to indicate "out of range" */ Serial.print("distance: "); Serial.println("-1"); digitalWrite(LED, HIGH); } else { /* Send the distance to the computer using Serial protocol, and turn LED OFF to indicate successful reading. */ Serial.print("distance: "); Serial.println(distanceCM); digitalWrite(LED, LOW); } }
Soweit sogut... Morgen kümmer ich mich um den distance_sensor Part
-
....Über den jeweiligen PWM pin kann die Geschwindigkeit festgelegt werden. Aufgrund von unterschiedlichen Motoren (auch selben Models) kann es vorkommen dass der eine Motor auf 255 und der andere auf zB 249 laufen muss damit der Roboter gerade aus fährt - diesen Umstand muss man leider in der Feinabstimmung jeder für sich vornehmen.Soweit sogut... Morgen kümmer ich mich um den distance_sensor Part
Vorschlag, gleich mit dem Distancesensor eine Autokalibrierung einbauen
der an der Seite montiert sollte beim parallel zur Wand fahren diese Unterschiede registrieren und die Feinabstimmung festlegen
-
An der Seite montier ich aber eigentlich keine Sensoren, bzw hatte ich das zumindest nicht vor sondern nur im Bereich wo er fährt also vorne mittig und vorne seitlich (45° von der Mitte zur Seite)
-
Ich will jetzt wirklich keinem den Spass verderben und begeistern kann ich mich für die Roboter-Thematik durchaus auch. Wenn man aber den Aufwand in Relation zum Ergebnis sieht - wo ist da der Nutzen? Das Teil läuft zuverlässig z.B. von einem ins andere Eck, erkennt alle Hindernisse und kennt die Entfernungen - prima und für uns freaks natürlich begeisternd. :thumbs1:
Ein Laie wird dann sagen: "toll" und dann ...? Der echte Nutzen fehlt. Wäre es ein Roboter, der beispielsweise in den Keller geht, eine Flasche Wein und ein Glas holt und mir dann am Tisch einschenkt - super! Es würde ja auch schon genügen, "nur" eine Flasche aus dem Kühlschrank zu holen.
meigrafd: Ich wünsche Dir wirklich viel Spass und Erfolg - glaube aber, daß das Potential für in der Breite nützliche Anwendungen auf anderen Gebieten liegt: immer komplexere Software bei vergleichsweise einfacher und billiger Hardware.
Erwähnenswert finde ich aber noch den jährlich stattfindenden Fußballwettstreit mit von Studenten gebauten Robotern, da ist das Budget (wie bei uns) begrenzt und man sieht, was geht. Ein Glas Bier schenkt einem aber auch da noch keiner einIf it's just for fun - do it!
Gruß, mmi
-
Wenn es dir um den puren Nutzen Faktor geht kannst du über die Hälfte der weltweit versuchten Projekte mit dem RaspberryPI (oder anderer Hardware) ebenfalls derart kritisieren, in die Tonne kloppen und weiter in der Steinzeit leben!
Dank Forschung hast du überhaupt die Möglichkeit andere mit deiner Sinnvoll Hinterfragung zu nerven!Bitte KEINE Grundsatzdiskussion hier abhalten ob Du oder wer anderes dies hier Sinnvoll findet oder nicht!! Macht euch dafür einen eigenen Thread
Wenn Du/Ihr darin kein Sinn/Nutzen/Whatever seht dann ignoriert den jeweiligen Thread und ersparrt euch den Versuch andere zu demotivieren
-
Ja hi mmi,
wo kommst Du denn her bei dem Sauwetter ...Ich sehe da sehr wohl einen ganz erheblichen Nutzen: ich habe zwar einiges an Zeit und Geld investiert, aber am Ende den einen oder anderen AHA-Effekt, ein Erfolgserlebnis und eine Menge Spass am Basteln und Tüfteln gehabt. Und das genügt mir vollkommen.
Auch wenn ich, aus Platzmangel, den ganzen Tag dazu brauche mit Puk-Säge, Heißluftgebläse und Minibohrmaschine eine Halterung für zwei Stepper zu basteln - es hat Spass gemacht und ich finde das Endergebnis toll ...
Ansonsten finde ich es prima, dass meigrafd mal wieder den Werdegang seines Vorhabens hier dokumentiert. Da steckt eine Menge Information drin. Wär allerdings nicht schlecht, das evtl. in einem eigenen Thread in einem anderen Forum zu machen. Offtoppic ist das imho ja nicht mehr.
cu,
-ds- -
mmi, verbreitest du bitte keine Falschinformationen zum Roboterfußball?
Die Roboter der Haupt-Liga sind Standard-Plattformen. Jedes Team hat die gleichen Roboter. Unterscheiden tut sich nur die Software.
Daher ist Budget schonmal uninteressant dabei (und so ein Roboter kostet ein HEIDEN Geld).Und ein Glas eingescheknt wird dir bei dem Wettbewerb durchaus von Robotern. Neben dem Fußball laufen diverse andere Competitions, unter anderem im Thema Service-Roboter wo es genau darum geht. Und das können die schon!
Ich hab mir auch schon von einem Roboter einen Pfannkuchen machen lassen (leider mit einer leeren Teig-Tube, aber mir wurde versichert, wenn die voll gewesen wäre, hätte man den Pfannkuchen echt essen können, man kam nur nicht zum einkaufen.)
Und bei diesen Projekten geht es um das LERNEN nicht darum, dass am Ende der Roboter eine Bereicherung für die Menschheit ist.
Daher mein +1 für meigrafd. Er weiß ja, das ich finde, er sollte eines nach dem anderen angehen und nicht alles auf einmal^^
-
Ok, irgendwie ist mein "Beitrag" nach hinten losgegangen, demotivationsfördernd war er nun wirklich nicht gemeint - ein dickes sorry!
Es stimmt natürlich, eine Grundsatzdiskussion passt hier nicht, mein Fehler. Gäbe zwar jetzt meinerseits noch was zu sagen - aber hierher gehört's nicht und wäre ziemlich OT, also halt' ich auch unverzüglich den Mund.
meigrafd: Sorry nochmal und Gutes Gelingen!
-
Hab jetzt noch mal die motor_driver.ino aus Beitrag#46 etwas umgeschrieben und erweitert.
Nun kann ich vom RaspberryPI zum Arduino Befehle schicken die dann der MotorDriver umsetzt. Dabei übergebe ich zum einen den Steuerbefehl (forward/backward/left/right/stop) plus einen PWM Wert. Die Syntax sieht wie folgt aus:oder
oder
Der " : " dient als Trennzeichen und muss angegeben werden.
Der PWM Wert gibt dann eben an wie "doll" die Motoren drehen sollen, wird also an den PWMA oder PWMB Pin des MotorShields übergeben.Außerdem hab ich in motor_driver.ino auch einen Ultraschall Sensor mit eingebaut (sonar), da das ja auch zum Fahren dazu gehört und einen Ultraschall Sensor krieg ich an den UNO zusätzlich zum Motor Driver auch noch angeschlossen (2 Pins sind dann noch frei, da ich auch noch 3 LEDs verwende: eine für den MotorDriver zum anzeigen das er was umgesetzt haben müsste, und 2 für den Sensor um "out of range" sowie später ggf auch noch "detected" anzuzeigen (letzteres ist noch nicht eingebaut))
Für den Ultraschall Sensor ist es wichtig das zwischen den Messungen mindestens 29ms liegen da sich sonst die Signale überlagern; je nach Entfernung kann es eben 29ms dauern bis ein Ping wieder zurück kommt.
Da ich auf delay's verzichten möchte hab ich das ganze mit einem pingTimer und einer interrupt Anweisung umgesetzt:- Beim einschalten des Arduino's wird ja bekanntlich setup() ausgeführt, darin steht am Ende:
PING_INTERVAL ist auf 33 gesetzt
- Im loop() wird dann geprüft:
und erst dann wird pingTimer neu gesetzt und ein Ping ausgesendet sowie auf ein interrupt gewartet..
Zu meiner Firmware gehören bisher 2 Dateien:RoPi_config.h
Spoiler anzeigen
C
Alles anzeigen// // RoPi - global config // //------------------------------------------------------------------------------ #include <arduino.h> //------------------------------------------------------------------------------ //#define DEBUG #define SERIAL_BAUD 9600 //115200 // HC-SR04 //5V on Arduino to VCC of HC-SR04 //Pin 12 of Arduino to TRIG of HC-SR04 //Pin 13 of Arduino to ECHO of HC-SR04 //GND of Arduino to GND of HC-SR04 #define ULTRASONIC_TRIG 12 #define ULTRASONIC_ECHO 13 #define MAX_DISTANCE 500 /**< maximum distance to track with sensor (in centimeters). Maximum sensor distance is rated at 400-500cm. */ #define MIN_DISTANCE 0 /**< minimum distance to track with sensor */ #define PING_INTERVAL 33 // Milliseconds between sensor pings (29ms is about the min to avoid cross-sensor echo). #define pingGreenLED 10 #define pingRedLED 11 // TB6612FNG Motor Driver /*Pins for the left track*/ #define PWMA 3 #define AIN1 0 #define AIN2 1 /*Pins for the right track*/ #define PWMB 5 #define BIN1 2 #define BIN2 4 #define STBY 6 #define motorLED 7
motor_driver.ino
Spoiler anzeigen
C
Alles anzeigen/* Um Befehle vom RaspberryPI zu empfangen und fuer den MotorDriver umzusetzen version 0.4 by meigrafd */ //------------------------------------------------------------------------------ #include <stdint.h> #include "RoPi_config.h" #include <NewPing.h> // http://code.google.com/p/arduino-new-ping/ //------------------------------------------------------------------------------ NewPing sonar(ULTRASONIC_TRIG, ULTRASONIC_ECHO, MAX_DISTANCE); // NewPing setup of pins and maximum distance unsigned long pingTimer; unsigned int distanceCM; String dataString; //------------------------------------------------------------------------------ static void activityLED (byte pin, byte mode) { pinMode(pin, OUTPUT); digitalWrite(pin, mode); } // blink led for n times void blinkLED (byte pin, byte n = 3) { pinMode(pin, OUTPUT); for (byte i = 0; i < 2 * n; ++i) { delay(100); digitalWrite(pin, !digitalRead(pin)); } } /// If ping received, set the sensor distance. void echoCheck() { if (sonar.check_timer()) { distanceCM = sonar.ping_result / US_ROUNDTRIP_CM; } if (distanceCM >= MAX_DISTANCE || distanceCM <= MIN_DISTANCE){ /* Send a negative number to computer and Turn LED ON to indicate "out of range" */ Serial.println("distance: -1"); digitalWrite(pingRedLED, HIGH); } else { /* Send the distance to the computer using Serial protocol, and turn LED OFF to indicate successful reading. */ Serial.println("distance: " + distanceCM); digitalWrite(pingRedLED, LOW); } } static void motorDriverState (byte state) { digitalWrite(STBY, state); } void goFWD(int pwmWert) { digitalWrite(AIN1, HIGH); digitalWrite(AIN2, LOW); digitalWrite(BIN1, HIGH); digitalWrite(BIN2, LOW); analogWrite(PWMA, pwmWert); analogWrite(PWMB, pwmWert); } void goREV(int pwmWert) { digitalWrite(AIN1, LOW); digitalWrite(AIN2, HIGH); digitalWrite(BIN1, LOW); digitalWrite(BIN2, HIGH); analogWrite(PWMA, pwmWert); analogWrite(PWMB, pwmWert); } void rotateLeft(int pwmWert) { digitalWrite(AIN1, LOW); digitalWrite(AIN2, HIGH); digitalWrite(BIN1, HIGH); digitalWrite(BIN2, LOW); analogWrite(PWMA, pwmWert); analogWrite(PWMB, pwmWert); } void rotateRight(int pwmWert) { digitalWrite(AIN1, HIGH); digitalWrite(AIN2, LOW); digitalWrite(BIN1, LOW); digitalWrite(BIN2, HIGH); analogWrite(PWMA, pwmWert); analogWrite(PWMB, pwmWert); } //only one side, left track void rotateLeft1f(int pwmWert) { digitalWrite(AIN1, LOW); digitalWrite(AIN2, HIGH); digitalWrite(BIN1, LOW); digitalWrite(BIN2, LOW); analogWrite(PWMA, pwmWert); analogWrite(PWMB, pwmWert); } //only one side, left track void rotateRight1f(int pwmWert) { digitalWrite(AIN1, HIGH); digitalWrite(AIN2, LOW); digitalWrite(BIN1, LOW); digitalWrite(BIN2, LOW); analogWrite(PWMA, pwmWert); analogWrite(PWMB, pwmWert); } //only one side, right track void rotateLeft1r(int pwmWert) { digitalWrite(AIN1, LOW); digitalWrite(AIN2, LOW); digitalWrite(BIN1, LOW); digitalWrite(BIN2, HIGH); analogWrite(PWMA, pwmWert); analogWrite(PWMB, pwmWert); } //only one side, right track void rotateRight1r(int pwmWert) { digitalWrite(AIN1, LOW); digitalWrite(AIN2, LOW); digitalWrite(BIN1, HIGH); digitalWrite(BIN2, LOW); analogWrite(PWMA, pwmWert); analogWrite(PWMB, pwmWert); } void Stop() { digitalWrite(AIN1, LOW); digitalWrite(AIN2, LOW); digitalWrite(BIN1, LOW); digitalWrite(BIN2, LOW); analogWrite(PWMA, 0); analogWrite(PWMB, 0); } String splitString(String s, char parser, int index) { String rs='\0'; int parserIndex = index; int parserCnt=0; int rFromIndex=0, rToIndex=-1; while (index >= parserCnt) { rFromIndex = rToIndex+1; rToIndex = s.indexOf(parser,rFromIndex); if (index == parserCnt) { if (rToIndex == 0 || rToIndex == -1) { return '\0'; } return s.substring(rFromIndex,rToIndex); } else { parserCnt++; } } return rs; } //------------------------------------------------------------------------------ void setup() { Serial.begin(SERIAL_BAUD); pinMode(PWMA,OUTPUT); pinMode(AIN1,OUTPUT); pinMode(AIN2,OUTPUT); pinMode(PWMB,OUTPUT); pinMode(BIN1,OUTPUT); pinMode(BIN2,OUTPUT); pinMode(STBY,OUTPUT); pinMode(motorLED,OUTPUT); pinMode(pingGreenLED,OUTPUT); pinMode(pingRedLED,OUTPUT); motorDriverState(HIGH); // turn driver ON pingTimer = millis() + PING_INTERVAL; // ping starts at PING_INTERVAL ms, gives time for the Arduino to chill before starting. } // cmd: f:255 --> vorwaerts mit pwm 255 //This routine is run between each time loop() runs void serialEvent() { if (Serial.available()) { dataString = Serial.readStringUntil('\n'); #ifdef DEBUG Serial.println("got: " + dataString); #endif dataString = dataString + ":"; //needed so below works String command = splitString(dataString, ':', 0); String value = splitString(dataString, ':', 1); #ifdef DEBUG Serial.println("command: " + command + " value: " + value); #endif if (command == "forward") { goFWD(value.toInt()); blinkLED(motorLED, 2); Serial.println("MOTOR: " + command + " " + value); } else if (command == "backward") { goREV(value.toInt()); blinkLED(motorLED, 2); Serial.println("MOTOR: " + command + " " + value); } else if (command == "left") { rotateLeft(value.toInt()); blinkLED(motorLED, 2); Serial.println("MOTOR: " + command + " " + value); } else if (command == "right") { rotateRight(value.toInt()); blinkLED(motorLED, 2); Serial.println("MOTOR: " + command + " " + value); } else if (command == "stop") { Stop(); blinkLED(motorLED, 2); Serial.println("MOTOR: " + command + " " + value); } else { Serial.println("INVALIED COMMAND"); } } } void loop() { if (millis() >= pingTimer) { // Is it time to ping? pingTimer += PING_INTERVAL; // Set next time this sensor will be pinged. sonar.timer_stop(); // Make sure previous timer is canceled before starting a new ping (insurance). distanceCM = 0; // Make distance zero in case there's no ping echo for this sensor. sonar.ping_timer(echoCheck); // Do the ping (processing continues, interrupt will call echoCheck to look for echo). } }
Nun setz ich mich erstmal ans Script für den RaspberryPI.
Das will ich auch mehrschichtig aufbauen, also ein Main Script soll für die Kommunikation RPI<-USB->Arduino zuständig sein und permanent laufen. Dort sollen dann auch so Entscheidungen festgelegt werden wie "was passiert wenn Objekt nur noch 5cm entfernt" usw. Ein weiteres Script soll dann zum einen zur Visuellen Darstellung genutzt werden und eben natürlich auch zur Steuerung von Extern (also vom PC)//EDIT:
Da ich ja mehrere Arduino's nutzen werde bzw möchte, nutze ich UDEV um jeden einen festen und eindeutigen /dev/ Gerätenamen zuzuweisen, so komm ich später nicht durcheinander und leider kommt es ja auch mal vor das die beim Booten in einer anderen Reihenfolge eingebunden werden...
Also zunächst Arduino anstecken, mit dmesg | tail -n10 prüfen welche SerialNumber der Arduino hat und dann die udev Rule erstellen: nano /etc/udev/rules.d/99-arduino-motor.rules
Nach erneutem einstecken gibts dann /dev/MOTOR - Beim einschalten des Arduino's wird ja bekanntlich setup() ausgeführt, darin steht am Ende:
-
Ich hab zZt üble Probleme eine vernünftige/stabile Verbindung RPI<-USB->Arduino hinzukriegen, hab ständig Fehlermeldungen bzw kann der PI nicht auf USB zugreifen oder ich hab Timeouts und die Befehle kommen nicht an
Deshalb versuch ich mein Glück jetzt über I2C, wobei der PI als Master fungiert und der Arduino als Slave. Somit brauch ich dann auch kein Logic Level Converter. Für UART wiederum bräuchte man leider einen Logic Level Converter..
Dazu verwende ich am PI den P1 header und den pin#3 (SDA) und pin#5 (SCL).
Am Arduino UNO wiederum verwende ich pin A4 (SDA) und pin A5 (SCL) - für die Analogen Pins hab ich zZt eh keine Verwendung.. Auf dem Arduino Mega wären das 20 (SDA) und 21 (SCL), auch wenn ich zZt noch kein Mega hab
(quelle)Zusätzlich muss aber auch GND beider Boards miteinander verbunden werden.
CodeRPI Arduino (Uno/Duemillanove) -------------------------------------------- GPIO 0 (SDA) <--> Pin 4 (SDA) GPIO 1 (SCL) <--> Pin 5 (SCL) Ground <--> Ground
Auf dem PI muss man zunächst das i2c Kernel Module laden bzw aus der Blacklist entfernen (# an den Anfang der Zeile einfügen):
/etc/modprobe.d/raspi-blacklist.confCode# blacklist spi and i2c by default (many users don't need them) blacklist spi-bcm2708 #blacklist i2c-bcm2708
Dann das i2c-dev Module laden lassen bzw ans Ende der Datei /etc/modules einfügen.
Das Paket i2c-tools installieren:
Optional: Wenn man dem pi Benutzer Zugriff auf i2c geben möchte, diesen in die Gruppe aufnehmen:
PI neu starten (oder manuelle usw manuell laden) und dann sollte bei ls -la /dev/i2c* was angezeigt werden
Anschließend einen simplen Test laufen lassen:
Ausgabe:Code0 1 2 3 4 5 6 7 8 9 a b c d e f 00: -- -- -- -- -- -- -- -- -- -- -- -- -- 10: -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- 20: -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- 30: -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- 40: -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- 50: -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- 60: -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- 70: -- -- -- -- -- -- -- --
..es ist also noch kein I2C Device verbunden..
Um i2c auch über Python verwenden zu können muss noch das Paket python-smbus installiert werden - alternativ ginge auch quick2wire
Nun ein Testprogramm auf dem Arduino flashen, dabei legen wir die Slave Adresse auf 4 fest, die wir dann später über den PI gezielt ansprechen:
Spoiler anzeigen
Code
Alles anzeigen#include <Wire.h> #define SLAVE_ADDRESS 0x04 int number = 0; int state = 0; void setup() { pinMode(13, OUTPUT); Serial.begin(9600); // start serial for output // initialize i2c as slave Wire.begin(SLAVE_ADDRESS); // define callbacks for i2c communication Wire.onReceive(receiveData); Wire.onRequest(sendData); Serial.println("Ready!"); } void loop() { delay(100); } // callback for received data void receiveData(int byteCount){ while(Wire.available()) { number = Wire.read(); Serial.print("data received: "); Serial.println(number); if (number == 1){ if (state == 0){ digitalWrite(13, HIGH); // set the LED on state = 1; } else{ digitalWrite(13, LOW); // set the LED off state = 0; } } } } // callback for sending data void sendData(){ Wire.write(number); }
Und auf dem PI folgendes python Script:
Spoiler anzeigen
Code
Alles anzeigenimport smbus import time # for RPI version 1, use "bus = smbus.SMBus(0)" bus = smbus.SMBus(1) # This is the address we setup in the Arduino Program address = 0x04 def writeNumber(value): bus.write_byte(address, value) # bus.write_byte_data(address, 0, value) return -1 def readNumber(): number = bus.read_byte(address) # number = bus.read_byte_data(address, 1) return number while True: var = input("Enter 1 - 9: ") if not var: continue writeNumber(var) print "RPI: Hi Arduino, I sent you ", var # sleep one second time.sleep(1) number = readNumber() print "Arduino: Hey RPI, I received a digit ", number print
Wird nun der Arduino über I2C mit dem PI verbunden müßte der Befehl i2cdetect -y 1 auch etwas zurück geben:
Codepi@raspberrypi ~ $ i2cdetect -y 1 0 1 2 3 4 5 6 7 8 9 a b c d e f 00: -- 04 -- -- -- -- -- -- -- -- -- -- -- 10: -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- 20: -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- 30: -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- 40: -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- 50: -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- 60: -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- 70: -- -- -- -- -- -- -- --
quelle: http://blog.oscarliang.net/raspberry-pi-a…-connected-i2c/
..nun bau ich erstmal meine Scripts entsprechend um und hoffe dass das besser/stabiler klappt.. stay tuned
-
Hi meigrafd,
hattest Du den Rpi und den Arduino so verbunden, wie -> hier <- beschrieben?
Das lief, bei mir zumindest, sehr stabil ...Ah ... mit fiel da grad noch was ein.
Irgendwann hattest Du mal Konfigurationsdaten erwähnt, wenn ich mich nicht irre.
Hats Du schon mal drüber nachgedacht, bei einem Slave-Arduino ein TFT mit SD-Karten-Slot zu verwenden und diverse Einstellungen auf einer SD zu speichern.
Also zu funktionieren scheint das ... beim 2.2" TFT Display erkennt er jedenfalls eine eingesteckte SD-Karte (sie muss aber FAT formatiert sein).
Ich probiere gerade noch das 1.8" Teil aus und fummel dann bei Gelegenheit mal Schreib-/Leseroutinen zusammen.
Ach ... und die Standard-LCDs mit 44780 kompatiblem Controller sind im Zusammenspiel mit einem I2C-Konverter auch sehr resourcenschonend und "out of the box" (schau vielleicht mal -> hier <- rein, vielleicht ist da ja was Brauchbares für Dich dabei ... Fortsetzung folgt, wenn ich den derzeit aktuellen Kram für den RPi erledigt habe).//EDIT:
Total vergessen: schöne Anleitung für RPi <- IIC -> Arduino ...
Wär imho ein eigenes Tut wert, findest Du nicht?cu,
-ds- -
Die Verbindung ansich hat über USB funktioniert, nur kamen entweder nicht immer die Befehle des PI's beim Arduino an, oder ich bekam ein timeout, oder der PI konnte manchmal auch nicht auf die USB-Verbindung zugreifen ... Warum das so ist konnte ich bisher nicht herausfinden und bevor ich mich damit noch 2 Tage auseinander setze versuch ich erstmal ein anderen Weg
Konfigurationsdateien brauch ich nur RPI seitig - zumindest wüsste ich jetzt akut nicht wofür die Arduino(s) welche bräuchten - die lesen nur die Sensoren aus und sprechen die Motoren an, den Rest soll der PI machen. Es sei denn es besteht ein Kommunikationsproblem mit dem PI dann soll der Arduino alle Aktivitäten einstellen also den RoPi anhalten bzw stehen bleiben
Wie genau das ganze letztlich ablaufen wird weiß ich aber auch noch nicht Wird denk ich innerhalb der Entwicklung sich heraus kristallisieren ob der derzeit eingeschlagene Plan überhaupt funktioniert
Ich weiß zum Beispiel noch immer nicht wie ich den RoPi letztlich tatsächlich steuern kann, also vom PC aus.. Oder was ich genau mit den Sensordaten anfange usw.ZZt hab ich's so vor dass der eine Arduino-UNO den MotorDriver ansteuert (nachfolgend Arduino-Master genannt) und einen Haupt-Ultraschall Sensor (der vorne inner Mitte). Theoretisch sollte das soweit auch schon funktionieren: alle 33ms schickt er ein Ping (Ultraschall) raus und das Ergebnis bzw die distance wird via Serial ausgegeben.
Der PI soll dann entscheiden ob das Objekt bereits zu nah dran ist und dem Arduino-Master Steuerbefehle geben, also zB anhalten oder ausweichen usw.Dh. ich brauch schon mal ein Programm auf dem PI welches den Arduino-Master anspricht und dessen Daten empfängt. In dem einen Programm soll dann noch ein socket-server integriert werden um auf "externe" Befehle reagieren zu können, also Befehle von mir
Aber weiter bin ich jetzt noch nicht mit dem Konzept
-
Hallöle,
...
USB-Verbindung zugreifen ... Warum das so ist konnte ich bisher nicht herausfinden
...das hatte ich vergessen dazu zu schreiben: meiner Erfahrung nach war eine rs232 Verbindung mit 3V3 Pegeln eher problematisch und störanfällig. Nachdem ich die Signale auf 5V gezogen hatte, war alles in Butter ...
Vielleicht wäre es eine Idee, die Stolpersteine mal in einem eigenen Beitrag zusammen zu fassen.Was die Steuerung betrifft: das ist sicher nicht ohne. Bei Sichtkontakt gehts ja noch, aber wie ich Dich kenne, willst Du vermutlich eher was anderes ...
Nun, dann wünsch ich Dir weiterhin viel Erfolg und Durchhalte-Vermögen (woran es bei Dir erfahrungsgemäß ja nicht mangelt),
-ds- -
das hatte ich vergessen dazu zu schreiben: meiner Erfahrung nach war eine rs232 Verbindung mit 3V3 Pegeln eher problematisch und störanfällig. Nachdem ich die Signale auf 5V gezogen hatte, war alles in Butter ...kann ich in keinster Weise bestätigen
Atmel Atmega 8 an Raspberry Pialle Versuche mit cutecom zu hyperterminal liefen fehlerfrei !
Am Atmel habe ich eh keine Probleme, das läuft im IRQ und kein Zeichen geht verloren.
Am PI klemmt es nur über die Streams, warte ich auf CR lineinput kann es mal dauern je nach dem wie der Atmel grad beschäftigt ist. sammel ich Zeichen für Zeichen geht mir am PI manchmal eines durch die Lappen weil der PI nicht wieder rechtzeitig guckt. Bei mir sind es nur Soft Probleme -
mit 3V3 an RS232 hab ich auch schlechte Erfahrungen. Pegelwandler und alles ist gut. Aber nicht mit dem Pi sondern mit "echten" Computern.
-
Jetzt mitmachen!
Du hast noch kein Benutzerkonto auf unserer Seite? Registriere dich kostenlos und nimm an unserer Community teil!