I2C Wire , Arduino mit Adresse 1 fühlt sich IMMER angesprochen

Hallo,

#1

void setup()
{
  Wire.begin(111); // I2C Bus als #111 betreten
  Wire.onReceive(beiempfang);
...


void anzahlsetzen(){
  Wire.beginTransmission(anslavenr+1); //Starte Senden an Slave#
  Wire.write(anzahl[anslavenr]); //Sende Anzahl
  Wire.endTransmission(); //Beende Uebertragung

...

Output über Serial.print ist korrekt ( 1 + Anzahlvon2 , dann 2+ Anzahlfür2 etc..)

Aber der 2te Arduino fühlt sich jedes mal angesprochen und empfängt die Nachricht, auch wenn sie eigtl an Nummer 2 , 3 , 4 oder 5 gesendet wurde und nicht an ihn!
Es sind nur 2 Arduinos verbunden. Die anderen sollen nur in der Theorie existieren.

#2:

int slavenr = 1;
{
  Wire.begin(slavenr); // I2C Bus als #1 betreten
  Wire.onReceive(beiempfang); //bei Empfang diese Funktion ausfuehren


void beiempfang(int howMany)
{
  int x = Wire.read();    // byte als integer empfangen
  Serial.println(x);         // debugging am pc
  if (x > 0) { anzeige(x); }
}

Bzw ich merk gerade, #2 spuckt seltsamerweise IMMER eine 3 aus. obwohl #1 z.b. sendet an 1: 3 an 2: 4 an 3: 5 etc. Bei jedem senden von #1 egal was an wen spuckt #2 ne 3 aus :smiley:

Poste ganze Sketche, nicht nur Ausschnitte, es könnte ja sein, dass Dein Fehler in einem anderen Code-Stück begraben liegt.

#include <Wire.h>

void setup()
{
  Wire.begin(111); // I2C Bus als #111 betreten
  Wire.onReceive(beiempfang); //bei Empfang diese Funktion ausfuehren
  Serial.begin(9600); //fuer debugging am PC
}

byte anzahl[] = {3, 4, 8, 3, 5}; // Slave #1 kriegt Zahl #1 (hier z.b. 3)
int anslavenr;
int slavenummer;
void loop()
{
  for (int anslavenr = 0; anslavenr < 5; anslavenr++)
 { 
  if (anzahl[anslavenr] > 0) { anzahlsetzen(); }
  Serial.print(anslavenr+1);
  Serial.print(anzahl[anslavenr]);
  Serial.print('\n');
  delay(2000);
 }

}

void anzahlsetzen(){
  Wire.beginTransmission(anslavenr+1); //Starte Senden an Slave#
  Wire.write(anzahl[anslavenr]); //Sende Anzahl
  Wire.endTransmission(); //Beende Uebertragung
}

void beiempfang(int howMany) //diese Funktion wird bei Empfang ausgefuehrt
{
  while(1 < Wire.available()) // alle bytes bis auf das letzte empfangen
  {
    int slavenummer = Wire.read(); // Slavenummer empfangen und speichern
    Serial.print(slavenummer);         // debugging am pc
  }
  int okbtn = Wire.read();
  Serial.println(okbtn); //debugging am pc
 if (okbtn == 1) { anzahl[slavenummer-1] = 0; }
  
}

Ausgabe wie erwartet:
13
24
38
43
55

#include <Wire.h>
const int okbtn = 10;
int okbtnstate = 0;
int slavenr = 1;
// Array für Ausgabe der Zahlen von 0 bis 9
byte siebenSegmentZahlen[10][7] =
{
   { 0,0,0,0,0,0,1 },  // = 0 (Leds bei Low(0) an!)
   { 1,0,0,1,1,1,1 },  // = 1
   { 0,0,1,0,0,1,0 },  // = 2
   { 0,0,0,0,1,1,0 },  // = 3
   { 1,0,0,1,1,0,0 },  // = 4
   { 0,1,0,0,1,0,0 },  // = 5
   { 0,1,0,0,0,0,0 },  // = 6
   { 0,0,0,1,1,1,1 },  // = 7
   { 0,0,0,0,0,0,0 },  // = 8
   { 0,0,0,0,1,0,0 }   // = 9
};

void setup()
{
  Wire.begin(slavenr); // I2C Bus als #1 betreten
  Wire.onReceive(beiempfang); //bei Empfang diese Funktion ausfuehren
  Serial.begin(9600); //fuer debugging am PC
  
  pinMode(2, OUTPUT); // definieren Pin 2 digital als Ausgang
  pinMode(3, OUTPUT); // definieren Pin 3 digital als Ausgang
  pinMode(4, OUTPUT); // definieren Pin 6 digital als Ausgang
  pinMode(5, OUTPUT); // definieren Pin 7 digital als Ausgang
  pinMode(6, OUTPUT); // definieren Pin 8 digital als Ausgang
  pinMode(7, OUTPUT); // definieren Pin 9 digital als Ausgang
  pinMode(8, OUTPUT); // definieren Pin 10 digital als Ausgang
  pinMode(9, OUTPUT); // definieren Pin 11 digital als Ausgang
  pinMode(okbtn, INPUT);   
}

void loop()
{
  okbtnstate = digitalRead(okbtn);
  delay(500);
  if (okbtnstate == HIGH) { okbtnpressed(); }
}

void beiempfang(int howMany)
{
  int x = Wire.read();    // byte als integer empfangen
  Serial.println(x);         // debugging am pc
  if (x > 0) { anzeige(x); }
}

void okbtnpressed(){
  Wire.beginTransmission(111); // an 111 senden
  Wire.write(slavenr);             // Slavenummer senden
  Wire.write(1);             // eine 1 senden als okbtnpress
  Wire.endTransmission();    // stop transmitting
  }
  
void anzeige(byte digit){
  byte pin = 2;
  for (byte segmentZaehler = 0; segmentZaehler < 7; ++segmentZaehler)
  {
    digitalWrite(pin, siebenSegmentZahlen[digit][segmentZaehler]);
    ++pin;
  }
}

Ausgabe:

3
3
3
und zwar bei jeder Ausgabe oben eine 3 und nicht nur bei 13

Welche Arduino ist der Master?
Grüße Uwe

Der obere, aber sie sollen da eigentlich flexibel sein.. so dass eine Kommunikation von beiden aus gestartet werden kann.
Geht mit den zweien alleine und ohne die anderen nicht vorhandenen anzusprechen auch ganz gut, beide senden und empfangen wie vorgesehen..

Sind 2 Arduino Nano, stecken beide im gleichen PC, verbunden sind nur A4 und A5.

Der Master hat per Deifinition die Adresse 0 und diese wird bei Wire.begin(); nicht geschrieben. Es gibt einen Multimaterbetrieb aber darüber kann ich Dir nichts genaues sagen.
Grüße Uwe

Die Wire-Bibliothek unterstützt den Multimaster-Betrieb nicht, zudem funktioniert der I2C-Bus nicht so, wie Du Dir das scheinbar vorstellst. Auf dem Bus gibt es im Normalfall einen Master und mehrere Slaves. Auch bei Multimaster-Betrieb ist nicht vorgesehen, dass die Master zugleich auch Slaves sind. Du musst die Kommunikation also so aufbauen, dass der Master dem Slave Befehle schickt und dieser nur auf einen Befehl antwortet. Dies liegt darin begründet, dass der Master den Bus taktet, er schickt diese Taktsignale auch für den Empfang der angeforderten Daten, aber natürlich nur soviele, wie er auch wirklich Bits erwartet.

Du solltest also Kommandos vorsehen, die auf den Slave schreiben und solche, die von ihm Daten zurückerwarten. Wenn der Slave auf Tastendrücke oder ähnliches reagieren soll und das dem Master mitteilen muss, dann muss der Master genügend oft nachfragen (pollen).

Hallo pylon,

zunächst Danke für die Antwort. Das habe ich bereits vermutet und befürchtet.. Wenn ich jedoch nur die beiden alleine kommunizieren lasse, ohne Spaßeshalber nicht vorhandene zu adressieren, funktioniert alles wie gewollt

ich lasse #1 von 1 bis 9 durchzählen und das an #2 schicken, #2 empfängt alles und beim empfang von 5 wird der buttonpress aktiv an #1 gesendet. (dachte nen versuch ist es ja wert und es klappte)

Befürchte aber in der Tat auch, dass das wohl echt ein glücklicher zufall ist, dass das funktioniert und es auch nur mit genau 2 und nicht mehr Arduinos funktionieren wird :confused:

Dennoch würde ich gerne verstehen, weshalb #2 sich bei jedem senden von #1 egal an wen und egal was nicht nur angesprochen fühlt aber vorallem jedes mal eine 3 empfängt ?

//EDIT: da muss ich echt nen Schwein mit den delayzeiten gehabt haben, denn ich krieg es gerade nicht mehr einwandfrei reproduziert.

Es kann schon funktionieren, aber ob es funktioniert, ist nicht gewährleistet. Wenn Du damit leben kannst, dass die Kommunikation nur in gewissen Fällen klappt, kannst Du es weiter so versuchen. Ich bevorzuge deterministische Systeme und verwende die Hardware deshalb nach Möglichkeit nicht ausserhalb der Spezifikation.

Was sicher nicht hilfreich ist:

void beiempfang(int howMany)
{
  int x = Wire.read();    // byte als integer empfangen
  Serial.println(x);         // debugging am pc
  if (x > 0) { anzeige(x); }
}

Innerhalb eines Interrupt-Handlers sollte nie auf die serielle Schnittstelle geschrieben werden, dass kann zu einem Deadlock führen.

Ja, das ganze habe ich auch nur so auf gut Glück gemacht, weil es eh nie echt verwendung finden sollte, alles mehr schein als sein.

Aber ich werde es jetzt vermutlich doch korrekt auf die Beine stellen :wink:

Also ich kann problemlos einen Master an Slaves Nachrichten senden und auch von ihnen requesten lassen? Dann muss ich das wohl oder übel in ausreichender Frequenz so umsetzen :wink:

pylon:
Was sicher nicht hilfreich ist:

void beiempfang(int howMany)

{
  int x = Wire.read();    // byte als integer empfangen
  Serial.println(x);         // debugging am pc
  if (x > 0) { anzeige(x); }
}




Innerhalb eines Interrupt-Handlers sollte nie auf die serielle Schnittstelle geschrieben werden, dass kann zu einem Deadlock führen.

Das merk ich mir gerne, aber die Schuld reiche ich weiter an http://arduino.cc/en/Tutorial/MasterWriter :wink:

Das merk ich mir gerne, aber die Schuld reiche ich weiter an http://arduino.cc/en/Tutorial/MasterWriter

Absolut richtig, es ist dort schon falsch im Code.

Also ich kann problemlos einen Master an Slaves Nachrichten senden und auch von ihnen requesten lassen?

Ja, sollte prinzipiell kein Problem sein. Probleme kriegst Du, wenn der Bus eine gewissen Länge überschreitet, aber die sind elektrischer Natur (Bus-Kapazität) und nicht logischer.

Gedankenfehler gefunden. Zurücksetzen einer Variable vergessen. Shame on me.