PDA

Archiv verlassen und diese Seite im Standarddesign anzeigen : RP6 I2C



shedepe
09.01.2010, 21:47
Ich habe mir einen kleinen Entfernungssensor gebaut, der soweit auch schon gut funktioniert. Jetzt habe ich den Ausgang des Sensor an die RP6 Base angeschlossen. Wenn ich die Werte über den UART an den PC sende sind diese vollkommen korrekt. Wenn ich jedoch versuche via I2C den vom ADC0 gemessenen Wert am Display von dem M32 Erweiterungsboard anzuzeigen, bekomme ich nur Schrott angezeigt.
Anbei mein Code der Basis und der Erweiterung. Ich kann zwar keinen Fehler darin entdecken aber vllt findet jemand von euch einen.




#include "RP6RobotBaseLib.h"
#include "RP6I2CmasterTWI.h"


void I2C_transmissionError(uint8_t errorState)
{
writeString_P("\nI2C ERROR - TWI STATE: 0x");
writeInteger(errorState, HEX);
writeChar('\n');
}


int main(void)
{
initRobotBase();
powerON();
writeString_P("Hallo"); //UART Test
writeChar('\n');
I2CTWI_initMaster(200); //I2C Master initialisieren
I2CTWI_setTransmissionErrorHandler(I2C_transmissio nError);


while(1)
{
uint16_t adc0 = readADC(ADC_ADC0); //ADC auslesen
writeInteger(adc0, DEC); // Wert via UART senden
writeChar('\n');
while(I2CTWI_isBusy()) // warten bis I2C frei ist
{

}
if(!I2CTWI_isBusy())
{

I2CTWI_transmit2Bytes(10 ,adc0, (adc0 >> 8 )); //ADC Wert in Lowbyte und Highbyte teilen und via I2C senden
writeString_P("I2C hat was gesendet"); // Kontrolle dass etwas gesendet wurde
writeChar('\n');
}


}
return 0;

}






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


int main(void)
{
initRP6Control();

initLCD(); //Display initialisieren

setLEDs(0b1010);

I2CTWI_initSlave(10); // Slave mit der Adresse 10 initialisieren
writeString_P("I2C Init"); //UART testen
writeChar('\n');
showScreenLCD("Hallo","ADC:"); // Display testen
uint16_t adcwert;

uint8_t highbyte = 0;
uint8_t lowbyte = 0;
while(true)
{

if(I2CTWI_writeRegisters[0] && !I2CTWI_writeBusy)
{
lowbyte = I2CTWI_writeRegisters[0]; //lowbyte auslesen

highbyte= I2CTWI_writeRegisters[1]; //highbyte auslesen

}

adcwert = ((highbyte << 8 ) | lowbyte); // wieder zusammensetzen
setCursorPosLCD(1,4);
writeIntegerLCD(adcwert, DEC); // auf dem display ausgeben
setCursorPosLCD(1,4);
writeInteger(adcwert , DEC);
writeChar('\n');
}


return 0;
}

Dirk
09.01.2010, 22:50
Hallo shedepe,

beim Master ist wohl alles ok.

Beim Slave:
Du solltest erst den Wert anzeigen, wenn er komplett übertragen wurde. Da du immer wieder einen 16-Bit Wert sendest, erkennt der Slave evtl. nicht, welche Bytes zusammen gehören.
Abhilfe:
Übertrag einfach 3 Bytes. Wenn das 1. Byte einen bestimmten Wert != 0 hat, dann sind die weiteren beiden Bytes der Messwert und werden nur ausgegeben, wenn das 1. Byte stimmt. Ist das 1. Byte 0, wird ja auch schon bei deinem jetzigen Programm nichts gelesen, allerdings leider in jeder Schleife wieder etwas (Müll) ausgegeben.

Gruß Dirk

shedepe
09.01.2010, 23:05
ich hab das ganze jetzt so abgeändert:
im Master wird jetzt zuerst ein Kontrollbyte gesendet mit:


