Archiv verlassen und diese Seite im Standarddesign anzeigen : RP6 mit m32 steuern
Momo2712
29.12.2010, 17:28
ich habe den rp6 zu weihnachten bekommen und das m32 und das lcd display dazu. es hat alles super gefunzt, bis ich das m32 draufgebaut habe. seitedem weiß ich nich wie ich die motoren richtig ansteuere. hier is meine arbeit (is vieles aus beispielen kopiert):
#include "RP6ControlLib.h"
#include "RP6I2CmasterTWI.h"
#include "RP6Control_I2CMasterLib.h"
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');
}
void Bumpers(void)
{
if (bumper_left || bumper_right)
{
moveAtSpeed(0,0);
if (bumper_left)
{
changeDirection(BWD);
moveAtSpeed(150,150);
}
else if (bumper_right)
{
move(60,BWD,1000,1);
changeDirection(FWD);
moveAtSpeed(150,150);
}
else if (bumper_left && bumper_right)
{
move(60,BWD,500,1);
rotate(60,LEFT,90,1);
changeDirection(FWD);
moveAtSpeed(60,60);
}
}
}
void ACS (void)
{
if(obstacle_left)
{
setCursorPosLCD(1, 12);
writeStringLCD_P("LEFT");
rotate(50, RIGHT, 180, 1);
}
else
{
clearPosLCD(1, 12, 4);
}
if(obstacle_right)
{
setCursorPosLCD(1, 0);
writeStringLCD_P("RIGHT");
moveAtSpeed(90,40);
}
else
{
clearPosLCD(1, 0, 5);
}
if(obstacle_left && obstacle_right)
{
setLEDs(0b0110);
setCursorPosLCD(1, 7);
writeStringLCD_P("MID");
moveAtSpeed(0,0);
changeDirection(FWD);
moveAtSpeed(50,50);
}
else
{
setLEDs(0b0000);
clearPosLCD(1, 7, 3);
}
if(obstacle_left)
{
setLEDs(0b0001);
}
if(obstacle_right)
{
setLEDs(0b1000);
}
if(obstacle_left && obstacle_right)
{
sound(140,10,0);
}
else
{
if(obstacle_left)
sound(100,5,0);
if(obstacle_right)
sound(120,5,0);
}
}
int main(void)
{
initRP6Control();
initLCD();
ACS_setStateChangedHandler(ACS);
BUMPERS_setStateChangedHandler(Bumpers);
I2CTWI_initMaster(100);
I2CTWI_setRequestedDataReadyHandler(I2C_requestedD ataReady);
I2CTWI_setTransmissionErrorHandler(I2C_transmissio nError);
sound(180,80,25);
sound(220,80,25);
setLEDs(0b1111);
showScreenLCD("ATTENTION", "");
mSleep(1000);
setLEDs(0b0000);
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);
startStopwatch1();
changeDirection(FWD);
moveAtSpeed(80,80);
while(true)
{
task_I2CTWI();
task_LCDHeartbeat();
}
return 0;
}
wenn ich moveAtSpeed(x,x) schreibe, dann fährt er auch, aber wenn ich rotate benutze, dann macht er das zwar auch, aber danach passiert nichts mehr
ich bitte um hilfe, bin noch absoluter neuling
lg mo
thx
Fabian E.
29.12.2010, 17:39
Naja wenn er rotiert ist doch alles super? Warum sollte er danach was machen? Du musst danach wieder moveAtSpeed aufrufen...
Momo2712
29.12.2010, 17:43
also ich hab des so gedacht, dass wenn halt was im weg is, dass er dann stehen bleibt und rotiert. danach soll er wieder weiter fahren. und des tut er aber nicht, auch nicht mit nem neuen move befehl.
ich hab das alles schon erstellt ohne m32 und display, das schaut bei mir so aus:
#include "RP6RobotBaseLib.h"
void Crash (void)
{
if (bumper_left || bumper_right)
{
moveAtSpeed(0,0);
}
if (bumper_left)
{
move(60,BWD,500,1);
mSleep(500);
rotate(60,RIGHT,90,1);
changeDirection(FWD);
moveAtSpeed(60,60);
}
else if (bumper_right)
{
move(60,BWD,500,1);
mSleep(500);
rotate(60,LEFT,90,1);
changeDirection(FWD);
moveAtSpeed(60,60);
}
else if (bumper_left && bumper_right)
{
move(60,BWD,500,1);
rotate(60,LEFT,90,1);
changeDirection(FWD);
moveAtSpeed(60,60);
}
}
void Achtung (void)
{
if (obstacle_left)
{
rotate(60,RIGHT, 45,1);
changeDirection(FWD);
moveAtSpeed(60,60);
}
else if (obstacle_right)
{
rotate(60,LEFT, 45,1);
changeDirection(FWD);
moveAtSpeed(60,60);
}
}
int main (void)
{
initRobotBase();
setLEDs(0b111111);
mSleep(500);
setLEDs(0b011111);
mSleep(500);
setLEDs(0b001111);
mSleep(500);
setLEDs(0b000111);
mSleep(500);
setLEDs(0b000011);
mSleep(500);
setLEDs(0b000001);
mSleep(500);
setLEDs(0b000000);
mSleep(1000);
BUMPERS_setStateChangedHandler(Crash);
ACS_setStateChangedHandler(Achtung);
powerON();
setACSPwrMed();
changeDirection(FWD);
moveAtSpeed(60,60);
while(true)
{
task_RP6System();
}
return 0;
}
und wenn ich das auf die base auflade, dann funzt es einwandfrei. und des alles hätt ich halt jetz gern mit m32...
Fabian E.
29.12.2010, 18:00
Guck dir dazu doch mal die Beispiele an, da wird ja ziemlich genau das gemacht, was du willst.
Hallo Willkommen im Forum
nur mal zwei Anmerkungen für den Anfang:
Bitte suche dir für weitere Threads aussagekräftigere Namen und verwende für Code die dafür vorgesehenen Codetags.
(Änderungen eingefügt von radbruch ;)
Wenn du deine Motoren über die m32 Erweiterung steuern willst, wirst du dies mithilfe des I2C Buses des RP6 machen müssen. (Die Anleitung wird dir dabei weiterhelfen)
Momo2712
29.12.2010, 18:07
@ fabian: hab ich ja, darauf hab ich ja vieles kopiert, damit ichs dann umschreiben kann. im beispiel control move wird da rotate benutzt, ich hab alles aus move kopiert, einschließlich makefile usw und trotzdem geht bei mir rotate zwar noch, aber dann macht der robot nix mehr. ein evtl vorhandener heartbeat hört auf... ich bin am verzweifeln
@shedepe: ich werde es mir merken. ich bin am verzweifeln, ich versuch das schon zwei tage zum laufen zu kriegen, aber es klappt nicht.
die anleitung hab ich schon angeschaut. ich frage mich ja nur, warum moveAtSpeed funzt und rotate nicht. die gehen doch beide zum motor???
Also das letzte von dir gepostete Programm führt ja nur einmal den Befehl moveAtSpeed aus und geht dann in die Endlosschleife. Deine weiteroben im Code definierten Funktionen musst du aus der MainFunktion natürlich auch aufrufen
Momo2712
29.12.2010, 18:21
also das hier wie es jetzt is:
ACS_setStateChangedHandler(ACS);
BUMPERS_setStateChangedHandler(Bumpers);
und dann in der main funktion auch nochmal
task_ACS();
task_Bumpers();
hab ich des richtig verstanden?
Momo2712
29.12.2010, 18:29
aber jetzt nochmal was anderes: selbes problem wieder...
#include "RP6ControlLib.h"
#include "RP6I2CmasterTWI.h"
#include "RP6Control_I2CMasterLib.h"
void Bumpers(void)
{
if (bumper_left || bumper_right)
{
moveAtSpeed(0,0);
if (bumper_left)
{
move(60,BWD,500,1);
rotate(60, RIGHT, 45, BLOCKING);
changeDirection(BWD);
moveAtSpeed(70,70);
}
else if (bumper_right)
{
move(60,BWD,500,1);
rotate(60, LEFT, 45, BLOCKING);
changeDirection(FWD);
moveAtSpeed(70,70);
}
else if (bumper_left && bumper_right)
{
move(60,BWD,500,1);
rotate(60, RIGHT, 180, BLOCKING);
changeDirection(FWD);
moveAtSpeed(70,70);
}
}
}
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();
//ACS_setStateChangedHandler(ACS);
BUMPERS_setStateChangedHandler(Bumpers);
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);
showScreenLCD("################", "################");
mSleep(500);
showScreenLCD("I2C-Master", "Movement...");
mSleep(1000);
setLEDs(0b0000);
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);
moveAtSpeed(70,70);
while(true)
{
task_checkINT0();
task_I2CTWI();
}
return 0;
}
er fährt vorwärts wie er soll, wenn ich nen bumper drücke hält er an und fährt n stück zurück. so und jetz kommt rotate und des macht er nicht. dann passiert nichts mehr
Momo2712
30.12.2010, 12:43
kann mir denn keiner helfen?
Hast du schon mal testweise probiert, was passiert wenn du ein Programm reinlädst in dem er nur rotieren soll?
Momo2712
30.12.2010, 17:07
also wenn ich das beispiel rp6 control 9 move reinlade funktioniert das alles super. in der endlosschleife sind die move und rotate befehle drin, alles super.
wenn ich ne methode draus mach void Fahren (void) mit den gleichen befehlen und die methode dann in der endlosschelife aufrufe, dann geht auch alles super.
aber wenn ich bei den bumpers schreibe, if bumper_left... und dann move oder rotate schreibe, dann macht er das zwar, aber danach geht nichts mehr. der watchdog bleibt stehen und nichts rührt sich...
Ich hab jetzt auch ein Problem
Ich steuere meinen RP6 über die Tasten, ich kann ihn 100 mal vorwärts und zurück fahren lassen. Aber sobald ich in drehen lasse macht er nichts mehr danach. Erst hab ichs mit rotate probiert, das klappte nicht also versuchte ich es mit move. Das will allerdings auch nicht .
Hier das Programm :
#include "RP6ControlLib.h"
#include "RP6I2CmasterTWI.h"
#include "RP6Control_I2CMasterLib.h"
int main(void)
{
initRP6Control();
I2CTWI_initMaster(100);
setLEDs(0b1111);
mSleep(1000);
setLEDs(0b0000);
I2CTWI_transmit3Bytes(I2C_RP6_BASE_ADR, 0, CMD_SET_WDT, true);
I2CTWI_transmit3Bytes(I2C_RP6_BASE_ADR, 0, CMD_SET_WDT_RQ, true);
void I2C_requestedDataReady(uint8_t dataRequestID)
{
checkRP6Status(dataRequestID);
}
while(true)
{
uint8_t key = getPressedKeyNumber();
{
if(key == 5)
{
changeDirection(FWD);
moveAtSpeed(100,100);
}
if(key == 4)
{
changeDirection(BWD);
moveAtSpeed(100,100);
}
if(key == 1)
{
changeDirection(RIGHT);
move(100,RIGHT,DIST_CM(10),true);
changeDirection(FWD);
moveAtSpeed(0,0);
}
if(key == 3)
{
changeDirection(LEFT);
move(100,LEFT,DIST_CM(10),true);
changeDirection(FWD);
moveAtSpeed(0,0);
}
if(key == 2)
{
moveAtSpeed(0,0);
}
}
task_I2CTWI();
}
return 0;
}
Magelan1979
02.01.2011, 09:47
Habe lange nichts mehr damit gemacht, aber kann es sein, dass er mit LEFT und RIGHT bei MOVE nichts anfangen kann? Versuche mal für´s Drehen die rotate-Funktion
doch kann er, er dreht ja. Nur wenn er den Befehl move ausgeführt hat tut er nichts mehr. Und rotate habe ich auch schon probiert, funktionierte aber auch nicht.
@Mario94:
Nur wenn er den Befehl move ausgeführt hat tut er nichts mehr.
"Move" wird bei dir ja benutzt, wenn du Taste 1 oder 3 drückst. Danach wird der RP6 mit "moveAtSpeed(0,0);" gestoppt (d.h. er "tut nichts mehr").
Also tut dein RP6 doch das, was du ihm beigebracht hast.
Gruß Dirk
Richtig, wenn ich diese Taste drücke macht er genau das was ich will.
Aber dadurch wird der gesamte programmablauf blockiert und er reagiert auf keine Taste mehr.
Wie oben geschrieben, ich könnte ihn 100 mal vor und zurückfahren lassen. Aber sobald ich ihn einmal drehen lasse reagiert er auf keine Taste mehr.
Ok...aus irgendeinem Grund steht in der Slave vom RP6 bei move und bei rotate am ende false. Wenn ich jetzt mein Programm mit rotate true schreibe tut er dies zwar, aber danach reagiert er auf keine Taste mehr.
Wenn ich allerdings wie in der Slave steht, false dahinter schreibe, funktioniert es. Er rotiert und reagiert auf die Tasten, genau wie er es soll.
Hier nochmal der Code:
#include "RP6ControlLib.h"
#include "RP6I2CmasterTWI.h"
#include "RP6Control_I2CMasterLib.h"
int main(void)
{
initRP6Control();
I2CTWI_initMaster(100);
setLEDs(0b1111);
mSleep(1000);
setLEDs(0b0000);
I2CTWI_transmit3Bytes(I2C_RP6_BASE_ADR, 0, CMD_SET_WDT, true);
I2CTWI_transmit3Bytes(I2C_RP6_BASE_ADR, 0, CMD_SET_WDT_RQ, true);
void I2C_requestedDataReady(uint8_t dataRequestID)
{
checkRP6Status(dataRequestID);
}
while(true)
{
uint8_t key = getPressedKeyNumber();
{
if(key == 5)
{
changeDirection(FWD);
moveAtSpeed(100,100);
}
if(key == 4)
{
changeDirection(BWD);
moveAtSpeed(100,100);
}
if(key == 1)
{
rotate(130,RIGHT,50,false);
}
if(key == 3)
{
rotate(130,LEFT,50,false);
}
if(key == 2)
{
moveAtSpeed(0,0);
}
}
task_I2CTWI();
}
return 0;
}
@ Momo2712: Versuchs mal mit rotate 0 anstatt 1 bzw. mit false anstatt true, kann gut sein das du das selbe Problem hast.
Infotroniker
04.01.2011, 19:09
Hi Leute,
ich habe ein Problem bei mit dem I2C-Bus Programm.
Zum testen habe ich versucht, das Beispielprogramm \RP6BASE_EXAMPLES\RP6Base_I2CSlave.c zu kompilieren und auf den RP6 zu laden.
Jedoch bekomme ich immer die Fehler:
> "make.exe" all
-------- begin --------
avr-gcc (WinAVR 20100110) 4.3.3
Copyright (C) 2008 Free Software Foundation, Inc.
This is free software; see the source for copying conditions. There is NO
warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
Size before:
AVR Memory Usage
----------------
Device: atmega32
Program: 6904 bytes (21.1% Full)
(.text + .data + .bootloader)
Data: 246 bytes (12.0% Full)
(.data + .bss + .noinit)
Compiling: main-base.c
avr-gcc -c -mmcu=atmega32 -I. -gdwarf-2 -Os -funsigned-char -funsigned-bitfields -fpack-struct -fshort-enums -Wall -Wstrict-prototypes -Wa,-adhlns=main-base.lst -I../RP6Lib -I../RP6Lib/RP6base -I../RP6Lib/RP6common -std=gnu99 -MD -MP -MF .dep/main-base.o.d main-base.c -o main-base.o
Linking: main-base.elf
avr-gcc -mmcu=atmega32 -I. -gdwarf-2 -Os -funsigned-char -funsigned-bitfields -fpack-struct -fshort-enums -Wall -Wstrict-prototypes -Wa,-adhlns=main-base.o -I../RP6Lib -I../RP6Lib/RP6base -I../RP6Lib/RP6common -std=gnu99 -MD -MP -MF .dep/main-base.elf.d main-base.o ../RP6Lib/RP6base/RP6RobotBaseLib.o ../RP6Lib/RP6common/RP6uart.o --output main-base.elf -Wl,-Map=main-base.map,--cref -lm
main-base.o: In function `getCommand':
C:\RP6\Base/main-base.c:307: undefined reference to `I2CTWI_writeRegisters'
C:\RP6\Base/main-base.c:307: undefined reference to `I2CTWI_writeBusy'
C:\RP6\Base/main-base.c:309: undefined reference to `I2CTWI_writeRegisters'
C:\RP6\Base/main-base.c:310: undefined reference to `I2CTWI_writeRegisters'
C:\RP6\Base/main-base.c:311: undefined reference to `I2CTWI_writeRegisters'
C:\RP6\Base/main-base.c:312: undefined reference to `I2CTWI_writeRegisters'
C:\RP6\Base/main-base.c:313: undefined reference to `I2CTWI_writeRegisters'
main-base.o:C:\RP6\Base/main-base.c:314: more undefined references to `I2CTWI_writeRegisters' follow
main-base.o: In function `task_commandProcessor':
C:\RP6\Base/main-base.c:361: undefined reference to `setLEDs'
main-base.o: In function `task_updateRegisters':
C:\RP6\Base/main-base.c:237: undefined reference to `I2CTWI_readBusy'
C:\RP6\Base/main-base.c:239: undefined reference to `I2CTWI_readRegisters'
C:\RP6\Base/main-base.c:240: undefined reference to `I2CTWI_readRegisters'
C:\RP6\Base/main-base.c:241: undefined reference to `I2CTWI_readRegisters'
C:\RP6\Base/main-base.c:242: undefined reference to `I2CTWI_readRegisters'
C:\RP6\Base/main-base.c:243: undefined reference to `I2CTWI_readRegisters'
main-base.o:C:\RP6\Base/main-base.c:244: more undefined references to `I2CTWI_readRegisters' follow
main-base.o: In function `task_updateRegisters':
C:\RP6\Base/main-base.c:269: undefined reference to `I2CTWI_dataWasRead'
C:\RP6\Base/main-base.c:269: undefined reference to `I2CTWI_dataReadFromReg'
main-base.o: In function `signalInterrupt':
C:\RP6\Base/main-base.c:92: undefined reference to `I2CTWI_dataWasRead'
main-base.o: In function `task_MasterTimeout':
C:\RP6\Base/main-base.c:419: undefined reference to `setLEDs'
C:\RP6\Base/main-base.c:423: undefined reference to `setLEDs'
main-base.o: In function `main':
C:\RP6\Base/main-base.c:444: undefined reference to `setLEDs'
C:\RP6\Base/main-base.c:446: undefined reference to `setLEDs'
C:\RP6\Base/main-base.c:448: undefined reference to `I2CTWI_initSlave'
main-base.o: In function `motionControlStateChanged':
C:\RP6\Base/main-base.c:151: undefined reference to `isMovementComplete'
make.exe: *** [main-base.elf] Error 1
> Process Exit Code: 2
> Time Taken: 00:00
Ich habe die neuste Version der Librarys (Version 20080915) und exakt das Beispielprogramm genommen, ohne etwas zu verändern.
Die Antwort wird wahrscheinlich kurz, da der Fehler bei mir liegt, ich weiß aber nicht wo?!
Vielen Dank
Ich
@Ich:
Zum testen habe ich versucht, das Beispielprogramm \RP6BASE_EXAMPLES\RP6Base_I2CSlave.c zu kompilieren ...
Laut Ausdruck kompilierst du ein Programm namens "main-base.c" und nicht das RP6Base_I2CSlave.c.
Und das Programm main-base.c kennt wohl nicht die I2C-Library.
Gruß Dirk
Infotroniker
06.01.2011, 20:02
Hi,
sorry, dass ich erst jetzt antworten kann...
Aber zum Thema:
Laut Ausdruck kompilierst du ein Programm namens "main-base.c" und nicht das RP6Base_I2CSlave.c.
Ja, habe ich schlecht geschrieben. Ich meinte eigentlich, dass ich den Code von \RP6BASE_EXAMPLES\RP6Base_I2CSlave.c in main-base.c 1:1 kopiert und dann kompiliert habe.
Und was meintest du mit "main-base.c kennt wohl nicht die I2C-Library"?
Wenn du #include "RP6I2CslaveTWI.h" meinst, dann kennt main-base.c die Library.
Denn, wie gesagt, ich habe exakt den Code aus dem Beispielprogramm \RP6BASE_EXAMPLES\RP6Base_I2CSlave.c genommen.
Gruß
Ich, wieder
@Ich, wieder:
Ok, wenn ich RP6Base_I2CSlave.c in seinem Ordner \RP6Base_I2CSlave in main-base.c umbenenne und das makefile entsprechend anpasse, dann kann ich main-base.c ohne Fehler kompilieren (hab's probiert).
Wenn du Probleme hast, hast du vielleicht nicht dieselbe Ordnerstruktur wie bei den Original-Beispielen beibehalten. Dann werden evtl. Libs nicht gefunden.
Gruß Dirk
Momo2712
08.01.2011, 20:53
@ Mario94
das funktioniert auch nicht. ich bin jetz dann echt am verzweifeln.
Momo2712
09.01.2011, 15:22
wenn ich alles mit false mache wie mario 94 beschrieben hat, dann lässt er immer was aus. wenn ich das so schreibe:
if(bumper_left)
{
showScreenLCD("STOP", "BUMPER LEFT");
rotate(50, RIGHT, 90, true);
changeDirection(FWD);
moveAtSpeed(70,70);
dann zeigt er beim bumper left auch auf dem display was an, aber fährt dann n kleines stück vorwärts und des wars. er sollte ja eig rotieren und dan müsste er doch unendlich grade aus weiter fahren, oder nicht?
lg mo
Weil du funktion dann nicht Programm ablauf blockierend aufgerufen wird. Steht auch auf Seite 102 der Rp6 Bedienungsanleitung.
Ich würde vorschlagen du prüfst in der Hauptschleife ob einer der Bumperkontakt gibt und führst dort dann den rotate Befehl blockierend aus.
Läuft dein Programm eig auf der Base oder auf der M32 Erweiterung, denn soviel ich weiß hat die Base ja kein Display und von der M32 kann man ja auch nicht direkt auf die Antriebsfunktionen zugreifen
Momo2712
13.01.2011, 13:21
es läuft auf der m32 erweiterung. ich habe fast alles aus den beispielprogrammen übernommen, und es ist egal ob ich blocked oder nicht benutze, es funktioniert nicht.
könntest du nicht ein programm schreiben für die m32, dass er fährt, wenn der bumper gedrückt wird (er wo dagegen fährt) ein stück rückwärts, dann um 90 grad dreht und wieder vorwärts fährt. und nebenbei nich mit dem acs checked ob was im weg ist, sollte was sein, soll die eine kette schneller laufen als die andre, dass er noch ausweichen kann.
ich wär dich wirklich sehr dankbar, ich bekomme das einfach nicht hin
Ich habe einen besseren vorschlag (Da mein RP6 zerlegt in der Ecke liegt würde des mit dem programmieren auch etwas blöd), du postest einfach mal dein Programm, das auf der Base läuft komplett und das Pogramm das auf der M32 läuft (auch komplett) und dann kann man ja mal schauen wo der Fehler liegt.
Momo2712
13.01.2011, 19:22
hier ist das programm auf der m32:
#include "RP6ControlLib.h"
#include "RP6I2CmasterTWI.h"
#include "RP6Control_I2CMasterLib.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');
}
void bumpersStateChanged(void)
{
if(bumper_left || bumper_right)
{
moveAtSpeed(0,0);
if(bumper_left)
{
rotate(50, RIGHT, 90, true);
changeDirection(FWD);
moveAtSpeed(70,70);
}
else
{
rotate(50, LEFT, 90, false);
changeDirection(FWD);
moveAtSpeed(70,70);
}
}
}
void acsStateChanged(void)
{
if(obstacle_left || obstacle_right)
{
moveAtSpeed(0,0);
if(obstacle_left)
{
rotate(70, RIGHT, 90, true);
changeDirection(FWD);
moveAtSpeed(70,70);
}
else
{
rotate(70, LEFT, 90, true);
changeDirection(FWD);
moveAtSpeed(70,70);
}
}
}
int main(void)
{
initRP6Control();
initLCD();
BUMPERS_setStateChangedHandler(bumpersStateChanged );
ACS_setStateChangedHandler(acsStateChanged);
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(1000);
setLEDs(0b0000);
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);
changeDirection(FWD);
moveAtSpeed(70,70);
while(true)
{
task_checkINT0();
task_I2CTWI();
}
return 0;
}
und hier das slave programm auf der base (ist aus den beispiel programmen:
/*
* ************************************************** **************************
* RP6 ROBOT SYSTEM - ROBOT BASE EXAMPLES
* ************************************************** **************************
* Example: I2C Slave
* Author(s): Dominik S. Herwald
* ************************************************** **************************
* Description:
*
* A very common thing that many users will want to do with their RP6 is
* to control it with a second controller which has more free resources.
* (more free memory, free I/O Ports and ADCs, faster, etc. pp.
* for example the RP6-M32 expansion Module)
*
* This programs allows you to control the Robot Base Unit completely via
* I2C-Bus as a slave device!
*
* Also have a look at the RP6 CONTROL M32 example programs which can also
* be found on this CD-ROM - there you get examples of how to use
* this program!
*
* ************************************************** **************************
*/
/************************************************** ***************************/
// Includes:
#include "RP6RobotBaseLib.h"
#include "RP6I2CslaveTWI.h" // Include the I²C-Bus Slave Library
/************************************************** ***************************/
// The Slave Address on the I2C Bus can be specified here:
#define RP6BASE_I2C_SLAVE_ADR 10
/************************************************** ***************************/
// This bitfield contains the main interrupt event status bits. This can be
// read out and any Master devices can react on the specific events.
union {
uint8_t byte;
struct {
uint8_t batLow:1;
uint8_t bumperLeft:1;
uint8_t bumperRight:1;
uint8_t RC5reception:1;
uint8_t RC5transmitReady:1;
uint8_t obstacleLeft:1;
uint8_t obstacleRight:1;
uint8_t driveSystemChange:1;
};
} interrupt_status;
// Some status bits with current settings and other things.
union {
uint8_t byte;
struct {
uint8_t powerOn:1;
uint8_t ACSactive:1;
uint8_t watchDogTimer:1;
uint8_t wdtRequest:1;
uint8_t wdtRequestEnable:1;
uint8_t unused:3;
};
} status;
// Drive Status register contains information about current movements.
// You can check if movements are complete, if the motors are turned
// on, if there were overcurrent events and for direction.
union {
uint8_t byte;
struct {
uint8_t movementComplete:1;
uint8_t motorsOn:1;
uint8_t motorOvercurrent:1;
uint8_t direction:2;
uint8_t unused:3;
};
} drive_status;
RC5data_t lastRC5Reception;
/************************************************** ***************************/
/**
* Generates Interrupt Signal and starts Software Watchdog
*/
void signalInterrupt(void)
{
I2CTWI_dataWasRead = 0;
extIntON();
if(status.watchDogTimer)
startStopwatch2();
}
/**
* Clears Interrupt
*/
void clearInterrupt(void)
{
stopStopwatch2();
setStopwatch2(0);
status.wdtRequest = false;
interrupt_status.RC5reception = false;
interrupt_status.driveSystemChange = false;
extIntOFF();
}
/**
* ACS Event Handler
*/
void acsStateChanged(void)
{
interrupt_status.obstacleLeft = obstacle_left;
interrupt_status.obstacleRight = obstacle_right;
signalInterrupt();
}
/**
* Bumpers Event Handler
*/
void bumpersStateChanged(void)
{
interrupt_status.bumperLeft = bumper_left;
if(bumper_right)
interrupt_status.bumperRight = true;
else
interrupt_status.bumperRight = false;
signalInterrupt();
}
/**
* RC5 Event Handler
*/
void receiveRC5Data(RC5data_t rc5data)
{
lastRC5Reception.toggle_bit = rc5data.toggle_bit;
lastRC5Reception.device = rc5data.device;
lastRC5Reception.key_code = rc5data.key_code;
interrupt_status.RC5reception = true;
signalInterrupt();
}
/**
* Motion Control Event Handler
*/
void motionControlStateChanged(void)
{
drive_status.movementComplete = isMovementComplete();
drive_status.motorOvercurrent = motion_status.overcurrent;
interrupt_status.driveSystemChange = true;
signalInterrupt();
}
uint16_t uBat_measure = 720;
uint8_t uBat_count = 0;
/**
* This function needs to be called frequently in the main loop. It updates
* some values (currently only Battery Voltage and Motor status, but this may
* be expanded in future).
*/
void task_update(void)
{
if(getStopwatch4() > 250)
{
uBat_measure += adcBat;
uBat_measure /= 2;
uBat_count++;
setStopwatch2(0);
}
if(uBat_count > 5)
{
if(!interrupt_status.batLow && uBat_measure < 560)
{
interrupt_status.batLow = true;
signalInterrupt();
}
else if(interrupt_status.batLow && uBat_measure > 580)
{
interrupt_status.batLow = false;
signalInterrupt();
}
uBat_count = 0;
}
drive_status.motorsOn = (mleft_power || mright_power);
drive_status.direction = getDirection();
}
/************************************************** ***************************/
// I2C Registers that can be read by the Master. Their names should
// be self-explanatory and directly relate to the equivalent variables/functions
// in the RP6Library
#define I2C_REG_STATUS1 0
#define I2C_REG_STATUS2 1
#define I2C_REG_MOTION_STATUS 2
#define I2C_REG_POWER_LEFT 3
#define I2C_REG_POWER_RIGHT 4
#define I2C_REG_SPEED_LEFT 5
#define I2C_REG_SPEED_RIGHT 6
#define I2C_REG_DES_SPEED_LEFT 7
#define I2C_REG_DES_SPEED_RIGHT 8
#define I2C_REG_DIST_LEFT_L 9
#define I2C_REG_DIST_LEFT_H 10
#define I2C_REG_DIST_RIGHT_L 11
#define I2C_REG_DIST_RIGHT_H 12
#define I2C_REG_ADC_LSL_L 13
#define I2C_REG_ADC_LSL_H 14
#define I2C_REG_ADC_LSR_L 15
#define I2C_REG_ADC_LSR_H 16
#define I2C_REG_ADC_MOTOR_CURL_L 17
#define I2C_REG_ADC_MOTOR_CURL_H 18
#define I2C_REG_ADC_MOTOR_CURR_L 19
#define I2C_REG_ADC_MOTOR_CURR_H 20
#define I2C_REG_ADC_UBAT_L 21
#define I2C_REG_ADC_UBAT_H 22
#define I2C_REG_ADC_ADC0_L 23
#define I2C_REG_ADC_ADC0_H 24
#define I2C_REG_ADC_ADC1_L 25
#define I2C_REG_ADC_ADC1_H 26
#define I2C_REG_RC5_ADR 27
#define I2C_REG_RC5_DATA 28
#define I2C_REG_LEDS 29
/**
* This very important function updates ALL registers that the Master can read.
* It is called frequently out of the Main loop.
*/
void task_updateRegisters(void)
{
if(!I2CTWI_readBusy)
{
I2CTWI_readRegisters[I2C_REG_STATUS1] = (uint8_t)(interrupt_status.byte);
I2CTWI_readRegisters[I2C_REG_STATUS2] = (uint8_t)(status.byte);
I2CTWI_readRegisters[I2C_REG_MOTION_STATUS] = (uint8_t)(drive_status.byte);
I2CTWI_readRegisters[I2C_REG_POWER_LEFT] = (uint8_t)(mleft_power);
I2CTWI_readRegisters[I2C_REG_POWER_RIGHT] = (uint8_t)(mright_power);
I2CTWI_readRegisters[I2C_REG_SPEED_LEFT] = (uint8_t)(getLeftSpeed());
I2CTWI_readRegisters[I2C_REG_SPEED_RIGHT] = (uint8_t)(getRightSpeed());
I2CTWI_readRegisters[I2C_REG_DES_SPEED_LEFT] = (uint8_t)(getDesSpeedLeft());
I2CTWI_readRegisters[I2C_REG_DES_SPEED_RIGHT] = (uint8_t)(getDesSpeedRight());
I2CTWI_readRegisters[I2C_REG_DIST_LEFT_L] = (uint8_t)(getLeftDistance());
I2CTWI_readRegisters[I2C_REG_DIST_LEFT_H] = (uint8_t)(getLeftDistance()>>8);
I2CTWI_readRegisters[I2C_REG_DIST_RIGHT_L] = (uint8_t)(getRightDistance());
I2CTWI_readRegisters[I2C_REG_DIST_RIGHT_H] = (uint8_t)(getRightDistance()>>8);
I2CTWI_readRegisters[I2C_REG_ADC_LSL_L] = (uint8_t)(adcLSL);
I2CTWI_readRegisters[I2C_REG_ADC_LSL_H] = (uint8_t)(adcLSL>>8);
I2CTWI_readRegisters[I2C_REG_ADC_LSR_L] = (uint8_t)(adcLSR);
I2CTWI_readRegisters[I2C_REG_ADC_LSR_H] = (uint8_t)(adcLSR>>8);
I2CTWI_readRegisters[I2C_REG_ADC_MOTOR_CURL_L] = (uint8_t)(adcMotorCurrentLeft);
I2CTWI_readRegisters[I2C_REG_ADC_MOTOR_CURL_H] = (uint8_t)(adcMotorCurrentLeft>>8);
I2CTWI_readRegisters[I2C_REG_ADC_MOTOR_CURR_L] = (uint8_t)(adcMotorCurrentRight);
I2CTWI_readRegisters[I2C_REG_ADC_MOTOR_CURR_H] = (uint8_t)(adcMotorCurrentRight>>8);
I2CTWI_readRegisters[I2C_REG_ADC_UBAT_L] = (uint8_t)(adcBat);
I2CTWI_readRegisters[I2C_REG_ADC_UBAT_H] = (uint8_t)(adcBat>>8);
I2CTWI_readRegisters[I2C_REG_ADC_ADC0_L] = (uint8_t)(adc0);
I2CTWI_readRegisters[I2C_REG_ADC_ADC0_H] = (uint8_t)(adc0>>8);
I2CTWI_readRegisters[I2C_REG_ADC_ADC1_L] = (uint8_t)(adc1);
I2CTWI_readRegisters[I2C_REG_ADC_ADC1_H] = (uint8_t)(adc1>>8);
I2CTWI_readRegisters[I2C_REG_LEDS] = (uint8_t)(statusLEDs.byte);
I2CTWI_readRegisters[I2C_REG_RC5_ADR] = (uint8_t)((lastRC5Reception.device)|(lastRC5Recept ion.toggle_bit<<5));
I2CTWI_readRegisters[I2C_REG_RC5_DATA] = (uint8_t)(lastRC5Reception.key_code);
if(I2CTWI_dataWasRead && I2CTWI_dataReadFromReg == 0)
clearInterrupt();
}
}
/************************************************** ***************************/
// Command Registers - these can be written by the Master.
// The other registers (read registers) can NOT be written to. The only way to
// communicate with the Robot is via specific commands.
// Of course you can also add more registers if you like...
// ----------------------
#define I2C_REGW_CMD 0
#define I2C_REGW_CMD_PARAM1 1
#define I2C_REGW_CMD_PARAM2 2
#define I2C_REGW_CMD_PARAM3 3
#define I2C_REGW_CMD_PARAM4 4
#define I2C_REGW_CMD_PARAM5 5
#define I2C_REGW_CMD_PARAM6 6
// ----------------------
uint8_t cmd;
uint8_t param1;
uint8_t param2;
uint8_t param3;
uint8_t param4;
uint8_t param5;
uint8_t param6;
/**
* Checks if a new Command has been received and also reads all
* paramters associated with this command.
* It returns true if a new command has been received.
*/
uint8_t getCommand(void)
{
if(I2CTWI_writeRegisters[I2C_REGW_CMD] && !I2CTWI_writeBusy)
{
cmd = I2CTWI_writeRegisters[I2C_REGW_CMD]; // store command register
I2CTWI_writeRegisters[I2C_REGW_CMD] = 0; // clear command register (!!!)
param1 = I2CTWI_writeRegisters[I2C_REGW_CMD_PARAM1]; // parameters 1-6...
param2 = I2CTWI_writeRegisters[I2C_REGW_CMD_PARAM2];
param3 = I2CTWI_writeRegisters[I2C_REGW_CMD_PARAM3];
param4 = I2CTWI_writeRegisters[I2C_REGW_CMD_PARAM4];
param5 = I2CTWI_writeRegisters[I2C_REGW_CMD_PARAM5];
param6 = I2CTWI_writeRegisters[I2C_REGW_CMD_PARAM6];
return true;
}
return false;
}
/************************************************** ***************************/
// Command processor:
uint8_t leds = 1;
// Commands:
#define CMD_POWER_OFF 0
#define CMD_POWER_ON 1
#define CMD_CONFIG 2
#define CMD_SETLEDS 3
#define CMD_STOP 4
#define CMD_MOVE_AT_SPEED 5
#define CMD_CHANGE_DIR 6
#define CMD_MOVE 7
#define CMD_ROTATE 8
#define CMD_SET_ACS_POWER 9
#define CMD_SEND_RC5 10
#define CMD_SET_WDT 11
#define CMD_SET_WDT_RQ 12
// Parameters for CMD_SET_ACS_POWER:
#define ACS_PWR_OFF 0
#define ACS_PWR_LOW 1
#define ACS_PWR_MED 2
#define ACS_PWR_HIGH 3
/**
* This function checks if commands have been received and processes them.
*/
void task_commandProcessor(void)
{
if(getCommand())
{
switch(cmd)
{
case CMD_POWER_OFF: powerOFF(); status.powerOn = false; break;
case CMD_POWER_ON: powerON(); status.powerOn = true; break;
case CMD_CONFIG: break;
case CMD_SETLEDS: setLEDs(param1); break;
case CMD_STOP: stop(); break;
case CMD_MOVE_AT_SPEED: moveAtSpeed(param1, param2); break;
case CMD_CHANGE_DIR: changeDirection(param1); break;
case CMD_MOVE: move(param1, param2, ((param3<<8)+param4), false); break;
case CMD_ROTATE: rotate(param1, param2, ((param3<<8)+param4), false); break;
case CMD_SET_ACS_POWER:
switch(param1)
{
case ACS_PWR_OFF:
disableACS(); setACSPwrOff(); status.ACSactive = false;
break;
case ACS_PWR_LOW:
enableACS(); setACSPwrLow(); status.ACSactive = true;
break;
case ACS_PWR_MED:
enableACS(); setACSPwrMed(); status.ACSactive = true;
break;
case ACS_PWR_HIGH:
enableACS(); setACSPwrHigh(); status.ACSactive = true;
break;
}
break;
case CMD_SEND_RC5: IRCOMM_sendRC5(param1, param2); break;
case CMD_SET_WDT: status.watchDogTimer = param1 ? true : false; break;
case CMD_SET_WDT_RQ: status.wdtRequestEnable = param1 ? true : false; break;
}
}
}
/**
* This is the Software watchdog function. After any interrupt event, a timer is
* stated and if a certain amount of time has passed by with no reaction from
* the Master, the Robot is stopped to prevent any damages. Usually the Master
* program has errors or is locked up if it does not react, so this it is
* very good idea to stop moving.
*/
void task_MasterTimeout(void)
{
if(status.watchDogTimer)
{
if( getStopwatch2() > 3000) // 3 seconds timeout for the master to react on
{ // our interrupt events - if he does not react, we
// stop all operations!
cli();
IRCOMM_OFF();
setACSPwrOff();
OCR1AL = 0;
OCR1BL = 0;
TCCR1A = 0;
powerOFF();
writeString_P("\n\n##### EMERGENCY SHUTDOWN #####\n");
writeString_P("##### ALL OPERATIONS STOPPED TO PREVENT ANY DAMAGE! #####\n\n");
writeString_P("The Master Controller did not respond to the interrupt requests\n");
writeString_P("within the defined timeout! Maybe he's locked up!\n");
writeString_P("\nThe Robot needs to be resetted now.\n\n");
while(true) // Rest In Peace
{
setLEDs(0b100010);
uint8_t dly;
for(dly = 10; dly; dly--)
delayCycles(32768);
setLEDs(0b010100);
for(dly = 10; dly; dly--)
delayCycles(32768);
}
}
else if(getStopwatch3() > 250)
{
status.wdtRequest = true;
signalInterrupt();
setStopwatch3(0);
}
}
}
/************************************************** ***************************/
// Main - The program starts here:
int16_t main(void)
{
initRobotBase();
setLEDs(0b111111);
mSleep(500);
setLEDs(0b000000);
I2CTWI_initSlave(RP6BASE_I2C_SLAVE_ADR);
ACS_setStateChangedHandler(acsStateChanged);
BUMPERS_setStateChangedHandler(bumpersStateChanged );
IRCOMM_setRC5DataReadyHandler(receiveRC5Data);
MOTIONCONTROL_setStateChangedHandler(motionControl StateChanged);
powerON();
startStopwatch1();
disableACS();
setACSPwrOff();
status.byte = 0;
interrupt_status.byte = 0;
drive_status.byte = 0;
status.watchDogTimer = false;
status.wdtRequestEnable = false;
startStopwatch3();
startStopwatch4();
while(true)
{
task_commandProcessor();
task_update();
task_updateRegisters();
task_RP6System();
task_MasterTimeout();
}
return 0;
}
Schau dir mal da Beispielprogramm 6 an, insbesondere die rotate Funktion dort. Daraus solltest du erkennen können wie du das ganze zu implementieren hast. Die Funktionen rotate und move z.B. sind noch Nicht in der Lib der M32 implementiert.
Momo2712
14.01.2011, 13:54
hab jetz alles unverändert belassen und nur des eingefügt:
uint8_t transmit_buffer[10];
#define CMD_ROTATE 8
#define LEFT 2
#define RIGHT 3
void RP6_rotate(uint8_t desired_speed, uint8_t dir, uint16_t angle)
{
transmit_buffer[0] = 0;
transmit_buffer[1] = CMD_ROTATE;
transmit_buffer[2] = desired_speed;
transmit_buffer[3] = dir;
transmit_buffer[4] = ((angle>>8) & 0xFF);
transmit_buffer[5] = (angle & 0xFF);
I2CTWI_transmitBytes(I2C_RP6_BASE_ADR, transmit_buffer, 6 );
}
und dann nur noch die bumper funktion geändert:
void bumpersStateChanged(void)
{
if (bumper_left || bumper_right)
{
moveAtSpeed(0,0);
}
if (bumper_left)
{
RP6_rotate(35,LEFT,40);
}
else if (bumper_right)
{
RP6_rotate(35,LEFT,40);
}
}
so jetzt fährt er vorwärts, hält an wenn ich drücke (den bumper) und rotiert dann. so und wie bekomme ich jetz die move funktion hin, weil mein progblem ist nämlich, dass ich das nicht verstehe was das ganz oben eig heißt? mit transmit buffer usw
Das mit dem Transmitbuffer usw. heißt nur, dass du die entsprechende Befehle in byteform in einen Übetragungspuffer schreibst und diese dann mit der Funktion:
I2CTWI_transmitBytes(I2C_RP6_BASE_ADR, transmit_buffer, 6 );
Überträgst.
Für move musst du natürlich das entsprechende Command schicken (Die sind alle weiter oben im Beispiel File definiert) und dann schauen in welcher reihenfolge du die Argumente schicken musst.
Momo2712
16.01.2011, 21:27
kannst du mir das mit dem command für move nochmal erklären, ich check das iwie nicht...
Momo2712
23.01.2011, 13:25
kann mir denn keiner helfen? ich bin jetzt echt verzweifelt. er tut einfach nicht das was ich denke, das ich ihm programmiert hab
Powered by vBulletin® Version 4.2.5 Copyright ©2024 Adduco Digital e.K. und vBulletin Solutions, Inc. Alle Rechte vorbehalten.