PDA

Archiv verlassen und diese Seite im Standarddesign anzeigen : Probleme mit I2C Verbindung



oderlachs
10.10.2013, 21:30
Hallo Freunde , vieleicht bin ich wieder mal ein bischen blind, oder wieder das oft zetierte Brett vorm K... ;) Ich habe Versucht eine Master-Slave-I2C Verbindung zwischen 2 Arduino(Uno) herzustellen. Am Master wird seriel die Tastatureingabe abgefragt und soll zum Slave übertragen per I2C übertragen werde. Dort soll der empfangene Byte Wert( Buchstaben A...Z Ziffern 0...9) auf einem LCD als Kontrolle angezeigt werden..
Wird aber nix angezeigt vom gesendetem Wert.... :o :confused:
Hier mal der Source:

/* ================================================== ======================== */
/* */
/* I2C_Master_Tx.c */
/* (c) 2013 Gerhard Hinze */
/* */
/* Description */
/* */
/* ================================================== ======================== */
/*
The circuit:
* SDA pin to analog pin 4
* SCL pin to analog pin 5
*/

#include <Wire.h>
#define I2C_Slave_Adress 127




void setup()
{
Serial.begin(9600);
Wire.begin(); //als Master am Bus anmelden
}

void loop()
{
if (Serial.available())
{
Wire.beginTransmission(I2C_Slave_Adress);
byte tx = Serial.read(); // Eingabe lesen
Wire.send(tx); // Eingabe über I2C senden
Wire.endTransmission();

Serial.write(tx); // Eingabe als Echo return zum Terminal
delay(100);


}


}


/* ================================================== ======================== */
/* */
/* I2C_Slave_LCD.c */
/* (c) 2013 Gerhard Hinze */
/* */
/* Description */
/* */
/* ================================================== ======================== */
/*
* SDA pin to analog pin 4
* SCL pin to analog pin 5
*/

#include <LiquidCrystal.h>
#include <Wire.h>
#define I2C_Slave_Adress 127
LiquidCrystal lcd(8, 13, 9, 4, 5, 6, 7);



void setup()
{
lcd.clear();
lcd.begin(16, 2);
lcd.setCursor(0,0);
lcd.print("I2C-Verbindung");
Wire.begin(I2C_Slave_Adress); //als Slave am Bus anmelden
}

void loop()
{
if (Wire.available())
{
byte x = Wire.receive();
lcd.setCursor(0, 1);
lcd.print("Empfange : ");
lcd.setCursor(11,1);
lcd.print (char(x));
delay(100);
}}




Ich danke schon mal dem Edlen Helfer , der mich ein wenig auf die Sprünge, besser zu einer Zeichenanzeige am LCD bringt. :)

oberallgeier
10.10.2013, 22:58
... Master-Slave-I2C Verbindung zwischen 2 Arduino ... #define I2C_Slave_Adress 127 ...Arduino-Slang kann ich nicht, sorry. Aber ich weiß definitiv, dass eine I²C-Adresse IMMER gerade ist. Im Prinzip. Das LSBit ist das R/W-Bit, es ist Null fürs Schreiben, und Eins fürs Lesen. Lies das doch ruhig mal im R.N.Wissen nach. Deswegen wird Dein Slave wohl auf Adresse 126 liegen, nur zum Lesen musst Du das Read-Bit setzten, dann liest der Master von 127 ;-). Du verwendest im Code aber offenbar nur eine einzige Adresse fürs schreiben UND lesen.

Darüber hinaus kann ich Richtigkeit oder Fehler in Deinem Code leider garnicht beurteilen.

oderlachs
11.10.2013, 08:54
Danke für die Ausführungen !
Es ist mein erstes I2C Proj. dieser Art. Beim Arduino bekommt der Master keine Nummer/Adresse zugeornet , darum steht da auch "#define I2C_Slave_Adress 127" , dem Slave kann als Adresse 0...127 zugeordnet werden.
So die Beschreibung in den Arduino Büchern. Ich werde aber mal danach googlen, da mir die Listings in den Büchern oft zu fehlerbehaftet sind...

Der Grund dieses Projektes ist, einen I2C -LCD-Datenmonitor zu bauen, um andere I"C Anwendungen zu testen. Da ich nun ..zig Arduino zu liegen habe und auch ein passendes LCD Shield , wolte ich das nutzbringend dafür verwenden...

Gruss und Dank

Gerhard