I2CTWI_transmit3Bytes(10 , 1 ,adc0, (adc0 >> 8 )); //Kontrollbyte senden ADC Wert in Lowbyte und Highbyte teilen und via I2C senden


und im slave mit:

if(I2CTWI_writeRegisters[0] && !I2CTWI_writeBusy)
{
controllbyte = I2CTWI_writeRegisters[0]; // Kontrollbyte

lowbyte = I2CTWI_writeRegisters[1]; //lowbyte auslesen

highbyte= I2CTWI_writeRegisters[2]; //highbyte auslesen

}
if(controllbyte != 0)
{
adcwert = ((highbyte << 8 ) | lowbyte); // wieder zusammensetzen
setCursorPosLCD(1,4);
writeIntegerLCD(adcwert, DEC); // auf dem display ausgeben
setCursorPosLCD(1,4);
writeInteger(adcwert , DEC);
writeChar('\n');
controllbyte = 0;
}

Mein Problem: es funktioniert immer noch nicht

Dirk
09.01.2010, 23:33
Mein Problem: es funktioniert immer noch nicht
Was genau?
Also heißt es: Bebuggen!
Ich würde versuchen, feste Bytes zu senden und herauszufinden, wo's hakt.

Vorher füge beim Master nach jedem Senden noch eine Pause von z.B. 500ms ein. Hilft das?

Gruß Dirk

shedepe
10.01.2010, 20:09
habe heut versucht das ganze mit festen bytes zu machen:
im Master mit
I2CTWI_transmitByte(10,5);

es macht keinerlei unterschied ob ich eine Pause einfüge, im Slave kommt immer noch nichts an. Habe sogar mal den Bus mit dem Oszilloskop überwacht. Es wird definitiv was gesendet. Auch die Beispiel Programme von der CD funktionieren.

Um noch mal von der theoretischen Seite sicher zu gehen. Wenn ich eine Byte versende wird dies im Slave hier hin geschrieben:
I2CTWI_writeRegisters[0] oder?

langsam gehen mir die ideen aus, woran es liegen könnte

Dirk
10.01.2010, 21:05
Ich werde das morgen 'mal bei mir probieren.

Gruß Dirk

shedepe
11.01.2010, 16:52
so habe das ganze jetzt so gelöst, dass ich das Erweiterungsboard als Master verwendet habe und im Slave den ADC Wert in die Readregister schreibe.
Würde mich dennoch interessieren warum das ganze nicht andersherum funktionert. Also dass ich mit der Basis als Master den Wert an die Erweiterungsende

Dirk
13.01.2010, 20:07
Hallo shedepe,

sorry, hatte einfach noch keine Zeit.

Hier jetzt eine funktionierende Variante:

RP6Base (Master):

/*
* ************************************************** **************************
* RP6 ROBOT SYSTEM - ROBOT BASE EXAMPLES
* ************************************************** **************************
* Example: I2C Master - I2C Send Test
* Author(s): Dirk
* ************************************************** **************************
* Description:
*
* This Example sends a 16-bit value via I2C as master.
*
*
* ################################################## ##########################
* The Robot does NOT move in this example! You can simply put it on a table
* next to your PC and you should connect it to the PC via the USB Interface!
* ################################################## ##########################
* ************************************************** **************************
*/

/************************************************** ***************************/
// Includes:

#include "RP6RobotBaseLib.h" // The RP6 Robot Base Library.
// Always needs to be included!
#include "RP6I2CmasterTWI.h" // Include the I2C-Bus Master Library

/************************************************** ***************************/
// Defines:

// The Slave Address on the I2C Bus can be specified here:
#define RP6CONTROL_I2C_SLAVE_ADR 10

#define CMD_SHOW_DATA 99 // Command to display the data

/************************************************** ***************************/
// I2C Event handlers:

