@AsuroPhilip:
Das M32-Beispiel "Example_09_Move" ist genau das Beispiel, das du suchst. Und es funktioniert!
Hallo
wollte mit der M32 den RP6 30cm Vorwärts fahren lassen:
Den "sound" höre ich, aber der Rp6 Fährt nicht.Code:#include "RP6ControlLib.h" #include "RP6I2CmasterTWI.h" #include "RP6Control_I2CMasterLib.h" int main(void) { initRP6Control(); initLCD(); I2CTWI_initMaster(100); sound(180,80,25); sound(220,80,25); while(true) { move(100,FWD,DIST_CM(30),true); } return 0; }
Kann mir einer helfen?
mfG
Philip
Geändert von AsuroPhilip (27.03.2011 um 12:53 Uhr)
@AsuroPhilip:
Das M32-Beispiel "Example_09_Move" ist genau das Beispiel, das du suchst. Und es funktioniert!
Gruß
Dirk
Mich würde es auch interessieren wo bei ihm der Fehler ist. Der Verweis auf das Beispiel ist zwar schön aber dieses ist ja leider nicht Kommentiert.
Welches sind die drei Feinde eines Programmierers?
Sonnenlicht, Sauerstoff und das unerträgliche Gebrüll der Vögel
@Ezalo:
Das Beispiel ist zwar wenig kommentiert, aber man kann ja wohl davon ausgehen, dass nicht unbedingt "Unnützes" da drin ist, so dass man das Programm so verkürzen könnte, wie Philip es gemacht hat.
Wenn man die M32 als Master betreibt, ist ja auf der "anderen Seite" immer die Base mit dem Slave-Programm "RP6Base_I2CSlave".
Master und Slave müssen zusammen passen, um sich unterhalten zu können. Der Slave in der Base hat z.B. einen "Watchdog" (Wachhund), der den RP6 stoppt, wenn die I2C-Verbindung zum Master irgendwie gestört ist. Dazu braucht es z.B. im Master den "Watchdog-Handler" (WDT_setRequestHandler(watchDogRequest). Damit reagiert der Master auf Watchdog-Anfragen des Slave.
Genauso braucht es einen Handler für "Daten eingetroffen" (I2CTWI_setRequestedDataReadyHandler(I2C_requested DataReady).
Verwendet wird auch noch ein Handler (I2CTWI_setTransmissionErrorHandler(I2C_transmissi onError) für die Anzeige von I2C-Kommunikationsfehlern, den könnte man aber weglassen.
Also: Der Master in der M32 funktioniert nur, wenn er passend zum Slave im RP6 programmiert wird.
Gruß
Dirk
Okay, das fahren klappt jetzt super! Danke Dirk!
Aber der Servo bewegt sich nicht:
Der zuckt nur kurz und dann fährt der Rp6 weiter.Code:#include "RP6ControlLib.h" #include "RP6I2CmasterTWI.h" #include "RP6Control_I2CMasterLib.h" #include "RP6ControlServoLib.h" void watchDogRequest(void) { static uint8_t heartbeat2 = false; if(heartbeat2) { clearPosLCD(0, 14, 1); heartbeat2 = false; } else { setCursorPosLCD(0, 14); writeStringLCD_P("#"); heartbeat2 = true; } } void I2C_requestedDataReady(uint8_t dataRequestID) { checkRP6Status(dataRequestID); } void I2C_transmissionError(uint8_t errorState) { writeString_P("\nI2C ERROR - TWI STATE: 0x"); writeInteger(errorState, HEX); writeChar('\n'); } int main(void) { initRP6Control(); initLCD(); initSERVO(SERVO1); WDT_setRequestHandler(watchDogRequest); I2CTWI_initMaster(100); I2CTWI_setRequestedDataReadyHandler(I2C_requestedDataReady); I2CTWI_setTransmissionErrorHandler(I2C_transmissionError); sound(180,80,25); sound(220,80,25); setLEDs(0b1111); mSleep(500); setLEDs(0b1111); I2CTWI_transmit3Bytes(I2C_RP6_BASE_ADR, 0, CMD_SET_ACS_POWER, ACS_PWR_MED); I2CTWI_transmit3Bytes(I2C_RP6_BASE_ADR, 0, CMD_SET_WDT, true); I2CTWI_transmit3Bytes(I2C_RP6_BASE_ADR, 0, CMD_SET_WDT_RQ, true); while(true) { servo1_position = 50; move(60, FWD, DIST_CM(30), BLOCKING); servo1_position = 140; task_SERVO(); } return 0; }
Am Servo liegt es nicht, da er in einem anderen Programm klappt.
mfG
Philip
@Philip:
Das liegt daran, dass die move-Funktion die while(true)-Schleife so lange blockiert, bis die Bewegung abgeschlossen ist.... der Servo bewegt sich nicht
Die task_SERVO() braucht aber eine while(true)-Schleife, die permanent durchläuft und nur wenige ms dauert.
Eine Lösung wäre, die move-Funktion nicht BLOCKING zu machen (also: move(60, FWD, DIST_CM(30), NON_BLOCKING) ) und direkt hinter der move-Funktion einzufügen:
Damit wird in der Schleife auch gewartet, bis die Bewegung beendet ist, aber trotzdem werden die 3 wichtigen Tasks aufgerufen.Code:while(!isMovementComplete()) { task_checkINT0(); task_I2CTWI(); task_SERVO(); }
Nicht getestet! Schlag mich nicht, wenn's nicht geht!
Gruß
Dirk
Funktioniert aber (siehe code):
Kannst du mir auch sagen wie das geht?Code:while(true) { servo1_position = 40; move(60, FWD, DIST_CM(30), NON_BLOCKING); //wenn der Rp6 30cm gefahren soll der servo1 auf 150 while(!isMovementComplete()) { task_checkINT0(); task_I2CTWI(); task_SERVO(); } } return 0; }
mfG
Philip
@Philip:
Mit dem while-Block mache ich genau das Selbe, was in der Funktion move mit Parameter BLOCKING gemacht würde.Kannst du mir auch sagen wie das geht?
Sieh dir die Funktion move oder rotate in der RP6Control_I2CMasterLib.c an!
Am Ende dieser Funktionen findest du einen ganz ähnlichen while-Block, der nur dann aktiv ist, wenn man den BLOCKING Parameter benutzt hat. Er bewirkt, dass während die Funktion auf das Ende der Bewegung wartet, die wichtigen Tasks abgearbeitet werden.
Genau das mache ich dann in deinem Hauptprogramm und habe noch die task_SERVO() in den while-Block aufgenommen.
Gruß
Dirk
Lesezeichen