Hallo :) Ich bin in der 4.und letzten Klasse in der Berufsschule. Jeder muss ein Abschlussprojekt machen. Eigentlich wollte ich eher ein hardwarelastiges Projekt machen, da meine Programmierkenntnisse nicht so groß sind. Aber dann habe ich doch von meinem Chef ein Projekt zugeteilt bekommen... :/ Es fällt mir wirklich schwer etwas zu programmieren, und ich hoffe ihr nehmt es mir nicht all zu übel wenn ich dumme Fragen stelle.. Mein Projekt kurz zusammengefasst: Ich habe einen Roboterarm (von Arexx-Robot-Arm V3 http://www.arexx.com/robot_arm/html/de/software.htm ), welcher mit einem 3D Pad von Ootsidebox (http://3dpadbyootsidebox.blogspot.fr/2014/09/3dpad-getting-started-guide.html) gesteuert werden soll. Das 3D Pad ist ein Arduino Shield (Arduino Uno) und deshalb muss ich das Arduino Uno Board verwenden! Das Problem ist nun, dass das 3D Pad fast alle Pins vom Arduino Uno verwendet, und deshalb kann ich die 6 Servos vom Roboterarm nicht am Arduino direkt anschließen. Der Roboterarm hatte eine fertige Elektonik (Atmega64A-au), aber die ist mir abgeraucht.. Ich habe keine Zeit mehr um diese Leiterplatte zu reparieren, und außerdem hat es nie wirklich funktioniert.. Deshalb habe ich mir ein Adafruit Servo Shield gekauft um meine 6 Servos anzusteuern. https://learn.adafruit.com/adafruit-16-channel-pwm-slash-servo-shield?view=all Dieses Shield funktioniert über die I2C Schnittstelle vom Arduino, mehr brauch ich nicht. Also perfekt, da ich quasi nur diese Pins frei habe.. Mit diesem Shield hab ich es jetzt immerhin geschafft die 6 Servos des Roboterarmes anzusteuern. Da der Code vom 3D Pad ziemlich groß ist, und fast den ganzen Speicher vom Arduino Uno verwendet, habe ich mir gedacht dass das 3D Pad (Arduino 1) der Master ist, und das Servoshield (Arduino 2) der Slave. Jetzt sollte ich die Daten vom 3D Pad, zur Arduino I2C Schnittstelle bekommen, damit ich diese weiter zum ServoShield schicken kann. Ich habe schon viel ausprobiert, aber leider hat nichts bis jetzt funktioniert. Ich hoffe ihr könnt mir helfen. Vielleicht weiß ja jemand von euch ein Master/Slave Code um die Gesten 1:1 weiter zu leiten. :) Das wäre der Link zur Lib. vom 3D Pad. Es sind zu viele Dateien, um sie im Anhang einzufügen. https://github.com/OotSideBox/3DpadArduinoSketch Im Anhang befindet sich der Servocode und der Beispielcode vom 3D Pad. Vielen Dank im Vorraus, und es tut mir leid falls ich euch zu wenig Infos gegeben habe - ist mein erster Beitrag in einem Forum. Liebe Grüße Mäggy :D
Es gibt bei http://www.arduino.cc eine I2C Master/Slave Library, die du für deine Zwecke umschnurzeln könntest: https://www.arduino.cc/en/Reference/Wire Dabei sind anscheinend auch Beispiele zur Master/Slave Kommunikation.
Danke für die Antwort :) Ich hab es mit den Beispielcodes schon versucht. (im Anhang wären die Codes Master/Slave) Hab einiges ausprobiert, hat aber leider nicht geklappt. Im Terminal vom Slave zeigt es mir auch keine Daten vom Master , welche gesendet werden sollten, an. Ich denke das Problem ist, dass die Gesten, welche zur SPI Schnittstelle gesendet werden, nicht von der I2C Schnittstelle gelesen werden können. Und deshalb sendet es nichts. Aber ist nur eine Vermutung.. Hab auch nichts gefunden ob und wie man SPI Daten ausliest, und zum I2C weiterleitet. Liebe Grüße
Matthias S. schrieb: > Dabei sind anscheinend auch Beispiele zur > Master/Slave Kommunikation. Maria du solltest dich an das Beispiel welches Matthias erwähnt halten. Probiere zunächst erstmal den Beispielcode aus ohne ihn zu verändern. Dann weißt du auch gleich, ob die Hardware funktioniert. https://www.arduino.cc/en/Tutorial/MasterWriter Maria K. schrieb: > Ich hab es mit den Beispielcodes schon versucht. > (im Anhang wären die Codes Master/Slave) Auszug aus deinem Code.
1 | Wire.beginTransmission(0x41); // transmit to device #8 |
2 | SPIsendForDac(VCOMAX); //signal indiquant arrete regulation |
3 | for(BoucleScrut=0; BoucleScrut<NODE;BoucleScrut++) //boucle de scrutation |
Deine Fremdsprachenkenntnisse sind zwar verblüffend, leider funktioniert
es aber selten wenn man Code aus mehreren Quellen zusammenkopiert (ohne
ihn vorher komplett verstanden zu haben). ;-(
Deshalb nochmals der Hinweis probiere erstmal das Beispiel zur Wire
Bibliothek ohne es zu verändern und versuche zu verstehen was da
passieren soll.
Maria K. schrieb:
> Im Terminal vom Slave zeigt es mir auch keine Daten vom Master
> , welche gesendet werden sollten, an.
> Ich denke das Problem ist, dass die Gesten, welche zur SPI
> Schnittstelle gesendet werden, nicht von der
> I2C Schnittstelle gelesen werden können.
Die SPI und I2C Schnittstellen (wie auch jede andere Schnittstelle)
interessieren sich überhaupt nicht für die Bedeutung der übertragenen
Daten. Schnittstellen kennen nur Daten. Nur du interpretierst diese mit
einer Bedeutung z.B. als "Gesten". Das solltest du dir selber
klarmachen.
Deshalb gibt es auch prinzipiell kein Problem bei der Übergabe von Daten
von SPI zum I2C oder umgekehrt.
> Und deshalb sendet es nichts. Aber ist nur eine Vermutung..
> Hab auch nichts gefunden ob und wie man SPI Daten ausliest,
> und zum I2C weiterleitet.
Und jetzt nochmal etwas Konstruktives. Eigentlich ist dein
zusammengewürfelter Code garnicht so schlecht.
In deinem Code liest schon Daten von Irgendwo und sendest sie per UART
an das Terminal. Beispielsweise in setServoPulse() sendest du 'pulse'
per Serial.println(pulse) also dem UART an das Terminal. Nichts anderes
ist das Senden und Empfangen der Gesten per I2C.
Und das (I2C senden/empfangen) hast du eigentlich gut geschrieben und
entspricht auch fast dem Beispiel. Das Beispiel stellt beim Empfangen
durch pollen von Wire.available() (while schleife) aber noch sicher,
dass auch alle gesendeten Bytes gelesen werden bevor die Funktion
receiveEvent() beendet wird.
Das Problem liegt sehr wahrscheinlich an einem anderen Teil des codes,
oder aber an der I2C Hardware.
Und noch etwas zu Kommentaren. Kommentare sollten zusätzliche
Dokumentation liefern und nicht nochmal erklären was sowieso der Code
schon aussagt. Bei deinem untenstehenden Code, weiß doch jeder sofort
dass an device (addresse) #8 gesendet werden soll. Der Kommentar ist
sozusagen doppelt und hust Einundvierzig oder 8! ;-)
1 | Wire.beginTransmission(0x41); // transmit to device #8 |
Und hier noch zwei vielleicht zu offensichtliche Fehlermöglichkeiten für dein Problem. 1) Sender-Seite: _3DMasterRev01.ino Du sendest immer die Geste mit dem Wert 0. EvGesture wird garnicht verändert.
1 | char EvGesture = 0; |
2 | [...]
|
3 | Wire.write(EvGesture); // sends one byte |
2) Empfänger-Seite: ServoSlave.ino Das Serial.println() steht außerhalb der case/break-Blöcke. Wird das überhaupt ausgeführt? Zusatzfrage: Gibt es den Fall "EvGesture == 0" hier überhaupt?
1 | char EvGesture = Wire.read(); // receive byte as a character |
2 | switch(EvGesture) { |
3 | [...]
|
4 | case PUSH: //Gesture = PUSH |
5 | break; |
6 | Serial.println(EvGesture); |
7 | }
|
Hey, danke für deine Antwort! - wirklich hilfreich, danke! void schrieb: > Maria du solltest dich an das Beispiel welches Matthias erwähnt halten. > Probiere zunächst erstmal den Beispielcode aus ohne ihn zu verändern. > Dann weißt du auch gleich, ob die Hardware funktioniert. Das habe ich ganz am Anfang schon versucht. Die zwei Arduino Boards kommunizieren über I2C einwandfrei! Den "Master Code" also vom 3D Pad hab ich von Ootsidebox gedownloadet. Das ist der Code, welcher vom Hersteller zur Verfügung gestellt wird, damit das Pad überhaupt so funktioniert. ootsidebox3DPad050315.ino Dort hab ich nichts zusätzliches zusammengewürfelt. Deshalb sollten im Rest vom Code eigentlich keine Fehler sein. Nur diesen Teil hab ich selber dazu geschrieben (& werde ihn gleich wieder ändern) char EvGesture = 0; [...] Wire.write(EvGesture); // sends one byte Wire.beginTransmission(0x41); // transmit to device #8 Wire.write(EvGesture); // sends one byte Wire.endTransmission(); // stop transmitting SendValues(ModeComSerie); //siehe SendValueByUART.cpp void schrieb: > Und noch etwas zu Kommentaren. Kommentare sollten zusätzliche > Dokumentation liefern und nicht nochmal erklären was sowieso der Code > schon aussagt. Bei deinem untenstehenden Code, weiß doch jeder sofort > dass an device (addresse) #8 gesendet werden soll. Der Kommentar ist > sozusagen doppelt und hust Einundvierzig oder 8! ;-) Ja stimmt.. Ich werde ab sofort darauf achten - danke! & auch die Fehler ausbessern. void schrieb: > Und hier noch zwei vielleicht zu offensichtliche Fehlermöglichkeiten für > dein Problem. Puh...iwie peinlich. werde es sofort ändern. Aber wie gesagt, noch kenn ich mich nicht wirklich aus... Ist eigentlich mein erstes Projekt mit einer Software... - Gib allerdings mein Bestes. Nochmals vielen Dank! :)
Maria K. schrieb: > Das habe ich ganz am Anfang schon versucht. > Die zwei Arduino Boards kommunizieren über I2C einwandfrei! Ok. Super, dann funktioniert ja schonmal deine Hardware. Und entschuldige, dass ich dir vorgeworfen hatte das nicht gemacht zu haben. ;-) Maria K. schrieb: > Nur diesen Teil hab ich selber dazu geschrieben > (& werde ihn gleich wieder ändern) Jetzt fällts mir auch hier auf. Das beschriebene Problem 2) gibt es auch auf der Sender-Seite. Bei einem switch statement, wird nur der Code innerhalb der case/break-Blöcke ausgeführt wenn kein default case definiert wurde. Code außerhalb der case/break-Blöcke wird niemals ausgeführt wenn kein default case existiert. Das ist jedenfalls das Verhalten vom gcc Compiler. (Ob es offizell undefiniertes Verhalten ist, habe ich jetzt nicht geprüft.) Sprich, dein Wire-Sendefunktionen werden auch nicht aufgerufen... Du solltest die Wire-Sendefunktionen entweder ganz aus dem switch herausnehmen oder in den jeweiligen case/break-Block aufnehmen. Und guter Stil ist es einen default-block zu schreiben, auch wenn dieser leer ist. Weil dann ist klar definiert was passiert wenn kein case zutrifft. Maria K. schrieb: > Aber wie gesagt, noch kenn ich mich nicht wirklich aus... > Ist eigentlich mein erstes Projekt mit einer Software... > - Gib allerdings mein Bestes. Keine Sorge, dass wird besser je mehr du dich damit beschäftigst. So haben die meisten hier angefangen... Habe gerade nochmal die Bibliothek angeschaut. Die Dokumentation zu der Library ist aber auch toll... Also was du eigentlich machen möchtest ist Senden der jeweiligen Geste, das ist exakt das was SendValues(char mode) aus SendValueByUART.cpp auch macht. Die Daten müssen dabei einfach nur zum I2C umgeleitet werden. Die Funktion GestureCompute(), welche passenderweise in AutomateGesture() schon aufgerufen wird, bereitet die Gesten-information schon passend in "EvGesture" auf. Dumm ist, dass es keine Funktion gibt um die EvGesture Variable aus der Bibliothek abzufragen. Alternative ist, dass du einfach direkt auf EvGesture in MAGesture.cpp zugreifst, dazu musst du wohl MAGesture.h in main.c includieren und per "extern int EvGesture;" dir Zugriff darauf verschaffen. Und dass nachdem AutomateGesture() aufgerufen wurde. Bezogen auf den ursprünglichen Code könnte das so aussehen.
1 | extern int EvGesture; |
2 | char GestureChar; |
3 | [...]
|
4 | AutomateDeroulement(); //automate d'acquisition |
5 | Filters(); |
6 | [...]
|
7 | AutomateGesture(0,0); //automate coordonnées 3D/gesture |
8 | |
9 | if ((EvGesture == RIGHT) || (EvGesture == LEFT) // alle Gesten welche per I2C gesendet werden sollen |
10 | || (EvGesture == UP) || (EvGesture == DOWN) // (kann man auch weglassen, aber dann werden |
11 | || (EvGesture == ROTATE_LEFT) || (EvGesture == ROTATE_RIGHT) // alle Gesten gesendet - siehe MGesture.h) |
12 | || (EvGesture == PUSH)) |
13 | {
|
14 | // per I2C senden
|
15 | GestureChar = (char)EvGesture; // casten nach char (weil Wire.write nur bytes oder byte arrays senden kann) |
16 | Wire.beginTransmission(0x41); // transmit to device #65 (0x41) |
17 | Wire.write(GestureChar); // sends one byte |
18 | Wire.endTransmission(); // stop transmitting |
19 | |
20 | // per UART (terminal) senden
|
21 | Serial.print("\n\r Eine Geste wurde gesendet "); |
22 | Serial.print(GestureChar); |
23 | }
|
24 | |
25 | // envoi des donnees sur le port USC (virtual COM port)
|
26 | SendValues(ModeComSerie); |
Im Prinzip sollte es das sein. Fallstricke welche halt auftauchen sind 1) Zugriff auf die Variable EvGesture 2) Format von EvGesture (int) passt nicht zur Wire.write (char) funktion 3) Aussortieren der "echten" Gesten (INIT, VOID, DUMMY, MOVING, ..., sind ja nicht so interessant) Könnte aber noch mehr sein, ist ungetester Code... Empfangen geht dann analog genau so nur anders herum. Viel Erfolg dabei!
Bitte melde dich an um einen Beitrag zu schreiben. Anmeldung ist kostenlos und dauert nur eine Minute.
Bestehender Account
Schon ein Account bei Google/GoogleMail? Keine Anmeldung erforderlich!
Mit Google-Account einloggen
Mit Google-Account einloggen
Noch kein Account? Hier anmelden.