/**
* 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 IS: 0x");
writeInteger(errorState, HEX);
writeChar('\n');
}

/************************************************** ***************************/
// Variables:

uint16_t adc0;
uint8_t buffer[4];

/************************************************** ***************************/
// Functions:


/************************************************** ***************************/
// Main - The program starts here:

int main(void)
{
initRobotBase();

I2CTWI_initMaster(100); // Initialize the TWI Module for Master operation
// with 100kHz SCL Frequency

// Register the event handlers:
I2CTWI_setTransmissionErrorHandler(I2C_transmissio nError);

setLEDs(0b111111);
mSleep(500);
setLEDs(0b000000);

powerON();

writeString_P("Hallo"); // UART Test
writeChar('\n');

startStopwatch1();

while(true)
{
if (getStopwatch1() > 250) { // Jede 1/4 Sekunde:
// adc0 = readADC(ADC_ADC0); // ADC auslesen
adc0 += 10; // TEST: ZÄHLER!!!
writeString_P("Zu sendender Wert: ");
writeInteger(adc0, DEC); // Wert via UART senden
writeChar('\n');
buffer[0] = 0;
buffer[1] = CMD_SHOW_DATA;
buffer[2] = adc0;
buffer[3] = (adc0 >> 8);
if (!I2CTWI_isBusy()) {
I2CTWI_transmitBytes(RP6CONTROL_I2C_SLAVE_ADR, buffer, 4);
writeString_P("I2C hat gesendet: "); // Kontrolle, dass etwas gesendet wurde
writeInteger(adc0, DEC);
writeChar('\n');
writeChar('\n');
}
setStopwatch1(0);
}
}
return 0;
}

/************************************************** ****************************
* Additional info
* ************************************************** **************************
* Changelog:
* - v. 1.0 (initial release) 13.01.2010 by Dirk
*
* ************************************************** **************************
*/

/************************************************** ***************************/

RP6Control (Slave):

/*
* ************************************************** **************************
* RP6 ROBOT SYSTEM - RP6 CONTROL M32 EXAMPLES
* ************************************************** **************************
* Example: I2C Slave - I2C Receive Test
* Author(s): Dirk
* ************************************************** **************************
* Description:
*
* This Example receives a 16-bit value via I2C as slave.
*
*
* ################################################## ##########################
* The Robot does NOT move in this example! You can simply put it on a table
* next to your PC and you should connect it to the PC via the USB Interface!
* ################################################## ##########################
* ************************************************** **************************
*/

/************************************************** ***************************/
// Includes:

#include "RP6ControlLib.h" // The RP6 Control Library.
// Always needs to be included!
#include "RP6I2CslaveTWI.h" // Include the I2C-Bus Slave Library

/************************************************** ***************************/
// Defines:

// The Slave Address on the I2C Bus can be specified here:
#define RP6CONTROL_I2C_SLAVE_ADR 10

#define CMD_SHOW_DATA 99 // Command to display the data

/************************************************** ***************************/
// Variables:

uint16_t adcwert;
uint8_t controlbyte;
uint8_t highbyte = 0;
uint8_t lowbyte = 0;

/************************************************** ***************************/
// Functions:


/************************************************** ***************************/
// Main function - The program starts here:

int main(void)
{
initRP6Control(); // Always call this first! The Processor will not
// work correctly otherwise.

initLCD(); // Initialize the LC-Display (LCD)
// Always call this before using the LCD!
clearLCD(); // Clear the whole LCD Screen

setLEDs(0b111111);
mSleep(500);
setLEDs(0b000000);

I2CTWI_initSlave(RP6CONTROL_I2C_SLAVE_ADR); // Slave mit der Adresse 10 initialisieren

showScreenLCD("I2C-Empfang", "ADC:"); // LC-Display vorbereiten

while(true)
{
if (I2CTWI_writeRegisters[0] && !I2CTWI_writeBusy) {
controlbyte = I2CTWI_writeRegisters[0]; // Kontrollbyte lesen
I2CTWI_writeRegisters[0] = 0; // und zurücksetzen (!!!)
lowbyte = I2CTWI_writeRegisters[1]; // lowbyte auslesen
highbyte = I2CTWI_writeRegisters[2]; // highbyte auslesen

if (controlbyte == CMD_SHOW_DATA) {
adcwert = ((highbyte << 8) | lowbyte); // wieder zusammensetzen
setCursorPosLCD(1, 5);
writeIntegerLCD(adcwert, DEC);
controlbyte = 0;
}
}
}
return 0;
}

