Archiv verlassen und diese Seite im Standarddesign anzeigen : RP6 I2C
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;
}
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
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
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
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
Ich werde das morgen 'mal bei mir probieren.
Gruß Dirk
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
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
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:
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
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;
}
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
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 ??
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
Ahhh ...
Danke für deine Erklärung ... ich glaub ich habs verstanden
Werd dann nochmal posten wenn ich das probiert habe.
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;
}
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
Vielen Dank für deine Hilfe ... ich glaub jetzt hab ich das verstanden ...
Powered by vBulletin® Version 4.2.5 Copyright ©2024 Adduco Digital e.K. und vBulletin Solutions, Inc. Alle Rechte vorbehalten.