PDA

Archiv verlassen und diese Seite im Standarddesign anzeigen : Anleitung: neue Lib einbinden



fabqu
25.01.2012, 17:17
Hallo liebe RP6-ler,

habe ein neues Problem, für das ich noch keine (voll) zufriedenstellende Antwort gefunden habe.
Ich habe ein Slave-Programm für die M32, jedoch soll sie nun auch über I2C einen Kompass (CMPSxx) und einen US (SRF02) auslesen und in die eigenen I2C-Register schreiben.
Meine ganzen Libs sind in einem Ordner:
.../Firmware/Library und dann eben /RP6control und so weiter, wie mans eben kennt.
Mein Slave der M32 liegt auf:
.../Firmware/M128 - Master/M32 - Slave

Nun die Frage:
Was genau muss ich dafür tun, um die einzubinden???
Welcher Pfad muss ins Makefile...

Sorry, aber sowas habe ich noch niemals gemacht.

Danke euch!

Dirk
25.01.2012, 21:42
@fabqu:
Mit diesem Teil:

################################################## #############################
# Specify relative path to RP6 library files here.
# This is "../../RP6lib" or "../RP6lib" usually.
RP6_LIB_PATH=../../RP6lib
RP6_LIB_PATH_OTHERS= $(RP6_LIB_PATH)/RP6control $(RP6_LIB_PATH)/RP6common
################################################## #############################
... kannst du den Pfad zu deinen Libs RELATIV zum Verzeichnis deines .c-Programms eintragen.
Die wesentliche Zeile ist: RP6_LIB_PATH=
Wenn dein Programm (Prog.c) im Verzeichnis /Firmware/M128 - Master/M32 - Slave/ ist, dann brauchst du 2x ../ , um (in der Baumstruktur der Verzeichnisse rückwärts) ins Verzeichnis /Firmware zu kommen, danach must du noch /Library anhängen, um (in der Baumstruktur aufwärts) in dein Hauptverzeichnis der Libs zu kommen:
RP6_LIB_PATH=../../Library
Wenn du die Zeile RP6_LIB_PATH_OTHERS= so läßt, werden deine Libs auch in den Unterverzeichnissen /RP6control und /RP6common gefunden.

Die Libs werden dann wie üblich in den SRC += Zeilen eingetragen, z.B.:
SRC += $(RP6_LIB_PATH)/RP6control/MyOwnLib.c
... wenn die Lib in /Firmware/Library/RP6control ist.

fabqu
26.01.2012, 13:18
danke dir!
Wird ausprobiert, wenn die neuen Teile da sind ;)

fabqu
27.01.2012, 16:03
So, SRF02 ist angeschlossen, LIB sollte eingebunden sein.

Dennoch bekomme ich eine Fehlermeldung.
Hier mein Code aus der SRF02-Lib:


// wurde früher aus PCConnection aufgerunfen, jetzt aus Slave!!
uint8_t messageBuf[8];
void checkSRFStatus(uint8_t dataRequestID){
static uint8_t dist_tmp;
switch(dataRequestID)
{
case MEASURE_US_HIGH: // High data register
// get received data ...
I2CTWI_getReceivedData(messageBuf, 2);
dist_tmp = (messageBuf[0]);
// ... and request low data byte:
I2CTWI_transmitByte(SRF_ADR, 3);
I2CTWI_requestDataFromDevice(SRF_ADR, MEASURE_US_LOW, 1);

break;
case MEASURE_US_LOW: // low data byte:
I2CTWI_getReceivedData(messageBuf, 2);
gemesseneEntfernungSRF = messageBuf[0] + (dist_tmp << 8);

break;
default:break;
}
}