/************************************************** ****************************
* Additional info
* ************************************************** **************************
* Changelog:
* - v. 1.0 (initial release) 13.01.2010 by Dirk
*
* ************************************************** **************************
*/

/************************************************** ***************************/

Gruß Dirk

Xandi11
15.02.2010, 11:11
Ich habe zurzeit ein großes Problem mit dem I²C Bus:

Ich verwende die M32 als Master und die Base als Slave.
Nun habe ich auf der M32 den folgenden Befehl im Programm stehen:

I2CTWI_transmitByte(10,1);

Das eigentliche Problem besteht nun darin, dass ich die 1, die ich übertragen will auf der Base nicht auslesen kann.

Mein eigentliches Ziel wäre, dass ich dann schreiben könnte if( ... ) und er dabei die übertragen Zahl abfragt.

Ich hoffe ihr versteht was ich meine und könnt mir helfen

:mrgreen:

Dirk
15.02.2010, 17:49
Ich hoffe ihr versteht was ich meine und könnt mir helfen
Ohne deinen Code für Master und Slave?

Wie soll das gehen?

Gruß Dirk

Xandi11
15.02.2010, 18:07
Im Rest liegt ja nicht das Problem ...

BASE:


#include"RP6RobotBaseLib.h"
#include "RP6I2CslaveTWI.h"

int main(void)

{

initRobotBase();

powerON();

setACSPwrOff();

uint8_t i;

I2CTWI_initSlave(10);

while (true)
{

i=I2CTWI_readBytes(10);

switch (i)
{
case 1: task_motionControl();
move(30,FWD,DIST_MM(50),false);
break;
case 2: task_motionControl();
move(30,BWD,DIST_MM(50),false);
break;
case 3: task_motionControl();
rotate(30,LEFT,20,false);
break;
case 4: task_motionControl();
rotate(30,RIGHT,20,false);
break;
}



}



while (true)
{
writeString_P("\n In Endlosschleife\n");
}
return 0;



}




M32


#include "RP6ControlLib.h"
#include "RP6I2CmasterTWI.h"

int main(void)
{
initRP6Control();
initLCD();

I2CTWI_initMaster(50);

int key;

while(true)
{

key=0;

do
{

showScreenLCD("Bitte Taster","druecken");
key=getPressedKeyNumber();

}
while (key==0);

switch(key)
{
case 1: //T1 - vorwärts
showScreenLCD("Daten werden","uebertragen");
I2CTWI_transmitByte(10,1);
showScreenLCD("...erfolgreich","");
break;
case 2: //T2 - rückwärts
showScreenLCD("Daten werden","uebertragen");
I2CTWI_transmitByte(10,2);
showScreenLCD("...erfolgreich","");
break;
case 3: //T3 - 20° rechts
showScreenLCD("Daten werden","uebertragen");
I2CTWI_transmitByte(10,3);
showScreenLCD("...erfolgreich","");
break;
case 4: //T4 - 20° links
showScreenLCD("Daten werden","uebertragen");
I2CTWI_transmitByte(10,4);
showScreenLCD("...erfolgreich","");
break;
}

showScreenLCD("","Bitte warten");
mSleep(200);

}


while(true)
{
showScreenLCD("Endlosschleife", "");
}
return 0;
}

