PDA

Archiv verlassen und diese Seite im Standarddesign anzeigen : Rp6 - Fährt nicht ?!?



AsuroPhilip
27.03.2011, 12:35
Hallo

wollte mit der M32 den RP6 30cm Vorwärts fahren lassen:


#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;
}

Den "sound" höre ich, aber der Rp6 Fährt nicht.

Kann mir einer helfen?


mfG
Philip

Dirk
27.03.2011, 13:25
@AsuroPhilip:

Das M32-Beispiel "Example_09_Move" ist genau das Beispiel, das du suchst. Und es funktioniert!

Ezalo
27.03.2011, 13:39
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.

Dirk
27.03.2011, 17:00
@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.

AsuroPhilip
27.03.2011, 17:23
Okay, das fahren klappt jetzt super! Danke Dirk!

Aber der Servo bewegt sich nicht:


#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_requestedD ataReady);
I2CTWI_setTransmissionErrorHandler(I2C_transmissio nError);

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;
}



Der zuckt nur kurz und dann fährt der Rp6 weiter.
Am Servo liegt es nicht, da er in einem anderen Programm klappt.


mfG
Philip

Dirk
27.03.2011, 19:56
@Philip:

... der Servo bewegt sich nicht
Das liegt daran, dass die move-Funktion die while(true)-Schleife so lange blockiert, bis die Bewegung abgeschlossen ist.
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:

while(!isMovementComplete())
{
task_checkINT0();
task_I2CTWI();
task_SERVO();
}

Damit wird in der Schleife auch gewartet, bis die Bewegung beendet ist, aber trotzdem werden die 3 wichtigen Tasks aufgerufen.
Nicht getestet! Schlag mich nicht, wenn's nicht geht!

AsuroPhilip
28.03.2011, 14:37
Funktioniert aber (siehe 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;
}


Kannst du mir auch sagen wie das geht?


mfG
Philip

Dirk
28.03.2011, 21:07
@Philip:

Kannst du mir auch sagen wie das geht?
Mit dem while-Block mache ich genau das Selbe, was in der Funktion move mit Parameter BLOCKING gemacht würde.

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.