I2C 2-Wege-Kommunikation zwischen Arduino Uno und Arduino Mega

7

Wenn ich den Übertragungscode vom Slave entferne, funktioniert dies ordnungsgemäß, aber ich muss vom Slave senden.

Hier ist mein Mastercode

#include <Wire.h>
void setup() {
  Wire.begin(3); 
  Wire.onReceive(receiveEvent);
}
byte x = 0;

void loop() {
  Wire.beginTransmission(9); 
  Wire.write("s");        
  Wire.write(x);                
  Wire.endTransmission();    
  x++;
  delay(500);
}

void receiveEvent(int howMany) {
  if(Wire.available()){
    int x = Wire.read();
    Serial.println(x);
  }
}

Hier ist mein Slave-Code:

#include <Wire.h>
void setup() {
  Wire.begin(9);                // join i2c bus with address #9
  Wire.onReceive(receiveEvent); // register event
  Serial.begin(9600);           // start serial for output
}

void loop() {
  delay(100);
}

void receiveEvent(int howMany) {
  if(Wire.available()){
    char c = Wire.read(); 
    Serial.print(c);
    if(c == 's'){
      int x = Wire.read();
      Serial.println(x);
      //transmit to master 
      Wire.beginTransmission(3);
      Wire.write(1);
      Wire.endTransmission();
    } else {
      Wire.read();
    }
  }
}

Ist es möglich, Wire.onRequest (requestCallback) nicht zu verwenden? Daten an den Master senden? Freundlich helfen.

Srinivas
quelle
1
Wenn eine Skizze Wire.begin () aufruft und eine Nummer übergibt, hat sie sich selbst als Slave im Bus nominiert. Sie scheinen also zwei Sklaven zu haben. Normalerweise hätte man einen Master und einen Slave.
Was Sie zu wollen scheinen, ist eine Kombination aus dem Arduino Wire Tutorial arduino.cc/en/Tutorial/MasterReader und arduino.cc/en/Tutorial/MasterWriter, stimmen Sie zu?
Ich habe einen Blick darauf geworfen, kann ihn aber nicht richtig umsetzen. Wenn ich 2 wire.write gebe, liest der Meister es nicht richtig
Ich weiß nicht was du meinst, sorry.
Die Wire.requestFrom hat nur eine Wire.write Ich benötige mehrere Wire.write, die nicht unterstützt werden. Gibt es also Problemumgehungen?
Srinivas

Antworten:

6

Um als Master in den Bus einzusteigen, können Sie keine 7-Bit-Slave-Adresse angeben, sodass Ihr Code zwei Slaves enthält.

Unten finden Sie 2 Skizzen, die erfolgreich Daten an einen Slave senden. Ich würde vorschlagen, dass Sie sich das I2C-Protokoll ansehen und verstehen, dass es 4 Modi gibt:

  • Master-> Sender
  • Master-> Empfänger
  • Slave-> Sender
  • Slave-> Empfänger

Für jede Kommunikation, unabhängig davon, wie die Daten übertragen werden, ist ein Master erforderlich. Es ist der Master, der die Taktimpulse steuert. Deshalb ist es immer der Master, der die Kommunikation initiiert.

Die MasterReader / MasterWriter- Tutorials im Arduino-Forum sollten jetzt möglicherweise etwas sinnvoller sein, wenn Sie diese Modi verstehen.

Dieser Code zeigt, wie ein Master Daten an einen Slave sendet und wie er dann Daten vom Slave anfordert. Wenn wir diesen Code aus der Sicht des Masters betrachten, können Sie sehen, dass er im Wesentlichen besagt: Senden Sie dieses Byte an den Client (m-> t & s-> r) und fordern Sie dann Daten vom Slave an (m-> r, s-> t)

Hauptkennziffer

#include <Wire.h>

#define SLAVE_ADDRESS 0x60

void setup()
{
  Wire.begin(); 
  randomSeed(analogRead(3));
  Serial.begin(9600);  
}

byte x = 0;