Dirk
15.02.2010, 18:44
Hallo Xandi11,

das hier im Slave: i=I2CTWI_readBytes(10);
... kann nicht funktionieren, weil:
1. Der Befehl unvollständig ist (zu wenig Parameter müßte der Compiler sagen) und ...
2. der Befehl nur für Master funktioniert.

Sieh dir für den Slave mal das Beispielprogramm in der Anleitung S. 106 an.

Gruß Dirk

Xandi11
15.02.2010, 18:59
Danke für deine schnelle Antwort Dirk.

Laut der Beschreibung müsste ich ja
i=I2CTWI_writeRegisters[0]
schreiben.

Stimmt das so oder ist das falsch ??

Dirk
15.02.2010, 19:12
Nein, das stimmt schon so.

Um zu erkennen, ob überhaupt ein Byte bzw. Befehl gesendet wurde, müßtest du die 0 vermeiden (also 0 nicht senden!) und im Slave auch so testen wie in dem Beispiel:

if(I2CTWI_writeRegisters[0] && !I2CTWI_writeBusy)
{
// Register speichern:
i = I2CTWI_writeRegisters[0];
I2CTWI_writeRegisters[0] = 0;
}
Gruß Dirk

Xandi11
15.02.2010, 19:37
Ahhh ...

Danke für deine Erklärung ... ich glaub ich habs verstanden

Werd dann nochmal posten wenn ich das probiert habe.

Xandi11
16.02.2010, 09:36
Ich hab das Ganze nun probiert, hat aber leider nicht funktioniert.

Mein Code sieht jetzt so aus:

M32 - Master:


#include "RP6ControlLib.h"
#include "RP6I2CmasterTWI.h"

int main(void)
{
initRP6Control();
initLCD();

I2CTWI_initMaster(50);

int key;

while(true)
{

key=0;

showScreenLCD("Bitte Taster","druecken");

do
{

key=getPressedKeyNumber();
I2CTWI_transmitByte(10,0);

}
while (key==0);

switch(key)
{
case 1: //T1 - vorwärts
showScreenLCD("Daten werden","uebertragen");
I2CTWI_transmitByte(10,1);
showScreenLCD("...erfolgreich","");
break;
case 2: //T2 - rückwärts
showScreenLCD("Daten werden","uebertragen");
I2CTWI_transmitByte(10,2);
showScreenLCD("...erfolgreich","");
break;
case 3: //T3 - 20° rechts
showScreenLCD("Daten werden","uebertragen");
I2CTWI_transmitByte(10,3);
showScreenLCD("...erfolgreich","");
break;
case 4: //T4 - 20° links
showScreenLCD("Daten werden","uebertragen");
I2CTWI_transmitByte(10,4);
showScreenLCD("...erfolgreich","");
break;
default: I2CTWI_transmitByte(10,0);
break;
}

showScreenLCD("","Bitte warten");
mSleep(200);

key=0;

}


while(true)
{
showScreenLCD("Endlosschleife", "");
}
return 0;
}

Base - Slave:


#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: task_motionControl();
move(30,FWD,DIST_MM(50),false);
break;
case 2: task_motionControl();
move(30,BWD,DIST_MM(50),false);
break;
case 3: task_motionControl();
rotate(30,LEFT,20,false);
break;
case 4: task_motionControl();
rotate(30,RIGHT,20,false);
break;
default: setLEDs(0b111111);
mSleep(200);
setLEDs(0b000000);
break;
}



}



while (true)
{
writeString_P("\n In Endlosschleife\n");
}
return 0;



}

Dirk
16.02.2010, 11:25
Hallo Xandi11,

probier's mal so:

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

Base - Slave:
#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);
}
}
}
}
Viel Erfolg!

Gruß Dirk

Xandi11
16.02.2010, 23:11
Vielen Dank für deine Hilfe ... ich glaub jetzt hab ich das verstanden ...