Archiv verlassen und diese Seite im Standarddesign anzeigen : Programme, die nicht funktionieren (wollen) ?!?!?!?!
Hallo!
Ich habe hier ein Problem mit meinen Programmen.
Im ersten wollte ich den Robby (nur mit Base) mit der TV Remote steuern, aber auch die Bumper einsetzen (er sollte dann ein wenig rückwärts fahren und dann kann ich erst wieder die Steuerung übernehmen).
Leider tut sich nix, wenn ich auf die Bumper drücke. Gar nix!
Beim zweiten Programm wollte ich ebenfalls die Robby-Base mit TV Remote steuern, aber auch die sämtlichen Sensorwerte etc. auf den I2C legen, um später auch den M32 miteinzubeziehen.
Doch es kommen ziemlich viele Meldungen mit "undefined reference to ...", was meistens (ich glaube sogar immer) "read"-Befehle anspricht.
Mein eigentliches Vorhaben:
Ich wollte eigentlich nie den M32 als Master, sondern als separaten Prozessor. Ich hatte mir das so vorgestellt, dass die Base die Sensoren übernimmt (kommt noch ein bisschen was hinzu ...) und der Master später eigene Aufgaben übernimmt, aber unter gewissen Umständen auch Befehle an die Base schicken kann bzw von ihr Befehle auslesen kann.
Außerdem sollte der Robot laufend von der TV Remote gesteuert werden können, aber auch auf gewissen RC5-Befehlen in eigene Programmroutinen fahren (z.B. Lichtverfolgung, ...) und erst bei Drücken eines bestimmten Knopfes auf der TV Remote aus dieser Routine wieder in die TV-Remote-Routine zurückgehen, also wieder von mir gesteuert werden können.
Davon bin ich aber scheinbar noch weit entfernt!
Mir würde es ja für den Anfang schon reichen, wenn ich meine Sensorwerte und die RC5-Daten auf den I2C legen könnte, damit ich meinen M32 mal was ausführen lassen kann (z.B. Beeper an bei drücken des Knopfes 0 oder so, wär ja schon was)
Wäre super, wenn sich das mal einer von euch ansehen könnte!
Wie man so eine Box hier reinstellt, weiß ich leider auch nicht, darum lade ich euch die c-Dateien hoch...
Danke schon mal!
Fabian
@Fabian:
Vielleicht machst du es dir für den Anfang zu schwierig.
Fang doch mit einer einfachen Aufgabe an:
Die Control M32 (Master) fordert auf Tastendruck bestimmte Aktionen von der Base (Slave) über I2C an.
Typischer Code der Control M32 (Master):
#include "RP6ControlLib.h"
#include "RP6I2CmasterTWI.h"
uint8_t buffer[2];
int main(void)
{
initRP6Control();
initLCD();
I2CTWI_initMaster(100);
uint8_t key;
while(true)
{
showScreenLCD("Bitte Taster", "druecken");
do
{
key = getPressedKeyNumber();
}
while (key == 0);
showScreenLCD("Daten werden", "uebertragen");
mSleep(500);
buffer[0] = 0;
buffer[1] = key;
if (!I2CTWI_isBusy()) {
I2CTWI_transmitBytes(10, buffer, 2);
}
showScreenLCD("...erfolgreich", "");
mSleep(500);
}
return 0;
}
Passender Code für den Slave (Base):
#include"RP6RobotBaseLib.h"
#include "RP6I2CslaveTWI.h"
int main(void)
{
initRobotBase();
powerON();
setACSPwrOff();
uint8_t i;
I2CTWI_initSlave(10);
while (true)
{
if(I2CTWI_writeRegisters[0] && !I2CTWI_writeBusy)
{
// Register speichern:
i = I2CTWI_writeRegisters[0];
I2CTWI_writeRegisters[0] = 0;
switch (i)
{
case 1:
setLEDs(0b000001);
mSleep(500);
setLEDs(0b000000);
// task_motionControl();
// move(30,FWD,DIST_MM(50),false);
break;
case 2:
setLEDs(0b000011);
mSleep(500);
setLEDs(0b000000);
// task_motionControl();
// move(30,BWD,DIST_MM(50),false);
break;
case 3:
setLEDs(0b000111);
mSleep(500);
setLEDs(0b000000);
// task_motionControl();
// rotate(30,LEFT,20,false);
break;
case 4:
setLEDs(0b001111);
mSleep(500);
setLEDs(0b000000);
// task_motionControl();
// rotate(30,RIGHT,20,false);
break;
default:
setLEDs(0b111111);
mSleep(500);
setLEDs(0b000000);
}
}
}
return 0;
}
Wenn das bei dir klappt, kannst du dich an neue Aufgaben machen.
Genau so kann die M32 Messwerte von der Base abrufen.
Gruß Dirk
Hmmm...
Ja, das ist wohl richtig!
Werds morgen mal ausprobieren!
Danke für den Code :)
->Jetzt kommt seit Neuestem auch noch, dass er powerON(); nicht mehr kennen will!
Ich habe gerade keinen Peil mehr.
Werds mal doch langsamer angehen!
Aber hat vielleicht doch noch jemand eine Idee zu einem meiner beiden Programme?
Danke!
Fabian
Fresh!
Sehr Fresh!
Endlich mal etwas, das funktioniert!
Danke Dir, Dirk!
Aber nochmal schnell ne Frage dazu:
Am Anfang includest du ja stets SalveLib bzw. MasterLib.
So wie ich das beim Lesen des Manuals gesehen habe, setzten wir damit so etwas wie einen festen Status für den Microcontroller fest, setzen ihn also in den "Slave-Modus" bzw. "Master-Modus"!?!??
Ist das so, oder enthält die jeweilige Lib eben nur gewisse Routinen (wie das Schreiben/Lesen der Register), die gebraucht werden?
Und wenn es doch so ist, kann ich dann Daten auf den I2C legen, ohne dass ich den Microcontroller in den Slave-Modus setzen muss???
Und noch etwas ganz anderes, viel anfängerisches: Wenn ich ein Programm nun selbst tippe, bzw. mir eines wie das von dir hier kopiere...
Wie bekomme ich dann ein Makefile? Bisher habe ich mir damit geholfen, dass ich einfach die Bsp-Programme "überschrieben" habe, mir also deren Makefiles geklaut habe (höchstens Target verändert).
Aber das ist ja wohl nicht so ganz in Ordnung!?
Danke schon mal Dirk!
Natürlich auch an alle anderen, die mir was erklären wollen :D
Fabian
@Fabian:
... setzen ihn also in den "Slave-Modus" bzw. "Master-Modus"!?!??
Genau. Jeder Teilnahmer auf dem I2C-Bus kann nur Master oder Slave sein. Das wird beim RP6 bestimmt durch die Master- oder Slave-Lib, die eingebunden wird.
... kann ich dann Daten auf den I2C legen, ohne dass ich den Microcontroller in den Slave-Modus setzen muss???
Master und Slave können Daten senden und empfangen. Dabei hat aber der Master "die Hosen an": Der Slave quatscht nicht einfach los, sondern der Master fordert die Daten vom Slave an, der die dann sendet. Der Master empfängt dann die Daten.
Wenn der Slave nicht gerade angeforderte Daten sendet, dann hat er nur eine Aufgabe: Die Ohren an den Bus legen und nur dann reagieren, wenn irgend etwas an SEINE Adresse (in meinem Beispiel: 10, oder an alle Teilnehmer) gesendet wird. Ansonsten hat er die Klappe zu halten.
Makefile:
Das mit dem Klauen von anderen Beispielen ist eine gute Idee. Außer dem TARGET = must du noch in diesem Bereich:
SRC += $(RP6_LIB_PATH)/RP6base/RP6RobotBaseLib.c
SRC += $(RP6_LIB_PATH)/RP6common/RP6uart.c
#SRC += $(RP6_LIB_PATH)/RP6common/RP6I2CslaveTWI.c
#SRC += $(RP6_LIB_PATH)/RP6common/RP6I2CmasterTWI.c
... was anpassen:
Hier kommen alle Libs rein, die du für dein Programm brauchst (einbinden willst). Zeilen mit dem "#" am Anfang sind im makefile Kommentare, werden also NICHT ausgeführt. Wenn du also die Slave-Lib in dein Programm einbinden willst, mach einfach das "#" am Anfang der vorletzten Zeile weg.
Gruß Dirk
Ah!
Danke, jetzt ist schon einiges klarer.
Danke Dir derweil, werd mal versuchen das so umzusetzen.
Macht es Sinn, sich dann auch noch die CC-Pro Mega128 zu holen (Weihnachten steht ja vor der Tür), oder wird das dann vielleicht doch zu viel für meine Akkus und vor allem für mich Anfänger?
Schlimmstenfalls muss ich also meine Sachen umschreiben von Base auf M32. Woran ich zwar schon mal gescheitert bin, aber das wird schon, hoffe ich ;)
Hat hier jemand das TV-Remote-Beispiel zufällig schon mal modifiziert für die M32?
Würde derjenige mich daran teilhaben lassen? :D
Das wär super.
Gruß,
Fabian
RP6conrad
21.11.2010, 20:15
Ich verstehe eigentlich gar das Problem nicht. In das Bespiel werden doch RC5 und analoge Eingangen von Slave an Master geschickt. Dat hat der Master zugriff auf fast alle Functionen von Slave (Fahrbefehle, aber auch ADC Eingangen, RC5 , Bumper, LEDs steuern. Was wollst du eigentlich erreichen ?
Ja, das ist schon richtig.
Aber ich wollte einfach, dass Base und M32 jeweils eigenständig arbeiten und nur miteinander kommunizieren, also ohne Master-Slave. Was mir nicht so ganz gefällt ist, dass die ganze Rechenarbeit der Base nur dafür genutzt wird, dass man auf Befehle wartet.
Außerdem hab ich den RP6 erst 2 Wochen. Und meine Programmierkentnisse belaufen sich bisher auch NUR auf das durchlesen der Beispielprogramme... daher tu ich mich noch etwas hart...
RP6conrad
21.11.2010, 21:24
Auch das ist perfect machbar mit das heutige konzept : Der slave hat eine directe digital output nach den master. So besteht die moglichkeit das der Slave ein Signal gibt an der Master : hola, neue Info wartet auf Abfrage von Master (die sogenannte Interrupt nach den Master). Dan reagiert den Master und hohlt sich ueber I2C die wichtige Register (beispiel ACS, Bumper, RC5...).
Also ist es moglich um beide Programme (Master und SLave) zu erweitern und trotzdem doch eine Schnittstelle in zwei Richtungen zu haben.
Ah, ok! Klingt einleuchtend.
Das werd ich jetzt eben mal versuchen, wenn ich Zeit habe.
Sollte ja machbar sein...
Gruß,
Fabian
So. Ich habs wieder mal versucht!
Und wieder der Fehler:
"make: *** No rule to make target `RP6Base_TV_REMOTE+Slave.elf', needed by `elf'. Stop."
Aber ich habe wie Dirk es gesagt hat, den TARGET-Namen verändert UND das "#" bei der Slave-Lib weggenommen...
Was gibts denn noch zu tun?
Müssen meine Libs vielleicht im selben Ordner sein, wie mein Programm?
Denn ich gebe ja "nur" den Relativpfad an, oder?
Danke Euch schon mal!
Fabian
@fabqu:
Müssen meine Libs vielleicht im selben Ordner sein, wie mein Programm? Denn ich gebe ja "nur" den Relativpfad an, oder?
Das makefile funktioniert ohne weitere Änderungen nur, wenn man genau dieselbe Ordnerstruktur für eigene Programme nimmt, wie bei den RP6 Examples:
RP6Programs\RP6BASE_PROGRAMS\MyProgram_01\(eigene Programmdateien)
RP6Programs\RP6Lib\RP6base\(Base Lib-Dateien)
RP6Programs\RP6Lib\RP6common\(I2C- und UART- Lib-Dateien)
Alternativ kann man die Pfade im makefile anpassen.
N.B.: Ich würde kein "+" im Dateinamen verwenden.
Gruß Dirk
Gut gut! Dank dir für die schnelle antwort. Werd das gleich später mal testen!
Gruß, fabian
Ja, jetzt klappts.
Ich habe -- ja, ich weiß, alle haben gesagt, dass es nicht funktionieren wird -- es jetzt doch mal ausprobiert mit der Base als eigenständigen Prozessor, der selbst alles erledigen kann und der M32 auch alles mitteilt.
Und ja, ihr hattet recht - funktioniert nicht.
Wie Dirk schon sagte, geht die Base mit #include_slaveLib in den Slave-Modus und wartet dann nur noch, ob BEFEHLE VON DER M32 KOMMEN. Ob es eigene Befehle zu verarbeiten gibt, wird ignoriert.
Dennoch lehrreich :D
Jetzt eben mit nem Masterprogramm... werd mich die Tage mal hinsetzen.
Danke euch!
Fabian
Soso.
Hab jetzt zwei Stunden damit verbracht, mein Beispiel 7 des M32 umzuschreiben, damit ich die von der Base empfangenen RC5-Daten in Motorbewegungen umwandeln kann...
Klappt nicht!
Kann mir da mal jemand helfen?
Ich mache wohl etwas ziemlich falsch im "interrupt_status.RC5reception.
Habs dort mit Switch-Cases versucht, aber ich habe noch nicht so ganz rausbekommen, was genau ich schreiben muss, damit meine Base dann z.B. solange ich die jeweilige Taste der Fernbedienung drücke geradeaus fährt.
/*
* ************************************************** **************************
* RP6 ROBOT SYSTEM - RP6 CONTROL M32 Examples
* ************************************************** **************************
* Example: I2C Master
* ************************************************** **************************
* Description:
* In this example we show how to react on interrupt requests from the
* Microcontroller on the RP6 Mainboard. It sets the signal INT1 (that's what
* it is called on the RP6 hardware...) which is connected to the external
* interrupt input 0 of the Microcontroller. We will NOT use the interrupt
* routine to react on the interrupts. Instead we simply poll the interrupt
* pin and check if there is an request. This works better together with
* the I2C Bus Master routines of the RP6Library. They are also interrupt
* based and thus we can not directly start a new transmission out of the
* interrupt service routine of external Interrupt 0.
* It would not make any difference in this case, but we could get new
* problems when there is a I2C Bus transfer in progress when we get
* an interrupt event. Then it could get cancelled and replaced by the
* new request, which would cause problems sometimes.
*
* When an Interrupt Event occurs on the Slave Controller, the program
* initiates an I2C-Bus request for the first 3 Status Registers.
* In the Status registers some bits change depending on what has caused
* the interrupt Event (e.g. ACS has detected an obstacle, or the way is
* free again...) so we can determine what happened and can react on it
* accordingly.
*
*
************************************************** ***************************
*/
/************************************************** ***************************/
// Includes:
#include "RP6ControlLib.h" // The RP6 Control Library.
// Always needs to be included!
#include "RP6I2CmasterTWI.h" // I2C Bus Master routines
/************************************************** ***************************/
#define I2C_RP6_BASE_ADR 10 // The default address of the Slave Controller
// on the RP6 Mainboard
/************************************************** ***************************/
// These are the same command definitions as you can find them in the
// I2C Bus Slave Example program for RP6Base:
#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
#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
#define ACS_PWR_OFF 0
#define ACS_PWR_LOW 1
#define ACS_PWR_MED 2
#define ACS_PWR_HIGH 3
#define Remote_Controll
#ifdef Remote_Controll
#define RC5_KEY_LEFT 4
#define RC5_KEY_RIGHT 6
#define RC5_KEY_FORWARDS 2
#define RC5_KEY_BACKWARDS 8
#define RC5_KEY_STOP 5
#define RC5_KEY_CURVE_LEFT 1
#define RC5_KEY_CURVE_RIGHT 3
#define RC5_KEY_CURVE_BACK_LEFT 7
#define RC5_KEY_CURVE_BACK_RIGHT 9
#define RC5_KEY_LEFT_MOTOR_FWD 32 //Ch+
#define RC5_KEY_LEFT_MOTOR_BWD 33 //Ch-
#define RC5_KEY_RIGHT_MOTOR_FWD 16 //Vol+
#define RC5_KEY_RIGHT_MOTOR_BWD 17 //Vol-
#define RC5_KEY_ALERT 0 //Auf der '0'-Taste blinken LEDs
#define RC5_KEY_LIGHT 13 //Auf der 'Stumm' gehen Postitions-LEDs an
#define RC5_KEY_LIGHT_OFF 34 //Auf der Pfeil-Taste gehen Lichter aus
#endif
/************************************************** ***************************/
/************************************************** ***************************/
// The Status Struct - here we write the data of the main status register.
// It is the same definition as it can be found in the RP6Slave example!
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;
/************************************************** ***************************/
// Behaviour command type:
#define IDLE 0
// The behaviour command data type:
typedef struct {
uint8_t speed_left; // left speed (is used for rotation and
// move distance commands - if these commands are
// active, speed_right is ignored!)
uint8_t speed_right; // right speed
unsigned dir:2; // direction (FWD, BWD, LEFT, RIGHT)
unsigned move:1; // move flag
unsigned rotate:1; // rotate flag
uint16_t move_value; // move value is used for distance and angle values
uint8_t state; // state of the behaviour
} behaviour_command_t;
/************************************************** ***************************/
// INT0
#define INT0_STATUS_CHECK 0
uint8_t block = false;
/**
* This function and task_I2CTWI have to be called VERY frequently out of the
* main loop.
* Bigger delays result in slower reaction to Interrupt requests of the
* Slave.
* This function initiates a request of the first 3 Registers of the I2C Bus
* Slave Controller - these Bytes contain status bits, which tell us what
* caused the Interrupt request.
* They are checked in the requested data ready handler below.
*/
void task_checkINT0(void)
{
if(!block && (PIND & EINT1))
{
block = true; // Block further requests and wait until
// this request has been processed.
I2CTWI_requestRegisterFromDevice(I2C_RP6_BASE_ADR, INT0_STATUS_CHECK, 0, 3);
}
}
uint8_t messageBuf[8]; // Buffer for I2C Data
/**
* You already know this Event Handler from the RP6 Base Examples.
* Here on RP6Control it works a little bit different. This Event Handler is
* very nice for reacting on an interrupt request from the Slave controller and
* read all the data from it!
*
* In this example we output the ACS Status. We show it with the
* LEDs, on the LCD, make a small sound each time an ACS Channel has detected
* an obstacle and output it on the serial Interface...
* In principle, this program works just like the ACS Example you know from
* the RP6Base examples... but with some additional outputs...
*
* Beneath this, this routine also checks the Bumpers and for
* RC5 Receptions.
*
*/
void I2C_requestedDataReady(uint8_t dataRequestID)
{
if(dataRequestID == INT0_STATUS_CHECK) // We only have one request source, so
{ // we leave out the switch-case from the
// other example that you already know...
// get received data:
I2CTWI_getReceivedData(messageBuf, 3);
// We want to check if the ACS and Bumper status bits have changed, so we XOR
// them with the old value for comparison and later mask them in the if
// conditions below...
uint8_t compare = messageBuf[0] ^ interrupt_status.byte;
interrupt_status.byte = messageBuf[0]; // Update local register
// First, we check if the ACS status bits have changed, if not
// we can just ignore the change as it was something else...
if(compare & 0b01100000) // 0b01100000 are the ACS Status bits...
{
writeString_P("- ACS state changed L: ");
if(interrupt_status.obstacleLeft)
{
writeChar('o');
setCursorPosLCD(1, 12);
writeStringLCD_P("LEFT");
}
else
{
writeChar(' ');
clearPosLCD(1, 12, 4);
}
writeString_P(" | R: ");
if(interrupt_status.obstacleRight)
{
writeChar('o');
setCursorPosLCD(1, 0);
writeStringLCD_P("RIGHT");
}
else
{
writeChar(' ');
clearPosLCD(1, 0, 5);
}
if(interrupt_status.obstacleRight && interrupt_status.obstacleLeft)
{
externalPort.LEDS = 0b0110;
writeString_P(" MIDDLE!");
setCursorPosLCD(1, 7);
writeStringLCD_P("MID");
}
else
{
externalPort.LEDS = 0b0000;
clearPosLCD(1, 7, 3);
}
writeChar('\n');
if(interrupt_status.obstacleLeft)
externalPort.LED1 = true;
if(interrupt_status.obstacleRight)
externalPort.LED4 = true;
outputExt();
// Play a small sound with the Beeper depending on which sensor has
// detected something:
if(interrupt_status.obstacleRight && interrupt_status.obstacleLeft)
{
sound(140,10,0);
}
else
{
if(interrupt_status.obstacleLeft)
sound(100,5,0);
if(interrupt_status.obstacleRight)
sound(120,5,0);
}
}
// ------------------------------------
// Check if Bumpers status has changed:
if(compare & 0b00000110)
{
// Bumper status changed, output current state and play sounds:
writeString_P(" - Bumpers changed: ");
if(interrupt_status.bumperRight && interrupt_status.bumperLeft)
{
writeString_P("MIDDLE!\n");
sound(200,100,0);
}
else
{
if(interrupt_status.bumperLeft)
{
writeString_P("LEFT!\n");
sound(200,50,10);
sound(150,20,0);
}
else if(interrupt_status.bumperRight)
{
writeString_P("RIGHT!\n");
sound(200,50,10);
sound(150,20,0);
}
else
{
writeString_P("FREE!\n");
}
}
}
// ------------------------------------
// Check if there was a RC5 Reception:
if(interrupt_status.RC5reception)
{
uint8_t readBuf[2];
writeString_P("Received RC5 Transmission: ");
I2CTWI_transmitByte(I2C_RP6_BASE_ADR,I2C_REG_RC5_A DR);
I2CTWI_readBytes(I2C_RP6_BASE_ADR, readBuf, 2);
writeString_P("ADR:");writeInteger(readBuf[0],DEC);
writeString_P(" | DATA:");writeInteger(readBuf[1],DEC);
writeString_P("\n");
// Check which key is pressed:
switch(readBuf[1])
{
case RC5_KEY_LEFT: // Turn left:
break;
case RC5_KEY_RIGHT: // Turn right:
break;
case RC5_KEY_FORWARDS: // Move forwards
// Cruise Behaviour:
#define CRUISE_SPEED_FWD 80 // Default speed
#define MOVE_FORWARDS 1
cruise = {CRUISE_SPEED_FWD, CRUISE_SPEED_FWD, FWD,
false, false, 0, MOVE_FORWARDS};
/**
* Cruise Behaviour
*/
void behaviour_cruise(void)
{
}
break;
case RC5_KEY_BACKWARDS: // Move backwards
case RC5_KEY_STOP: // Stop!
// Cruise Behaviour:
#define CRUISE_SPEED_stop 0 // Default speed
#define MOVE_FORWARDS 1
cruise = {CRUISE_SPEED_FWD, CRUISE_SPEED_FWD, FWD,
false, false, 0, MOVE_FORWARDS};
break;
case RC5_KEY_CURVE_LEFT: // Drive curve left - forwards
break;
case RC5_KEY_CURVE_RIGHT: // Drive curve right - forwards
break;
case RC5_KEY_CURVE_BACK_LEFT: // Drive curve left - backwards
break;
case RC5_KEY_CURVE_BACK_RIGHT: // Drive curve right - backwards
break;
case RC5_KEY_LEFT_MOTOR_FWD: // Only left motor on - forwards
break;
case RC5_KEY_LEFT_MOTOR_BWD: // Only left motor on - backwards
break;
case RC5_KEY_RIGHT_MOTOR_FWD: // Only right motor on - forwards
break;
case RC5_KEY_RIGHT_MOTOR_BWD: // Only right motor on - backwards
break;
case RC5_KEY_LIGHT: //Front- und Rück- LEDs gehen an
break;
case RC5_KEY_LIGHT_OFF: //Front- und Rück- LEDs gehen aus
break;
}
}
}
// ------------------------------------
// IMPORTANT - reset the block flag:
block = false;
}
/**
* A small useful routine, to show that the Program is running and not locked up.
* It lets a '*' character blink with 1Hz on the LC-Display.
* When you change the program and it seems to lock up under certain conditions, you
* can see if at least the main loop is still working or if only the I2C Bus Interface
* is locked up.
*/
void task_LCDHeartbeat(void)
{
static uint8_t heartbeat = false;
if(getStopwatch1() > 500)
{
if(heartbeat)
{
clearPosLCD(0, 15, 1);
heartbeat = false;
}
else
{
setCursorPosLCD(0, 15);
writeStringLCD_P("*");
heartbeat = true;
}
setStopwatch1(0);
}
}
/************************************************** ***************************/
// I2C Error handler
/**
* This function gets called automatically if there was an I2C Error like
* the slave sent a "not acknowledge" (NACK, error codes e.g. 0x20 or 0x30).
* The most common mistakes are:
* - using the wrong address for the slave
* - slave not active or not connected to the I2C-Bus
* - too fast requests for a slower slave
* Be sure to check this if you get I2C errors!
*/
void I2C_transmissionError(uint8_t errorState)
{
writeString_P("\nI2C ERROR - TWI STATE: 0x");
writeInteger(errorState, HEX);
writeChar('\n');
block = false;
}
/************************************************** ***************************/
// Main function - The program starts here:
int main(void)
{
initRP6Control(); // Always call this first! The Processor will not work
// correctly otherwise.
initLCD();
writeString_P("\n\nRP6 CONTROL M32 I2C Master Example Program!\n");
writeString_P("\nInterrupts...\n");
// IMPORTANT:
I2CTWI_initMaster(100); // Initialize the TWI Module for Master operation
// with 100kHz SCL Frequency
// Also very important in this example:
// Register the event handlers:
I2CTWI_setTransmissionErrorHandler(I2C_transmissio nError);
I2CTWI_setRequestedDataReadyHandler(I2C_requestedD ataReady);
sound(180,80,25);
sound(220,80,25);
setLEDs(0b1111);
showScreenLCD("################", "################");
mSleep(500);
showScreenLCD("I2C-Master", "Example Program 2");
mSleep(1000);
setLEDs(0b0000);
showScreenLCD("ACS Status:", "");
// ---------------------------------------
// Set ACS to medium power:
I2CTWI_transmit3Bytes(I2C_RP6_BASE_ADR, 0, CMD_SET_ACS_POWER, ACS_PWR_MED);
// Enable Software Watchdog timer on Slave:
I2CTWI_transmit3Bytes(I2C_RP6_BASE_ADR, 0, CMD_SET_WDT, true);
// (This timer stops all operations of the Slave if the Master Controller
// does not react on interrupt requests after a few seconds. This can
// prevent damage if the Master controller locks up but the Slave has still
// the order to drive at high speed... it would maybe crash against a wall
// at high speeds or worser things... )
// ---------------------------------------
startStopwatch1(); // For LCDHeartbeat function
while(true)
{
// You need to call task_I2CTWI frequently out of the
// main loop - otherwise the I2C Bus request functions don't work.
task_checkINT0();
task_I2CTWI();
task_LCDHeartbeat();
}
return 0;
}
Oder liegt der Fehler (auch) ganz woanders?
Wär super!
Danke euch schon mal.
Fabian
@Fabian:
Ich habe ... es jetzt doch mal ausprobiert mit der Base als eigenständigen Prozessor, der selbst alles erledigen kann und der M32 auch alles mitteilt. ... funktioniert nicht.
Wie Dirk schon sagte, geht die Base mit #include_slaveLib in den Slave-Modus und wartet dann nur noch, ob BEFEHLE VON DER M32 KOMMEN. Ob es eigene Befehle zu verarbeiten gibt, wird ignoriert.
Naja, ganz so ist es nicht. Die Base kann schon was Eigenes machen UND als Slave auf Befehle vom Master warten. Alles eine Frage der Programmierung.
Hab jetzt zwei Stunden damit verbracht, mein Beispiel 7 des M32 umzuschreiben, damit ich die von der Base empfangenen RC5-Daten in Motorbewegungen umwandeln kann... Klappt nicht!
Also: Du willst mit der M32 als Master die RC5-Daten von der Base per I2C bekommen und dann den RP6 per I2C in Bewegung setzen.
Dazu ist das Example RP6Control_07_I2CMaster als Grundlage gut geeignet.
Wenn du dann eine Taste von der Fernbedienung empfängst (z.B. bei case RC5_KEY_LEFT: // Turn left) müßtest du dann ja den Befehl geben, dass der RP6 linksherum fährt. Das ist ja dann ein I2C-Befehl.
Wie das aussieht, kannst du in der RP6Control_I2CMasterLib im Bereich "New movement functions" sehen.
Aber: Du bist auf dem richtigen Weg! Nicht aufgeben! \:D/
Gruß Dirk
So, hab mich nun bemüht.
Hab also die neue Lib eingebunden, auch im Makefile.
Hab überflüssiges aus dem Programm rausgelöscht, was schon in der Lib steht.
Jetzt kommt dieser Fehler:
RP6Control_I2CMasterLib.o: In function `BUMPERS_stateChanged_DUMMY':
C:\Dokumente und Einstellungen\Fabian Queck\Desktop\RP6\RP6-Library\RP6Examples\MeineProgramme\M32_für_TV_REMO TE/RP6Control_I2CMasterLib.c:31: multiple definition of `block'
M32_für_TV_REMOTE.o:C:\Dokumente und Einstellungen\Fabian Queck\Desktop\RP6\RP6-Library\RP6Examples\MeineProgramme\M32_für_TV_REMO TE/M32_für_TV_REMOTE.c:384: first defined here
make: *** [M32_für_TV_REMOTE.elf] Error 1
Allerdings weiß ich nicht, was er meint. Hab die Lib nicht angerührt/verändert. Trotzdem gefällt ihm ein "block" nicht, der aber nicht an der angegebenen Stelle (Zeile 31) steht...
Dafür kommt "Block" einige Male in meinem Hauptprog vor...
Noch eine Frage an Dich, Dirk:
Du meintest, man könne DOCH die Base selbstständig alles machen lassen, wobei die M32 TROTZDEM eingreifen kann.
Genau das will ich! Aber wie sähe das aus?
Ist das für mich Anfänger zu schwer, oder kannst Du mir das erklären?
Ich fände es schon um einiges besser, wenn die Base ihre sachen macht (Motoren, BatÜberwachung, RC5, ACS, Bumper, Lichtsensoren und ab nächster Woche auch noch Abstandserkennung hinten via ADC0&1).
Dazu soll sie noch alle daten auf den I2C schreiben (damit der M32 darauf reagieren kann) und gegebenenfalls, wenn ein Interrupt (?) von der M32 kommt, darauf reagieren.
=D>
Danke schon mal,
ich weiß, ich bin anstrengend :D
RP6conrad
26.11.2010, 00:10
Multiple definition meint das eine variable mehrfach definiert werd. Und das darf nicht sein. Ursache : eine lib die zweimal eingebunden wird ? Das ist der grund das beim eine library immer anfangt mit #ifndef RP6CONFIG_H
#define RP6CONFIG_H
Damit weiss der compiler das die lib schon eingebunden war, und macht es kein zweite mal.
Was sie wollen geht sicher. Jetzt ist der Slafe so programmiert das er nur noch Fahrauftrage von Master macht. Das Teil muss dan geandert werden, sowohl in Slafe program und in Master program. Gar nicht so einfach da sie jetzt auf zwei Fronten Fehler machen kann. Hatte bei mir auch einige Wochen gedauert, um diesen zusammenhang zwischen Base und Master zu durchgrunden.
@fabqu:
Ich fände es schon um einiges besser, wenn die Base ihre sachen macht (Motoren, BatÜberwachung, RC5, ACS, Bumper, Lichtsensoren ...
mmmmh DAS macht das Slave Programm doch schon.
Die komplette Motorregelung und ACS auswertung läuft unabhängig vom Erweiterungsmodul - und entlastet diesen Prozessor so von diesen Aufgaben.
Das ist ja Sinn und Zweck der ganzen Sache.
Wie RP6conrad schon schreibt - man muss nur einen einzelnen Befehl an den Controller senden und der regelt dann die Motorgeschwindigkeit oder fährt ne bestimmte Distanz o.ä.
Ändert sich das ACS wird der Master benachrichtigt... usw.
Die M32 ist DOPPELT SO SCHNELL getaktet wie der Controller auf der Base also ist es logisch das Erweiterungsmodul als Master zu verwenden. Man nimmt bei Robotern eigentlich IMMER den leistungsfähigeren Controller für High-Level Steuerung.
MfG,
SlyD
Jo, das ist ja soweit klar.
Was ich wollte ist aber, dass beide unabhängig arbeiten können.
Also dass die Base selbst auf ACS, Bumper... reagieren kann und die M32 sich darum nicht mehr kümmern muss. Denn diese Aufgaben kann die Base auch bei der Hälfte der M32-Taktung übernehmen.
Denn meine M32 soll sich dann mit gaaaanz anderen Sachen rumschlagen (Servos, andere Sensoren). Klar schafft die auch beides, aber ich wollts eben so...
So dachte ich mir das zumindest.
Ich glaube, ich bringe hier grad nen Wurm rein...
Ich werds einfach mal versuchen, vielleicht kann Dirk mir dabei helfen.
Gruß,
Fabian
Ahso Ok am elegantesten wäre das zu realisieren indem Du das ganze mit ner Subsumptionsarchitektur löst wie in den fortgeschrittenen Beispielen der Base gezeigt - das dann mit dem I2C Slave Programm kombiniert.
Die I2C Steuerung wäre dann eines oder mehrere zusätzliche Verhalten (nicht notwendigerweise das mit der höchsten Pritorität - Bumper ausweichen usw. müsste immer noch die höchste Prio haben)
Auf dem Erweiterungsmodul könnten weitere Verhalten laufen und die Verhalten auf der Base per I2C fernsteuern.
Das ist allerdings schon etwas komplexer zu realisieren also musst dich auf einiges an Arbeit einstellen ;)
Machbar ist das aber natürlich.
MfG,
SlyD
@Fabian:
Ich fände es schon um einiges besser, wenn die Base ihre sachen macht (Motoren, BatÜberwachung, RC5, ACS, Bumper, Lichtsensoren und ab nächster Woche auch noch Abstandserkennung hinten via ADC0&1).
Dazu soll sie noch alle daten auf den I2C schreiben (damit der M32 darauf reagieren kann) und gegebenenfalls, wenn ein Interrupt (?) von der M32 kommt, darauf reagieren.
Da müssen wir mal die Programmideen sortieren:
RP6Base (I2C-Slave Programm):
-> Die Motoren
Die Motoren werden geschwindigkeits-geregelt und können vollständig über I2C gesteuert werden. Was du willst (?) wäre eine Doppelfunktion: Fremdsteuerung bei Bedarf (über I2C von der M32) UND eine Eigensteuerung durch die Base. Teil 1 (Fremdsteuerung) funktioniert schon, die Eigensteuerung müßtest du selbst schreiben. Dazu gehört, dass du dir überlegst, auf WAS die (Motoren der) Base selbst reagieren soll(en) (ACS, Helligkeit, Bumper, ...) und in welchen Fällen die Steuerung von der M32 dazwischenfunken darf.
-> BatÜberwachung
Funktioniert jetzt schon und kann über I2C von der M32 gelesen werden. Was du willst (?) wäre eine Doppelfunktion: Lesen über I2C durch die M32 UND eigene Reaktion der Base auf die Ubat. Du müßtest jetzt überlegen, WIE die Base reagieren soll: Stoppen bei niedriger Ubat, Blinken der LEDs, Warnung über UART und müßtest das dann programmieren.
-> RC5
RC5 Empfang erfolgt schon durch das I2C-Slave-Programm und kann über I2C von der M32 gelesen werden. Was du willst (?) wäre auch eine eigene Reaktion der Base auf RC5. Du müßtest also überlegen, wie die Base auf die TV-Fernbedienung reagieren soll und das dann programmieren. Dazu must du festlegen, unter welchen Bedingungen evtl. die M32 sich einklinken soll und die Base nicht direkt auf RC5 agieren darf.
-> ACS, Bumper
Das ACS und die Bumper werden ausgewertet und können über I2C von der M32 gelesen werden. Du willst (?), dass die Base auch selbst auf das ACS und die Bumper reagieren kann. Das geht auch, aber du must ihr beibringen, wie sie auf das ACS, Bumper reagieren soll.
-> Lichtsensoren
Auch die können schon über I2C von der M32 ausgelesen werden. Wenn die Base selbst darauf reagieren soll, must du überlegen, was sie damit machen soll (zum Licht fahren oder in die Dunkelheit oder ...)
-> ADC0/1
Auch die ADC-Kanäle können schon von der M32 ausgelesen werden (I2C-Register 23..26). Wenn die Base selbst darauf reagieren soll, müßtest du programmieren, wie diese Reaktion aussehen soll.
-> Soll auf einen Interrupt von der M32 reagieren
Das muss sie gar nicht. Als Slave muss sie sowieso auf den Master hören und auf Nachrichten vom Master reagieren. Dazu gehört, dass man sich einen "Vokabelschatz" überlegt, den beide (Master und Slave kennen), d.h. der Slave muss wissen, wie er auf Kommandos vom Master reagieren soll. Dazu muss er auch noch die von dir gewünschte (?) Eigenintelligenz zurückstellen, wenn er Befehle vom Master annimmt. Das geht auch, muss aber genau überlegt und dann im Slave und Master programmiert werden.
Control M32 (Master - eigenes Programm):
-> Soll auf Daten von der Base reagieren
Naja, sicher müßte die M32 auch reagieren, aber eigentlich fordert sie ja selbst die Daten an und weiß dann ja, was sie damit machen will. Man müßte überlegen, wo die "Hauptintelligenz" sitzt. D.h. wer bestimmt, was gemacht werden soll: M32 oder Base oder abwechselnd? Wenn abwechselnd: Was sind die Regeln dafür?
-> Soll einen Interrupt an die Base schicken (die reagiert dann darauf)
Die M32 ist ja Master und braucht den Interrupt nicht. Sie kann einfach über I2C einen Befehl senden.
@Fabian:
Warum der lange und merkwürdige Text?
Als Anregung: Überleg dir evtl. noch einmal, was dein RP6 (mit M32 drauf) genau leisten soll. Dann ergibt sich die Aufgabenverteilung quasi automatisch.
Gruß Dirk
Jajajajaja! Das ist quasi alles richtig so!
Die Base steuert die Motoren und reagiert zunächst nur auf eigene Systeme (ACS, Bumper, Licht, Bat, ADC0&1, RC5,...)
Nun bekommt die M32 aber auch alles mit, was da unten so läuft und kann eigene Routinen abfahren (z.B.: Ist Batterie leer, bleibt die Base von sich aus stehen, dreht sich vielleicht auch im Kreis, blinkt mit allen LEDs. DAZU blinken auch die LEDs der M32 und der Beeper geht nervig los; nur mal als Beispiel). Außerdem soll die M32 mal ein oder zwei Robotarme mit deiner (Dirk) 8-Servo-Lib steuern...
das bisher genannte könnte ich (ich hoffe ich übernehme mich nicht) vielleicht sogar irgendwie hinkriegen, mit eurer Hilfe, einem Unikurs im nächsten Semester und ZEIT :)
Ich denke, es wäre gut, wenn ich es als erstes Teilprojekt mal dabei belasse. Bin denke ich damit gut aufgestellt!
Danach könnte man dann angehen, wie die M32 dennoch in die Vorgänge auf der Base eingreifen soll (sagen wir mal, die Base soll Wärmequellen suchen, aber die Sensorik (PIR, Snakevision) dafür liegt an der M32 an).
Und im letzten Schritt könnte man dann mein eigentliches Ziel umsetzen:
Der Rp6 ist gänzlich über RC5 gesteuert, kann aber auf Befehl in eigene Programmteile springen (z.B. "Lichtverfolgung", "Wärmequellenverfolgung",...) und wird erst bei Senden EINES bestimmten RC5-Signals wieder Fernsteuerbar.
So zumindest hatte ich mir das überlegt...
Danke schon mal!
Werd mir mal gedanken machen, wie man das so umsetzen könnte und ein bischen rumprobieren.
--Mal was anderes:
--Sollte man das alles vielleicht in einen neuen Thread stellen???
Hier mal mein bisheriger Stand des Programms:
Leider reagiert der RP6 aber auf gar nix mehr...
// 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();
}
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();
}
}
/************************************************** ***************************/
/************************************************** ***************************/
// Speed values:
#define MAX_SPEED_MOVE 200
#define MAX_SPEED_TURN 100
#define MAX_SPEED_CURVE 120
#define MAX_SPEED_CURVE2 40
#define ACCELERATE_CURVE 10
#define ACCELERATE_CURVE2 4
#define DECELERATE_CURVE 4
#define DECELERATE_CURVE2 2
#define MAX_SPEED_1_MOTOR 120
#define ACCELERATE_VALUE 8
#define DECELERATE_VALUE 4
uint8_t max_speed_left; // Maximum speed variable left
uint8_t max_speed_right; // Maximum speed variable right
uint8_t acl_left;
uint8_t acl_right;
uint8_t decl_left;
uint8_t decl_right;
/************************************************** ***************************/
/**
* Just a small helper function to set speed params.
*/
void setDefaultSpeedParameters(void)
{
max_speed_left = MAX_SPEED_MOVE;
max_speed_right = max_speed_left;
acl_left = ACCELERATE_VALUE;
acl_right = ACCELERATE_VALUE;
decl_left = DECELERATE_VALUE;
decl_right = DECELERATE_VALUE;
uint16_t tmp = (getDesSpeedLeft() + getDesSpeedRight())/2;
moveAtSpeed(tmp , tmp);
}
/**
* RC5 Data reception handler - this function is called automatically from the
* RP6lib if new RC5 Data has been received.
*/
void receiveRC5Data(RC5data_t rc5data)
#define Remote_Controll
#ifdef Remote_Controll
#define RC5_KEY_LEFT 4
#define RC5_KEY_RIGHT 6
#define RC5_KEY_FORWARDS 2
#define RC5_KEY_BACKWARDS 8
#define RC5_KEY_STOP 5
#define RC5_KEY_CURVE_LEFT 1
#define RC5_KEY_CURVE_RIGHT 3
#define RC5_KEY_CURVE_BACK_LEFT 7
#define RC5_KEY_CURVE_BACK_RIGHT 9
#define RC5_KEY_LEFT_MOTOR_FWD 32 //Ch+
#define RC5_KEY_LEFT_MOTOR_BWD 33 //Ch-
#define RC5_KEY_RIGHT_MOTOR_FWD 16 //Vol+
#define RC5_KEY_RIGHT_MOTOR_BWD 17 //Vol-
#define RC5_KEY_ALERT 0 //Auf der '0'-Taste blinken LEDs
#define RC5_KEY_LIGHT 13 //Auf der 'Stumm' gehen Postitions-LEDs an
#define RC5_KEY_LIGHT_OFF 34 //Auf der Pfeil-Taste gehen Lichter aus
#endif
{
// Output the received data:
writeString_P("Toggle Bit:");
writeChar(rc5data.toggle_bit + '0');
writeString_P(" | Device Address:");
writeInteger(rc5data.device, DEC);
writeString_P(" | Key Code:");
writeInteger(rc5data.key_code, DEC);
writeChar('\n');
uint8_t movement_command = false; // used to store if we have received
// a movement command.
// Any other key is ignored!
//Für den Slave: ------------------------------------
lastRC5Reception.toggle_bit = rc5data.toggle_bit;
lastRC5Reception.device = rc5data.device;
lastRC5Reception.key_code = rc5data.key_code;
interrupt_status.RC5reception = true;
signalInterrupt();
//---------------------------------------------------
// Check which key is pressed:
switch(rc5data.key_code)
{
//hier sind halt alle meine Befehle drin...
//musste ich kürzen, da sonst der Text zu lang wurde (>20.000 Zeichen)
}
if(movement_command) // Did we receive a move command?
{
// Accelerate if neccessary:
if(getDesSpeedLeft() < max_speed_left) // If we have not reached the left maximum speed...
{ // ... accelerate!
moveAtSpeed(getDesSpeedLeft()+acl_left, getDesSpeedRight());
if(getDesSpeedLeft() < 10)
moveAtSpeed(10, getDesSpeedRight());
}
if(getDesSpeedRight() < max_speed_right) // If we have not reached the right maximum speed...
{
// ... accelerate!
moveAtSpeed(getDesSpeedLeft(), getDesSpeedRight()+acl_right);
if(getDesSpeedRight() < 10)
moveAtSpeed(getDesSpeedLeft(), 10);
}
// Start Stopwatch 1 - it starts decceleration after 250ms of no RC5 reception! (s. below)
setStopwatch1(0);
startStopwatch1();
}
}
/************************************************** ***************************/
/**
* This function is called frequently out of the main loop and checks if
* Stopwatch1 has counted at least 250ms. If this is the case, decceleration is started
* and the Stopwatch is resetted and the progtam waits for next 250ms to pass by.
* Stopwatch1 ist set to 0 and started from the RC5 reception handler after
* each reception of a valid keycode. (s. above)
*/
void deccelerate(void)
{
if(getStopwatch1() > 250) // After 250ms with no reception...
{
if(getDesSpeedLeft() <= 10) // If left speed is less or equal than 10...
moveAtSpeed(0, getDesSpeedRight()); // ... stop the left motor
else // Otherwise continue to deccelerate:
moveAtSpeed(getDesSpeedLeft()-decl_left, getDesSpeedRight());
if(getDesSpeedRight() <= 10) // If right speed is less or equal than 10...
moveAtSpeed(getDesSpeedLeft(), 0); // ... stop the right motor
else // Otherwise continue to deccelerate:
moveAtSpeed(getDesSpeedLeft(), getDesSpeedRight()-decl_right);
if (getDesSpeedRight() == 0 && getDesSpeedLeft() == 0)
stopStopwatch1(); // Decceleration has finished!
max_speed_left = getDesSpeedLeft(); // Update max_speed value
max_speed_right = getDesSpeedRight(); // Update max_speed value
setLEDs(0b000000); // and clear LEDs
setStopwatch1(0);
}
// Make sure we don't move after Direction has changed and key is released too fast.
// This prevents the RP6 from moving when the direction has just changed and temporary saved
// speed value is written back again in the task_motionControl function.
if(getDesSpeedLeft() > max_speed_left)
{
if(getDesSpeedLeft() <= 10) // If left speed is less or equal than 10...
moveAtSpeed(0, getDesSpeedRight()); // ... stop the left motor
else // decelerate:
moveAtSpeed(getDesSpeedLeft()-decl_left, getDesSpeedRight());
}
if(getDesSpeedRight() > max_speed_right)
{
if(getDesSpeedRight() <= 10) // If right speed is less or equal than 10...
moveAtSpeed(getDesSpeedLeft(), 0); // ... stop the right motor
else // decelerate:
moveAtSpeed(getDesSpeedLeft(), getDesSpeedRight()-decl_right);
}
}
/************************************************** ***************************/
// Main - The program starts here:
int main(void)
{
initRobotBase();
setLEDs(0b111111);
writeChar('\n');
writeString_P("RP6 controlled by RC5 TV Remote\n");
writeString_P("___________________________\n");
mSleep(500);
setLEDs(0b000000);
// Set the RC5 Receive Handler:
IRCOMM_setRC5DataReadyHandler(receiveRC5Data);
//Für den Slave:-----------------------------------
I2CTWI_initSlave(RP6BASE_I2C_SLAVE_ADR);
ACS_setStateChangedHandler(acsStateChanged);
BUMPERS_setStateChangedHandler(bumpersStateChanged );
IRCOMM_setRC5DataReadyHandler(receiveRC5Data);
//-------------------------------------------------
powerON();
//Output small usage instructions and the RC5 Codes:
writeString_P("\nYou can control your RP6 with the following RC5 Keycodes:");
writeString_P("\n-----------------------");
writeString_P("\n * Turn Left: "); writeInteger(RC5_KEY_LEFT, DEC);
writeString_P("\n * Turn Right: "); writeInteger(RC5_KEY_RIGHT, DEC);
writeString_P("\n * Move Forwards: "); writeInteger(RC5_KEY_FORWARDS, DEC);
writeString_P("\n * Move Backwards: "); writeInteger(RC5_KEY_BACKWARDS, DEC);
writeString_P("\n * Stop: "); writeInteger(RC5_KEY_STOP, DEC);
writeString_P("\n * Move curve left forwards: "); writeInteger(RC5_KEY_CURVE_LEFT, DEC);
writeString_P("\n * Move curve right forwards: "); writeInteger(RC5_KEY_CURVE_RIGHT, DEC);
writeString_P("\n * Move curve left backwards: "); writeInteger(RC5_KEY_CURVE_BACK_LEFT, DEC);
writeString_P("\n * Move curve right backwards: "); writeInteger(RC5_KEY_CURVE_BACK_RIGHT, DEC);
writeString_P("\n * Motor left forwards: "); writeInteger(RC5_KEY_LEFT_MOTOR_FWD, DEC);
writeString_P("\n * Motor left backwards: "); writeInteger(RC5_KEY_LEFT_MOTOR_BWD, DEC);
writeString_P("\n * Motor right forwards: "); writeInteger(RC5_KEY_RIGHT_MOTOR_FWD, DEC);
writeString_P("\n * Motor right backwards: "); writeInteger(RC5_KEY_RIGHT_MOTOR_BWD, DEC);
writeString_P("\n-----------------------\n");
writeString_P("To change the key mapping, read the comments in the program source code!\n");
writeString_P("_________\nPlease make sure that your IR Remote Control really transmits RC5 code!\n");
startStopwatch2();
//Für den Slave:------------------------------
startStopwatch1();
disableACS();
setACSPwrOff();
status.byte = 0;
interrupt_status.byte = 0;
drive_status.byte = 0;
status.watchDogTimer = false;
status.wdtRequestEnable = false;
startStopwatch3();
startStopwatch4();
//-------------------------------------------
// Main loop
while(true)
{
task_update(); //Slave!
task_updateRegisters(); //Slave!
deccelerate(); // Call the deceleration function.
task_RP6System(); // Motion Control tasks etc.
}
return 0;
}
Wo liegt denn der Fehler?
Danke,
Fabian
Wo liegt denn der Fehler?
Wahrscheinlich daran, dass aus 2 zusammengefügten Programmen nicht automatisch ein funktionsfähiges neues Programm wird. O:)
Ich habe es nicht probiert, aber vielleicht wäre dies hier ein Anfang:
Du nimmst dir die RP6Base_I2CSlave.c und fügst in die Hauptschleife ein:
task_TVRemote(); // New TV Remote task!
Die Funktion task_TVRemote() fügst du über der Main ein:
/************************************************** ***************************/
// Task TV Remote
/**
* This is a simple TV Remote task.
*/
#define RC5_KEY_FORWARDS 2
#define RC5_KEY_BACKWARDS 8
#define RC5_KEY_STOP 5
void task_TVRemote(void)
{
if (lastRC5Reception.key_code) {
writeString_P("Key Code: ");
writeInteger(lastRC5Reception.key_code, DEC);
writeString_P("\n");
/*
switch(lastRC5Reception.key_code)
{
case RC5_KEY_FORWARDS: // Drive forwards:
changeDirection(FWD);
moveAtSpeed(80, 80);
break;
case RC5_KEY_BACKWARDS: // Drive backwards:
changeDirection(BWD);
moveAtSpeed(80, 80);
break;
case RC5_KEY_STOP: // Stop:
// changeDirection(FWD);
moveAtSpeed(0, 0); // stop moving!
}
*/
lastRC5Reception.key_code = 0;
}
}
So, wie es ist, wird der RC5-Code nur auf dem Terminal angezeigt. Du kannst aber auch Fahrbefehle (Vorwärts, Stop, Rückwärts) geben.
Auf der ControlM32 kann dabei z.B. Example_08_I2CMaster laufen. Wenn du das UART-Kabel auf die M32 umsteckst, wird der RC5-Code auch am Terminal gezeigt.
Wie gesagt: Nicht getestet ... und sicher auch nicht optimal in das Ausgangsprogramm integriert ... :-k
Gruß Dirk
Stimmt soweit.
Nur: Die RC5-Befehle gehen nicht an das Terminal, aber das könnte man ja einfügen.
Aber was bedeutet denn dann der Befehl z.B.
changeDirection(FWD);
moveAtSpeed(80, 80);
?
Müsste er sich dann nicht bewegen?
Und ich musste das IRCOM_OFF aus dem Slave-Main entfernen!?
Fabian
@Fabian:
Ja, das ist der Fahrbefehl für vorwärts.
Die RC5-Kommandos gehen mit writeInteger(lastRC5Reception.key_code, DEC); ans Terminal.
Gruß Dirk
@Dirk
Aber warum fährt er denn dann nicht?
Fabian
Hast du "/*" und "*/" vor und nach dem switch-Konstrukt entfernt?
Gruß Dirk
:D
Das is ja peinlich
;)
Jetz gehts!
Werd da mal ein bisschen dran rumprobieren...
Hab jetzt auch das ganze Beschleunigungszeug und meine anderen Befehle aus der TV-Remote übernommen, klappt alles wunderbar!!!
Danke Dir.
Damit ist für mich schon mal verdammt viel erreicht :DDDD
Jetzt versuch ich mal, die Bumper miteinzubeziehen.
Damit, wenn ich mich blöd anstelle und -- ferngesteuert -- das Ding an die Wand setze, der RP6 dann selbstständig ein Stück zurücksetzt, dreht und erst dann wieder steuerbar wird :)
SUPER!
Danke Dir Dirk, hast mir echt geholfen ;)
Schönen Sonntag Euch,
Fabian
In meinem Programm gibt es folgenden Code, um RC5 Daten von der Base auf der M32 zu empfangen (ist hier das Bsp 07):
// Check if there was a RC5 Reception:
if(interrupt_status.RC5reception)
{
uint8_t readBuf[2];
writeString_P("Received RC5 Transmission: ");
I2CTWI_transmitByte(I2C_RP6_BASE_ADR,I2C_REG_RC5_A DR);
I2CTWI_readBytes(I2C_RP6_BASE_ADR, readBuf, 2);
writeString_P("ADR:");writeInteger(readBuf[0],DEC);
writeString_P(" | DATA:");writeInteger(readBuf[1],DEC);
writeString_P("\n");
}
Was müsste ich denn hier eingeben, damit ich hier auf verschiedene Remote-Tasten z.B. I/Os schalten kann, oder LEDs etc?
Bei meinen Versuchen tat sich nix.
Und noch etwas zu Base-Programm:
void bumpersStateChanged(void)
{
interrupt_status.bumperLeft = bumper_left;
if(bumper_right)
interrupt_status.bumperRight = true;
else
interrupt_status.bumperRight = false;
signalInterrupt();
}
Hier würde ich gerne der Base beibringen, dass sie beim Auslösen der Bumper anhalten soll, dann ein Stück zurückfahren und erst dann wieder auf RC5 reagieren soll.
Wie stell ich denn sowas an?
Ich hab versucht, mir das vom Move-Bsp-Programm abzugucken, hat aber nicht geklappt...
Kann mir da jemand helfen?
Danke Euch
\:D/
Fabian
hab jetzt folgendes gemacht:
/**
* Bumpers Event Handler
*/
void bumpersStateChanged(void)
{
interrupt_status.bumperLeft = bumper_left;
if(bumper_right)
interrupt_status.bumperRight = true;
else
interrupt_status.bumperRight = false;
signalInterrupt();
move(60, BWD, DIST_MM(300), true);
rotate(50, RIGHT, 90, false);
}
Problem:
Wenn ich den Blocking-Parameter der Rotate-Fkt. auf "false" setze, dann beendet er das Programm nach Abfahren der Strecke und Rotieren und will einen Reset.
Wenn ich den Parameter auf "true" setze, macht er das Gleiche, nur dass er dreimal rotiert... ???
Außerdem arbeitet er auch sonst nix mehr ab (sendet nichts mehr ans Terminal, und legt nichts auf den I2C für die M32).
:-k
Was stimmt da nicht?
Was aber funktioniert hat, war statt anderen Befehlen einfach ein
stop();
mSleep(2000);
Dann geht soweit alles und Schlimmeres wird verhindert ;)
Auch wenn es einen Moment dauert, bis er anhält...
Dann zum M32:
Ich möchte ein paar LEDs schalten auf RC5-Code 13 (ein) und 34 (aus).
Hab das so versucht:
// ------------------------------------
// Check if there was a RC5 Reception:
if(interrupt_status.RC5reception)
{
uint8_t readBuf[2];
writeString_P("Received RC5 Transmission: ");
I2CTWI_transmitByte(I2C_RP6_BASE_ADR,I2C_REG_RC5_A DR);
I2CTWI_readBytes(I2C_RP6_BASE_ADR, readBuf, 2);
writeString_P("ADR:");writeInteger(readBuf[0],DEC);
writeString_P(" | DATA:");writeInteger(readBuf[1],DEC);
writeString_P("\n");
if(I2C_REG_RC5_DATA == 13)
{
DDRC |= IO_PC7; //PC7 ist nun auf OUT
PORTC |= IO_PC7; //PC7 ist nun High
}
else if(I2C_REG_RC5_DATA == 34)
{
DDRC |= IO_PC7; //PC7 ist nun auf OUT
PORTC &= ~IO_PC7; //PC7 ist nun Low
}
}
Aber es passiert leider nichts.
Danke schon mal,
Fabian
Aha, das erste Problem ist soweit beseitigt, ich weiß nur nicht, ob das zufriedenstellend beseitigt ist:
Problem war der Interrupt für den Master und der Master-Timeout. Da mein Master ja nicht auf Interrupts reagieren kann, hat der Base das gefehlt und es kam zum Shut-Down.
Hab also den Master-Timeout komplett rausgenommen!?
Aber das zweite Problem steht nach wie vor an!
Bräuchte da mal ne Zeile Beispielcode...
Danke!
@Fabian:
Vielleicht machst du es dir für den Anfang zu schwierig.
Fang doch mit einer einfachen Aufgabe an:
Die Control M32 (Master) fordert auf Tastendruck bestimmte Aktionen von der Base (Slave) über I2C an.
Gruß Dirk
wenn ich folgenden code in die slavedatei einfüge
DDRC |= SL1;
PORTC &= ~SL1;
......
for(c=0; c<50; c++) //50 = 50 Impulse senden, das dauert ca. 1 Sekunde
{
PORTC |= SL1; // Impulsstart servo I
sleep(5); // 1 = 0.1ms warten = Servoposition 1
PORTC &= ~SL1; // Impulsende
sleep(150); //50ms warten
}
.........
immer entsprechend case1 = SL1, case2 = SL2, case3 = SL4 und case4 = SL5, funktioniert es was die LEDs betrifft, aber der angeschlossener servo nur bei SL1 und SL2, nicht aber bei SL4 und SL5...
#include"RP6RobotBaseLib.h"
#include "RP6I2CslaveTWI.h"
int main(void)
{
initRobotBase();
powerON();
setACSPwrOff();
uint8_t i;
uint8_t c; // allgemeine 8-Bit-Variable (ein Char)
I2CTWI_initSlave(10);
while (true)
{
if(I2CTWI_writeRegisters[0] && !I2CTWI_writeBusy)
{
// Register speichern:
i = I2CTWI_writeRegisters[0];
I2CTWI_writeRegisters[0] = 0;
switch (i)
{
case 1:
DDRC |= SL1;
PORTC &= ~SL1;
setLEDs(0b000001);
mSleep(500);
setLEDs(0b000000);
// task_motionControl();
// move(30,FWD,DIST_MM(50),false);
for(c=0; c<50; c++) //50 = 50 Impulse senden, das dauert ca. 1 Sekunde
{
PORTC |= SL1; // Impulsstart servo I
sleep(5); // 1 = 0.1ms warten = Servoposition 1
PORTC &= ~SL1; // Impulsende
sleep(150); //50ms warten
}
break;
case 2:
DDRC |= SL2;
PORTC &= ~SL2;
setLEDs(0b000011);
mSleep(500);
setLEDs(0b000000);
// task_motionControl();
// move(30,BWD,DIST_MM(50),false);
for(c=0; c<50; c++)
{
PORTC |= SL2;
sleep(5);
PORTC &= ~SL2;
sleep(150);
}
break;
case 3:
DDRC |= SL4;
PORTC &= ~SL4;
setLEDs(0b000111);
mSleep(500);
setLEDs(0b000000);
// task_motionControl();
// rotate(30,LEFT,20,false);
for(c=0; c<50; c++)
{
PORTC |= SL4;
sleep(5);
PORTC &= ~SL4;
sleep(150);
}
break;
case 4:
DDRC |= SL5;
PORTC &= ~SL5;
setLEDs(0b001111);
mSleep(500);
setLEDs(0b000000);
// task_motionControl();
// rotate(30,RIGHT,20,false);
for(c=0; c<50; c++)
{
PORTC |= SL5;
sleep(5);
PORTC &= ~SL5;
sleep(150);
}
break;
default:
setLEDs(0b111111);
mSleep(500);
setLEDs(0b000000);
}
}
}
return 0;
}
ich komme einfach nicht dahinter warum???
Hallo
SL4 und SL5 sind am Port B zu finden, nicht am Port C :wink:
TrainMen
14.12.2010, 05:01
Hi fabqu,
Wenn der Code von der Fernbedienung am RP6 ankommt wüsste ich nicht warum es nicht funktionieren sollte. Ich schalte z.B Scheinwerfer und Kamera so ein. Hast Du Deine LED richtig rum. Der Pin ist Plus.
Trainmen
Hi trainman,
Mein Problem war die Bezeichnung der RC5 Signale, also der genaue Code, den ich verwenden muss. Ich könnt in der Lib evtl nachsehen, wenn mein pc nicht letze Woche gecrasht ware! Fabian
Was mache ich denn scho wieder falsch???
Da mir mein PC abgeka**t ist, musste ich meine Ganzen Daten auf einen alten PC laden.
Hab also an und für sich NICHTS verändert, trotzdem kann ich jetzt nichts mehr kompilieren!!!
Folgende Fehlermeldung kommt:
Compiling: RP6Base_TV_REMOTE_mitSlave.c
avr-gcc -c -mmcu=atmega32 -I. -gdwarf-2 -Os -funsigned-char -funsigned-bitfields -fpack-struct -fshort-enums -Wall -Wstrict-prototypes -Wa,-adhlns=RP6Base_TV_REMOTE_mitSlave.lst -I../../RP6Lib -I../../RP6Lib/RP6base -I../../RP6Lib/RP6common -std=gnu99 -MD -MP -MF .dep/RP6Base_TV_REMOTE_mitSlave.o.d RP6Base_TV_REMOTE_mitSlave.c -o RP6Base_TV_REMOTE_mitSlave.o
../../RP6Lib/RP6base/RP6RobotBaseLib.h:180: warning: inline function 'isMovementComplete' declared but never defined
../../RP6Lib/RP6base/RP6RobotBaseLib.h:67: warning: inline function 'setLEDs' declared but never defined
../../RP6Lib/RP6base/RP6RobotBaseLib.h:180: warning: inline function 'isMovementComplete' declared but never defined
../../RP6Lib/RP6base/RP6RobotBaseLib.h:67: warning: inline function 'setLEDs' declared but never defined
Linking: RP6Base_TV_REMOTE_mitSlave.elf
avr-gcc -mmcu=atmega32 -I. -gdwarf-2 -Os -funsigned-char -funsigned-bitfields -fpack-struct -fshort-enums -Wall -Wstrict-prototypes -Wa,-adhlns=RP6Base_TV_REMOTE_mitSlave.o -I../../RP6Lib -I../../RP6Lib/RP6base -I../../RP6Lib/RP6common -std=gnu99 -MD -MP -MF .dep/RP6Base_TV_REMOTE_mitSlave.elf.d RP6Base_TV_REMOTE_mitSlave.o ../../RP6Lib/RP6base/RP6RobotBaseLib.o ../../RP6Lib/RP6common/RP6uart.o ../../RP6Lib/RP6common/RP6I2CslaveTWI.o --output RP6Base_TV_REMOTE_mitSlave.elf -Wl,-Map=RP6Base_TV_REMOTE_mitSlave.map,--cref -lm
RP6Base_TV_REMOTE_mitSlave.o: In function `deccelerate':
C:\Dokumente und Einstellungen\user3\Desktop\RP6\RP6-Library\RP6Examples\MeineProgramme\TV_REMOTE_mitSl ave/RP6Base_TV_REMOTE_mitSlave.c:696: undefined reference to `setLEDs'
RP6Base_TV_REMOTE_mitSlave.o: In function `task_commandProcessor':
C:\Dokumente und Einstellungen\user3\Desktop\RP6\RP6-Library\RP6Examples\MeineProgramme\TV_REMOTE_mitSl ave/RP6Base_TV_REMOTE_mitSlave.c:351: undefined reference to `setLEDs'
RP6Base_TV_REMOTE_mitSlave.o: In function `main':
C:\Dokumente und Einstellungen\user3\Desktop\RP6\RP6-Library\RP6Examples\MeineProgramme\TV_REMOTE_mitSl ave/RP6Base_TV_REMOTE_mitSlave.c:726: undefined reference to `setLEDs'
C:\Dokumente und Einstellungen\user3\Desktop\RP6\RP6-Library\RP6Examples\MeineProgramme\TV_REMOTE_mitSl ave/RP6Base_TV_REMOTE_mitSlave.c:728: undefined reference to `setLEDs'
RP6Base_TV_REMOTE_mitSlave.o: In function `motionControlStateChanged':
C:\Dokumente und Einstellungen\user3\Desktop\RP6\RP6-Library\RP6Examples\MeineProgramme\TV_REMOTE_mitSl ave/RP6Base_TV_REMOTE_mitSlave.c:141: undefined reference to `isMovementComplete'
make: *** [RP6Base_TV_REMOTE_mitSlave.elf] Error 1
> Process Exit Code: 2
> Time Taken: 00:24
Kann mir jemand helfen?
Vor dem Kopieren des gesamten Ordners ging noch alles.
Gruß,
Fabian
C:\Dokumente und Einstellungen\user3\Desktop..........
An dem wird es wahrscheinlich liegen
Und wie kann ich das beheben?
Bzw wo muss ich das umändern?
Im Makefile?
Fabian
Kannst du dein Makefile zeigen?
Standartmässig ist es bei dir auch nicht mehr,
z.B. C:\Dokumente und Einstellungen\user3\Desktop\RP6\RP6-Library\RP6Examples\MeineProgramme
das gleiche soll eigentlich im Makefile sein.
Der Kompiler findet den Pfad einfach nicht, man muss im nur sagen wo er suchen soll.
Hier mal das Makefile:
Danke schon mal :D
Hallo Fabian.
Leider kann ich dein Link nicht sehen.
Ist was schief gelaufen?
Sonst kannst du mal hier schauen:
https://www.roboternetz.de/phpBB2/zeigebeitrag.php?t=57442&highlight=makefile
Ich versuchs einfach nochmal:
Also das schaut schon mal gut aus, du solltest noch schauen, ob der Pfad in deinem Kompiler fest vergeben ist oder auf zuletzt geöffnete Datei bezogen ist.
Wie man das im PN2 macht, ist im RP6 Manual beschrieben.
P.S.
hab es übrigens mit deine Makefile probiert - kompiliert ohne zu meckern.
P.P.S
und schau doch mal hier:
https://www.roboternetz.de/phpBB2/zeigebeitrag.php?t=57442&postdays=0&postorder=asc&highlight=makefile&start=0
rein, da hat einer sehr ähnliches Problemm.
So, hier mal für Marcel und wer noch so reinschauen mag.
Es ist schon einige Zeit her, dass ich da dran war. ich hoffe, es funzt noch.
Grüße
So, hier mal das für die M32.
Ist schon ne Weile her, daher weiß ich gar nicht mehr, obs funktioniert hat und wenn ja, wie gut...
Grüße
hi Fabqu,
hier fehlten auch damals wohl schon die links zu dem code:-( hast du den noch? Wäre schon interessant da reinzuschauen...
Hi!
Die habe ich irgendwann wieder gelöscht, leider hab ich nix mehr davon...
ist irgendwo im Chaos meiner Festplatte untergegangen.
Powered by vBulletin® Version 4.2.5 Copyright ©2024 Adduco Digital e.K. und vBulletin Solutions, Inc. Alle Rechte vorbehalten.