PS: werde dieses Tutorial (http://arduino.cc/en/Tutorial/MasterWriter)als Grundlage meiner weiteren Arbeit nehmen

BMS
11.10.2013, 09:56
Hallo,
ich sehe bei der I2C-Verbindung keine Pullup-Widerstände. Sind die internen überhaupt aktiviert?
I2C verwendet ja Open-Collector-Ausgänge und braucht deswegen Pullup-Widerstände.
Um auf Nummer sicher zu gehen würde ich empfehlen, zusätzliche Pullup-Widerstände einzubauen.
Zur Dimensionierung: Es dürfen bis zu 3mA fließen, wenn ein Ausgang auf Low gezogen wird, d.h. bis 5V/3mA=1,67kOhm darfst du gehen (oder hochohmiger).
Je niederohmiger die Widerstände, desto schneller werden die parasitären Kabelkapazitäten umgeladen aber desto höher die Stromaufnahme bei Low-Pegel.
Ich habe meistens 3,3kOhm verwendet, das ist ein Kompromiss zwischen Stromaufnahme und max. Übertragungsgeschwindigkeit.
Grüße,
Bernhard

oberallgeier
11.10.2013, 10:09
... einen I2C -LCD-Datenmonitor zu bauen, um andere I"C Anwendungen zu testen ...Als Monitor für den I²C-Bus ist natürlich ein Logikanalysator die beste Wahl

http://www.mikrocontroller.net/attachment/36104/Screenshot.png

da bekommt man die Schritte gleich im Klartext und kann auch triggern. Weil ich das viele Geld dafür nicht ausgeben will/wollte, hatte ich mir einen Sniffer gebaut (Dank an Peter Dannegger) klick hier. (http://www.mikrocontroller.net/topic/102228#894505) So kann ich prächtig die Ereignisse mitschneiden (klick (https://www.roboternetz.de/community/threads/55744-I²C-Master-m328-kann-Slave-m328-nicht-lesen?p=533026&viewfull=1#post533026)). Als weitere Hilfe hatte ich mir bei ELV einen USB-I²C-Adapter gekauft (http://www.elv.de/usb-i2c-interface-komplettbausatz-inkl-gehaeuse-bearbeitet-und-bedruckt-usb-kabel-3-anschlusskabel.html) (Fertiggerät), der kann nach I²C lesen und schreiben. SEHR zweckmässig.

Achim S.
11.10.2013, 10:43
Hallo Oberallgeier, habe mir den Beitrag über den Sniffer gezogen. Eigentlich kaum Aufwand und schnell zu machen. Was für ein Programm ist im Text vorher dargestellt? Sieht recht gut aus.achim

oberallgeier
11.10.2013, 14:08
... Was für ein Programm ist im Text vorher dargestellt? ...Hallo Achim, sorry, diese Frage versteh ich nicht :.-./

Achim S.
11.10.2013, 14:17
Du hast oben ein Bild reingestellt von Intronix mit einem schicken Bild und so. Das mein ich. achim

oberallgeier
11.10.2013, 14:23
Ist einfach ein Bildschirmdump von/mit dem Intronix - beim Mitschnitt einer I²-C-Kommunikation (mehr zum Intronix). (http://www.pctestinstruments.com/deutsch/index.htm)

oderlachs
11.10.2013, 17:40
Hallo,
ich sehe bei der I2C-Verbindung keine Pullup-Widerstände. Sind die internen überhaupt aktiviert?
I2C verwendet ja Open-Collector-Ausgänge und braucht deswegen Pullup-Widerstände.
Um auf Nummer sicher zu gehen würde ich empfehlen, zusätzliche Pullup-Widerstände einzubauen.
Zur Dimensionierung: Es dürfen bis zu 3mA fließen, wenn ein Ausgang auf Low gezogen wird, d.h. bis 5V/3mA=1,67kOhm darfst du gehen (oder hochohmiger).
Je niederohmiger die Widerstände, desto schneller werden die parasitären Kabelkapazitäten umgeladen aber desto höher die Stromaufnahme bei Low-Pegel.
Ich habe meistens 3,3kOhm verwendet, das ist ein Kompromiss zwischen Stromaufnahme und max. Übertragungsgeschwindigkeit.
Grüße,
Bernhard

Wie schon gesagt, ist das mein allererstes I2C Projekt dieser Art und ich denke das die Wire Bibliothek vom Arduino, das mit den PullupWiderständen macht. Ich habe da noch nicht im Quellcode weiter geschnüffelt.. ;)
Mir genügt es, das das Projekt mir einen übertragenen Wert auf dem LCD ausgibt. Das ist auch im Preis günstiger, als als der Intronix LogiPortAnalyzer... denn die Preislage ist für mein Hobbygebrauch zu happig.

Ich hatte heut in der Natur-Therme ein wenig Lesezeit für ein Fachbuch vom Arduino und denke, ich habe den Fehler , jedenfalls einen schon gefunden, wird später praktisch getestet und dann hier gepostet, das Ergebnis.


Gruss und Danke
Gerhard

oberallgeier
11.10.2013, 18:28
... mein allererstes I2C Projekt ... ich denke ... das mit den PullupWiderständen macht ...Glaub ich ganz bestimmt nicht. Ganz einfach: die internen Pullups sind in den Datenblättern mit (meist) 30 kΩ bis 60 kΩ spezifiziert, die I²C-Pullups sind viel niedriger, dazu gibts in den Atmel-Datenblättern auch Berechnungsgrundlagen. Ansonsten Richtwerte im R N Wissen im einschlägigen Artikel oder in der Originabibel von Philips.

oderlachs
11.10.2013, 18:35
Wie dem auch sei, sowie Zeit dafür ist probiere ich mit 2x 4k7, das ist so ein Wert vom meinem Handvorrat für solche Sachen....daran soll es nicht liegen ;)

oberallgeier
11.10.2013, 19:05
Wie dem auch sei, sowie Zeit dafür ist probiere ich mit 2x 4k7 ...Das ist ein guter, allgemein üblicher Wert. Die teilweise verbauten 10k (in der einen oder andern Fertig-Kauf-Platine) hatte ich alle als zu hoch beurteilen müssen und ersetzt. In einer Platine (glaub ich) habe ich 3k3 eingebaut. Und mein Bus mit vorerst drei, max vier Platinen tickert an einem 100kHz-Bus mit rund 2,2 m Länge recht sicher.

oderlachs
12.10.2013, 10:10
Also ganz kurz, mein Fehler lag darin, das ich den "onReceive-Handler" nicht aufgerufen hatte:
Wire.onReceive(receiveEvent);

Die Testverbindung zw. 2 Arduino über ca 30cm verbunden geht definitiv auch ohne ext. PullUpsR's, wie folgendes beweist der Empfang einer Zählschleife 0..255:
26549
Da ich aber längere Verbindungen , um die 5..7m benötige wird dasdann in der Praxis nicht so gehen, aber um mal empfangende Daten enzuzeigen reicht mir das schon um I2C-Sendemodule zu kontrollieren.

Vielen Dank
Gerhard

Hier nun der funktionierende Code für meine Tests:


//Listing Master & Slave(ID=4)

// Wire Master Writer
// by Nicholas Zambetti <http://www.zambetti.com>

// Demonstrates use of the Wire library
// Writes data to an I2C/TWI slave device
// Refer to the "Wire Slave Receiver" example for use with this

// Created 29 March 2006

// This example code is in the public domain.


#include <Wire.h>

void setup()
{
Wire.begin(); // join i2c bus (address optional for master)
}

byte x = 0;

void loop()
{
Wire.beginTransmission(4); // transmit to device #4
Wire.write("x is "); // sends five bytes
Wire.write(x); // sends one byte
Wire.endTransmission(); // stop transmitting

x++;
delay(500);
}
/************************************************** ****************************/
//Listing Slave mit LCD
#include <LiquidCrystal.h>
#include <Wire.h>
LiquidCrystal lcd(8, 13, 9, 4, 5, 6, 7);



void setup()
{
lcd.clear();
lcd.begin(16, 2);
lcd.setCursor(0,0);
lcd.print("I2C-Verbindung");
Wire.begin(4); // join i2c bus with address #4
Wire.onReceive(receiveEvent); // register event
}

void loop()
{
delay(100);
}

void receiveEvent(int howMany)
{
while(1 < Wire.available()) // loop through all but the last
{
char c = Wire.read(); // receive byte as a character
Serial.print(c); // print the character
}
int x = Wire.read(); // receive byte as an integer
Serial.println(x); // print the integer
lcd.setCursor(0, 1);
lcd.print("Empfange : ");
lcd.setCursor(11,1);
lcd.print (char(x));
}

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