void task_SRF02(void)
{
if(messungOkay>=1){
static uint8_t measureInProgress = false;
if(!measureInProgress) // Start measurement ONCE only
{
if(TWI_operation == I2CTWI_NO_OPERATION) // If there is no request in progress...
{
I2CTWI_transmit2Bytes(SRF_ADR, 0, 81); // 81 means return distance in cm
measureInProgress = true;
setStopwatch7(0);
}
}
else if(getStopwatch7() > 70) // 120ms (measurement delay)
{
I2CTWI_transmitByte(SRF_ADR, 2); // range register high byte
I2CTWI_requestDataFromDevice(SRF_ADR, MEASURE_US_HIGH, 1); // receive it
measureInProgress = false; // allow to start new measurement
setStopwatch7(0);

// Die Messung mitteln
zaehler++;
SRF02_zwischenergebnis=SRF02_zwischenergebnis+geme sseneEntfernungSRF;
}

if(zaehler>=3){
SRF02_Dist = SRF02_zwischenergebnis/zaehler;
zaehler = 0;
SRF02_zwischenergebnis = 0;
}

}else{
SRF02_Dist=-1;

}
}


Und hier, wie ichs in meiner M32-Slave aufrufe:


uint16_t mic = getMicrophonePeak();
uint16_t SRF02_Dist = task_SRF02();
I2CTWI_readRegisters[I2C_BUTTON] = (getPressedKeyNumber());
I2CTWI_readRegisters[I2C_MICROPHONEPEAKLOW] = (mic & 0x00ff);
I2CTWI_readRegisters[I2C_MICROPHONEPEAKHIGH] = (mic & 0xff00) >> 8;
I2CTWI_readRegisters[I2C_ADC_2] = (uint16_t)readADC(ADC_2);
I2CTWI_readRegisters[I2C_ADC_3] = (uint16_t)readADC(ADC_3);
I2CTWI_readRegisters[I2C_ADC_4] = (uint16_t)readADC(ADC_4);
I2CTWI_readRegisters[I2C_ADC_5] = (uint16_t)readADC(ADC_5);
I2CTWI_readRegisters[I2C_ADC_6] = (uint16_t)readADC(ADC_6);
I2CTWI_readRegisters[I2C_ADC_7] = (uint16_t)readADC(ADC_7);
I2CTWI_readRegisters[I2C_RF02_DIST_LOW] = (SRF02_Dist & 0x00ff);
I2CTWI_readRegisters[I2C_RF02_DIST_HIGH] = (SRF02_Dist & 0xff00) >> 8 ;


In der Zeile mit uint16_t SRF02_Dist... kommt dieser Fehler:
RP6M32_I2CSlave.c: In function 'task_updateRegisters':
RP6M32_I2CSlave.c:92: error: void value not ignored as it ought to be
make: *** [RP6M32_I2CSlave.o] Error 1

Danke Euch!


EDIT: Ich habe zum EInen vergessen, "checkSRFStatus" in meiner Slave aufzurufen... Wie und wo??

Dirk
27.01.2012, 17:59
RP6M32_I2CSlave.c:92: error: void value not ignored as it ought to be
So wie du task_SRF02() definiert hast, hat die Funktion keinen Ausgabewert.

fabqu
27.01.2012, 18:28
Ok, richtig. Habe ein "return SRF02_Dist;" angehängt und die Fkt. "uint16_t task_SRF02(void)" genannt, statt "void task_...". Gleiches Problem... Kann es daran liegen, dass ich im task und in meiner update_Register-Funktion denselben Namen verwende (SRF02_Dist)?

fabqu
28.01.2012, 17:49
Hmm. Also im Header habe ich den task als "void task_SRF02(void)" benannt. Und "SRF02_Dist" als externe uint16_t. Das heißt doch, dass wenn ich den Task in meiner Hauptschleife immer wieder aufrufe, dass dann die Variable SRF02_Dist stets neu beschrieben wird und auch in meinen anderen Funktionen verfügbar ist, ich brauche also keinen Rückgabewert im Tast (kein return ...). Und ich muss den Wert auch nicht mehr extra zuweisen, den sollte ja die Variable SRF02_Dist schon haben. Ich kann also einfach schreiben:


I2CTWI_readRegisters[I2C_RF02_DIST_LOW] = (SRF02_Dist & 0x00ff);
I2CTWI_readRegisters[I2C_RF02_DIST_HIGH] = (SRF02_Dist & 0xff00) >> 8;

Jedoch klappt das dann nicht, ich bekomme wieder Fehler:


avr-gcc -mmcu=atmega32 -I. -gdwarf-2 -Os -funsigned-char -funsigned-bitfields -fpack-struct -fshort-enums -Wall -Wstrict-prototypes -Wa,-adhlns=RP6M32_I2CSlave.o -I../../Library -I../../Library/RP6control -I../../Library/RP6common -std=gnu99 -MD -MP -MF .dep/RP6M32_I2CSlave.elf.d RP6M32_I2CSlave.o ../../Library/RP6control/RP6ControlLib.o ../../Library/RP6common/RP6uart.o ../../Library/RP6common/RP6I2CslaveTWI.o ../../Library/RP6control/RP6ControlServoLib.o ../../Library/RP6common/RP6RemotrolCommon.o --output RP6M32_I2CSlave.elf -Wl,-Map=RP6M32_I2CSlave.map,--cref -lm
RP6M32_I2CSlave.o: In function `task_updateRegisters':
C:\Users\Fabian\Dropbox\BA_Robotik\Firmware\M128 - Master\M32 - Slave/RP6M32_I2CSlave.c:104: undefined reference to `SRF02_Dist'
C:\Users\Fabian\Dropbox\BA_Robotik\Firmware\M128 - Master\M32 - Slave/RP6M32_I2CSlave.c:104: undefined reference to `SRF02_Dist'
RP6M32_I2CSlave.o: In function `main':
C:\Users\Fabian\Dropbox\BA_Robotik\Firmware\M128 - Master\M32 - Slave/RP6M32_I2CSlave.c:275: undefined reference to `task_SRF02'
make: *** [RP6M32_I2CSlave.elf] Error 1

fabqu
30.01.2012, 17:55
Jetzt habe ich versucht, eine Funktion direkt im Slave aufzurufen, da es ja mit der fremden Lib nicht geht:


#define SRF02_Adr 0xE0 //Standardadresse des SRF02
void task_SRF02(void);
{
I2CTWI_transmit2Bytes(SRF02_Adr, 0, 81); //Gib Distanz in cm zurück
mSleep(100);
I2CTWI_transmitByte(SRF02_Adr, 2);
uint8_t highbyte = I2CTWI_readByte(2);
I2CTWI_transmitByte(SRF02_Adr, 3);
uint8_t lowbyte = I2CTWI_readByte(3);
uint16_t SRF02_Dist = (highbyte*256)+lowbyte;
writeString_P("\n distance:");
writeInteger(distance,DEC);
return SRF02_Dist;
}


Meine Abfrage dann im Register:


uint16_t mic = getMicrophonePeak();
uint16_t SRF02_Dist = task_SRF02();
I2CTWI_readRegisters[I2C_BUTTON] = (getPressedKeyNumber());
I2CTWI_readRegisters[I2C_MICROPHONEPEAKLOW] = (mic & 0x00ff);
I2CTWI_readRegisters[I2C_MICROPHONEPEAKHIGH] = (mic & 0xff00) >> 8;
I2CTWI_readRegisters[I2C_ADC_2] = (uint16_t)readADC(ADC_2);
I2CTWI_readRegisters[I2C_ADC_3] = (uint16_t)readADC(ADC_3);
I2CTWI_readRegisters[I2C_ADC_4] = (uint16_t)readADC(ADC_4);
I2CTWI_readRegisters[I2C_ADC_5] = (uint16_t)readADC(ADC_5);
I2CTWI_readRegisters[I2C_ADC_6] = (uint16_t)readADC(ADC_6);
I2CTWI_readRegisters[I2C_ADC_7] = (uint16_t)readADC(ADC_7);
I2CTWI_readRegisters[I2C_RF02_DIST_LOW] = (SRF02_Dist & 0x00ff);
I2CTWI_readRegisters[I2C_RF02_DIST_HIGH] = (SRF02_Dist & 0xff00) >> 8;


Jedoch wieder nur Fehler. Das #include "SRF02ControlLibrary.h" habe ich aber schon rausgenommen.

fabqu
03.02.2012, 17:16
Das mit der Funktion funktioniert jetzt, nur verwende ich die drei Master-Funktionen in meinem Slave-Programm:
- I2CTWI_transmit2Bytes
- I2CTWI_transmitByte
- I2CTWI_readByte
Die Master-Lib für diese Funktionen darf ich aber nicht einbinden, da nur Slave ODER Master geht.
Welche Funktionen kann ich denn statt dessen verwenden? "I2CTWI_writeRegisters" geht ja auch nicht.

Danke Euch!
Fabian

SlyD
03.02.2012, 17:36
Ein Slave überträgt nichts aktiv. Der Master ZIEHT im das sozusagen alles aus der Nase.
Also klar das die transmit Funktionen nicht verwendet werden können.

Alles in die passenden Register reinschreiben - fertig.
Ggf. noch das externe Interrupt Signal schalten um den Master zu informieren.

oh und das hier:
> uint16_t SRF02_Dist = task_SRF02();

und das hier:

> void task_SRF02(void);
> {

ist beides nicht korrekt.

MfG,
SlyD

fabqu
03.02.2012, 17:40
Danke dir, SlyD!
Die beiden Voids und so habe ich glaube ich schon richtig gestellt.
Nur in welche Register soll ichs dann schreiben?
Ich will ja, dass der Slave diese Aufgabe übernimmt... Die M32 hat bei mir außer Beepen, Servos und Taster nix zu tun.
Aber natürlich soll sie auch noch die eigenen Register abarbeiten, die von der M128 kommen.

SlyD
03.02.2012, 17:49
ah mmm - Ich hatte den Anfang vom Thread nicht gelesen:


> Ich habe ein Slave-Programm für die M32, jedoch soll sie nun auch über I2C (http://www.rn-wissen.de/index.php/I2C) einen
> Kompass (http://www.robotikhardware.de/download/cmps03kompass.pdf) (CMPSxx) und einen US (SRF02) auslesen und in die eigenen I2C (http://www.rn-wissen.de/index.php/I2C)-Register schreiben.


Wenn die M128 Master ist, dann MUSS diese ALLE I2C Slaves kontrollieren.
Du kannst nicht einfach einen der Slaves verwenden um andere Slaves auszulesen das kann also nicht richtig funktionieren.

--> Dazu wäre eine Mulit-Master I2C Implementierung notwendig.
Die standard Lib unterstützt das nicht.

Du könntest allenfalls eine Software I2C Master Implementierung auf der M32 probieren und zwei frei I/O Ports für ein separates I2C Bus Segment nutzen. Also keine direkte Verbindung zum Haupt Bus. Macht aber eigentlich keinen Sinn.

MfG,
SlyD

fabqu
03.02.2012, 17:52
Ach so.
Dann sollte ich die SRF02-Abfrage doch in die M128 schieben... Hatte ich schon mal, nur irgendwie lief das Programm dann ordentlich viel langsamer. Gibts da einen Grund für?
Und reicht die oben geschriebene Funktion "task_SRF02" eigentlich komplett für die SRF02-Abfrage aus? Ich habe dafür schon Libs gesehen, die 4 und mehr Funktionen hatten, Initialisierungsfunktionen etc.

SlyD
03.02.2012, 17:55
> nur irgendwie lief das Programm dann ordentlich viel langsamer.

Wenns blokierend programmiert wurde natürlich.
Der I2C Bus macht ja nur 100 bis 400kbit/s das dauert schon etwas.


Wenn Du beim SRF02 noch was initialisieren willst, dann mach das halt ;)
Brauchen tut man das vermutlich nicht (ich hab die Doku nicht auswendig im Kopf - musst Du selber lesen ;) )


EDIT:
Zum "dauert etwas":
Der SRF02 Ping braucht natürlich etwas um zurückzukommen - 65ms oder so.
In der Zeit kann man natürlich andere Dinge tun.

fabqu
03.02.2012, 18:03
Cool, vielen Dank!
Werds auf die M128 schreiben und mal sehen, wies geht ;)

fabqu
03.02.2012, 18:28
Hmm, habe jetzt die SRF02-Lib von FabianE. hergenommen, und mir wird immer ein Wert um -3500 übertragen. Egal, ob ich auf die Fensterscheibe 4 Meter weit weg ziele, oder meine Hand 20 cm weit weg vom SRF halte. :( Und auch wenn ich die Hand hin und her bewege, ist der resultierende Wert nicht wirklich linear.
Hat jemand Erfahrung mit der Lib von FabianE. auf der M128???