PDA

Archiv verlassen und diese Seite im Standarddesign anzeigen : I²C Bus --- Frage zu meinem Programm



sloti
30.12.2007, 20:35
Guten Abend,

Ich habe nun mal angefangen mich mit dem I²C Bus auseinander zu setzen und stosse glich am anfang auf Probleme. Das Erweiterungs board M32 soll wenn ich klatsche oder irgendein anderes Geräusch wahrgenommen wird in das read regist 5 den Wert 1 schreiben und wenn kein geräusch da ist den wert null. Der Master soll wenn er den Wert 1 aus dem Register lesen kann die Funktion CACS ausführen (die soll Licht hinterherfahren und dabei nirgendwo gegenfahren). Wenn er den Wert 0 empfängt stehen bleiben. Er bleibt aber die ganze zeit stehen. Wenn ich klatsche führt der Slave aber das kleine Lauflicht aus, daher vermute ich das er auch die Daten schreibt. Ich denke das mein Problem beim Master Programm liegt und ich was beim Daten lesen falsch mache. Nur was?. Hier mal das Program für den Master:



#include "RP6RobotBaseLib.h"
#include "RP6I2CmasterTWI.h"
#define RECHTS adcLSR
#define LINKS adcLSL

void CACS (unsigned int warten)
{

if (getBumperLeft())
{
move(60,BWD,100,1);
rotate(60,RIGHT,45,1);
moveAtSpeed(80,80);
}
else if (getBumperRight())
{
move(60,BWD,100,1);
rotate(60,LEFT,45,1);
moveAtSpeed(80,80);
}
else if(getBumperLeft()&&getBumperRight())
{
move(60,BWD,100,1);
rotate(60,LEFT,90,1);
moveAtSpeed(80,80);
}

else
{
if (obstacle_left)
{
changeDirection(FWD);
moveAtSpeed(80,30);
setLEDs(0b010000);
}

else if (obstacle_right)
{
changeDirection(FWD);
moveAtSpeed(30,80);
setLEDs(0b000010);

}




else if(obstacle_right&&obstacle_left)
{
changeDirection(BWD);
moveAtSpeed(60,60);
setLEDs(0b110110);
}

else
{
changeDirection(FWD);
if (LINKS>RECHTS)
{
moveAtSpeed(50,80);
setLEDs(0b001000);
}
else if (RECHTS>LINKS)
{
moveAtSpeed(80,50);
setLEDs(0b000001);
}

else
{
moveAtSpeed(100,100);
setLEDs(0b100010);
}

}
mSleep(warten);
}
}






int main(void)
{
unsigned int data;
initRobotBase();
I2CTWI_initMaster(100);
powerON();
setACSPwrMed();
moveAtSpeed(100,100);
setLEDs(0b001001);



while(1)
{


I2CTWI_transmitByte(10,5);
data=I2CTWI_readByte(5);

if (data==1)
{
CACS(40);
}

else
{
stop();
}

task_ACS();
task_motionControl();
task_ADC();
}


return 0;
}


und das Programm für den Slave:




#include "RP6I2CslaveTWI.h"
#include "RP6ControlLib.h"

void start_sound (void)
{
sound(200,10,10);
sound(175,10,10);
sound(215,10,10);
sound(135,50,40);
sound(225,20,25);
sound(205,50,50);
sound(135,120,120);
sound(95,50,10);
sound(145,40,10);
sound(200,30,15);
sound(175,30,20);
sound(135,50,25);
}

void lauf_licht (void)
{
setLEDs(0b0001);
mSleep(50);
setLEDs(0b0010);
mSleep(50);
setLEDs(0b0100);
mSleep(50);
setLEDs(0b1000);
mSleep(50);
}



uint16_t main(void)
{
uint16_t oldton=0;
initRP6Control();
I2CTWI_initSlave(10);
start_sound();

dischargePeakDetector();



while(1)
{
uint16_t tmp = getMicrophonePeak();


if (tmp>5)

{
if(tmp > oldton)
{
lauf_licht();

tmp=oldton;
if (!I2CTWI_readBusy)
{
I2CTWI_readRegisters[5]=1;
}

}


}

else
{
setLEDs(0b0000);
I2CTWI_readRegisters[5]=0;
}



}
return 0;
}





Danke schonmal im vorraus
mfg
Erik

sloti
03.01.2008, 22:30
Hmm es scheint mir als hätte noch niemand Erfahrungen mit dem I²C Bus gemacht. Oder ist blos die Frage unverständlich? Naja dann werd ich die Erfahrung wohl selbst machen müssen.

mfg
Erik

SlyD
03.01.2008, 22:48
Hallo Erik,

Du musst auf dem Slave die Abfrage "if (!I2CTWI_readBusy) " eher als Schleife realisieren, die wartet bis keine Lesezugriffe mehr erfolgen. Sonst kannst Du hier nicht sicher sein, das der Wert überhaupt jemals geschrieben wird.

Also in der Art:
- Frage ab ob das Mikrofon etwas detektiert hat.
- WENN es etwas detektiert hat, setze ein Flag und warte solange bis schreibzugriff möglich ist.

Das gilt auch für den umgekehrten Fall, also wenn das Register auf 0 gesetzt werden soll.

Und vor allen Dingen wird bei Deinem Slave Code das Register fast sofort wieder auf 0 gesetzt - denn der Peak wird nur einmal kurz detektiert.
Du musst also zusätzlich den Code so auslegen, dass der Slave den Wert zurücksetzt sobald der Master das entsprechende Register gelesen hat.

Schau Dir hierzu auch mal das Beispielprogramm "RP6Base_I2CSlave" an - ist zwar für den Controller auf dem Mainboard, ist vom Prinzip her aber ähnlich. Da wird genau das gemacht (Interrupt flag zurücksetzen usw.)

MfG,
SlyD

sloti
03.01.2008, 23:15
Ok danke erstmal für die Antwort. Ich werd es probieren sobald ich zeit hab.

mfg
Erik

KayH
04.01.2008, 12:41
Mir scheint auch die generelle Programmlogik nicht zielfuehrend zu sein ...
Ich weiss nicht, ob SlyD das auch meinte.

Das Klatschen ist ein kurzer Augenblick. Die meiste Zeit ist Stille. D.h. zunaechst steht der Roby. Beim Klatschen "faehrt" er los (zumindest koennte dieser Zustand fuer einen minimalen Zeitraum eingenommen werden). Gleich darauf ist aber wieder Stille und der RP6 soll sofort stehen bleiben...

Vielleicht solltest Du nach dem Programmstart (suche das Licht) eine gewisse Zeit verstreichen lassen, in der der RP6 "nur" diesem Programm folgt. Das wird angehalten/unterbrochen bei einem zweiten Klatschen oder nach einem Timeout. Nur so als Idee ...

HTH
Kay

sloti
04.01.2008, 18:19
Hmm ich verstehe, ich werde das dann wohl in einer Schleife ausführen.

mfg
Erik