void loop()
{
  x = random(0,255);
  Serial.print("Sent: ");
  Serial.print(x, HEX);
  Serial.print("\n");
  Wire.beginTransmission(0x60);   
  Wire.write(x);                
  Wire.endTransmission();   
  delay(500);
  Serial.println("Requesting Data"); 
  Wire.requestFrom(SLAVE_ADDRESS, 1);

  int bytes = Wire.available();
  Serial.print("Slave sent ");
  Serial.print(bytes);
  Serial.print(" of information\n");
  for(int i = 0; i< bytes; i++)
  {
    x = Wire.read();
    Serial.print("Slave Sent: ");
    Serial.print(x, HEX);
    Serial.print("\n");
  }  
  delay(500);
}

Slave-Code

#include <Wire.h>

#define SLAVE_ADDRESS 0x60
byte x = 0x00;
void setup()
{
  Wire.begin(SLAVE_ADDRESS);
  Wire.onReceive(receiveEvent);
  Wire.onRequest(requestEvent);
  Serial.begin(9600);
}

void loop()
{
  delay(100);
}

void requestEvent() 
{
  Serial.print("Request from Master. Sending: ");
  Serial.print(x, HEX);
  Serial.print("\n");

  Wire.write(x);
}

void receiveEvent(int bytes)
{
  if(Wire.available() != 0)
  {
    for(int i = 0; i< bytes; i++)
    {
      x = Wire.read();
      Serial.print("Received: ");
      Serial.print(x, HEX);
      Serial.print("\n");
    }
  }
}
Wayne
quelle
Auf dem Master können Sie den Adressbereich nach angeschlossenen Geräten durchsuchen. Dies wäre ein angemessener Ansatz.
Wajatimur
In beiden Event-Handlern: Führen Sie keine seriellen Ausdrucke innerhalb eines ISR durch. Es kann funktionieren, bis der serielle Puffer voll ist, dann hängt es.
Nick Gammon
1
Sie müssen nicht testen, if(Wire.available() != 0)da die bytesVariable die Anzahl der empfangenen Bytes hat. Wenn überhaupt, testen Sie, ob bytes > 0ich jedoch davon ausgehe, dass ein Empfangsereignis mindestens ein Byte haben würde.
Nick Gammon
1

Ich habe dieses Problem kürzlich durchlaufen. Ihr Slave benötigt zwei Funktionen: eine zum Senden und eine zum Empfangen von Daten.

// function: what to do when asked for data
void requestEvent() {
Wire.write(t); 
}

// what to do when receiving data from master
void receiveEvent(int howMany)
{Val = Wire.read();}

Hier ist ein Code, der beide Arten der i2c-Kommunikation in einem einzigen Code unterstützt

Senden und Empfangen verschiedener Datentypen über I2C in Arduino

Camilo
quelle
0

Sie hatten:

 void receiveEvent(int howMany)
 {
   {         
         if(Wire.available()){
           char c = Wire.read(); 
           Serial.print(c);
           if(c == 's'){
             int x = Wire.read();
             Serial.println(x);

             //transmit to master 
             Wire.beginTransmission(3);
             Wire.write(1);
             Wire.endTransmission();

           }else{
             Wire.read();
           }
         }

       }

Es gibt eine Reihe von Problemen mit Ihrem Slave-Code.

  1. Führen Sie keine seriellen Ausdrucke in einem ISR (Interrupt Service Routine) durch.
  2. Führen Sie in einem Empfangsereignis keine beginTransmission / endTransmission durch.
  3. Schreib nicht
  4. Verwenden Sie zum Zurücksenden von Daten ein requestEvent und kein receiveEvent.

Besser wäre:

// add in setup()
Wire.onRequest (requestEvent);  // interrupt handler for when data is wanted

...


volatile byte what;

void receiveEvent(int howMany)
{
  if (howMany < 2)
    return;

  char c = Wire.read ();
  if (c != 's')
    return;

  what = Wire.read ();  // remember what we got
}  // end of receiveEvent

void requestEvent()
{
  Wire.write (1);  // return a response
}  // end of requestEvent

Das Wire.requestFrom hat nur ein Wire.write. Ich benötige mehrere Wire.write, die nicht unterstützt werden. Gibt es also Problemumgehungen?

Sammeln Sie die Antwort und schreiben Sie einmal:

void requestEvent ()
  {
  byte buf [4] = { 1, 2, 3, 4 };
  Wire.write (buf, sizeof buf);   // send response
  }  // end of requestEvent

Referenz

Bei I2C - Two-Wire Peripheral Interface - für Arduino gibt es viele Beispiele

Nick Gammon
quelle