arduino <-> i2c <-> arduino

Hallo zusammen, wie kommunizieren eure Arduinos miteinander? ich habe ein Projekt wo mehrere Arduinos long integer werte miteinander austauschen sollten. Das ganze so schnell wie möglich. daher dachte ich an I2C das Problem ist ich bekomme es nicht hin long werte zu senden und als solche zu empfangen.

hat da einer schon mit Erfahrungen sammeln können - oder sogar ein Sketch wo so etwas realisiert ist.

Mfg Alex

Hallo, das paßt ja... habe ich gerade gemacht. Hier die Lösung Deines Problem. Funktioniert einwandfrei. Gruß und Spaß Andreas

Bei mir (mit ATtiny4313) funktioniert es so, wie hier beschrieben "den Slave so implementiert wie man es von einem IC kennt".

agmue:
Bei mir (mit ATtiny4313) funktioniert es so, wie hier beschrieben “den Slave so implementiert wie man es von einem IC kennt”.

Wobei das ein Workaround war. Zu dem Zeitpunkt war mit nicht klar dass man im onRequest() Event Handler nur ein einziges mal write() machen kann. Das ist der springende Punkt der nicht richtig dokumentiert ist.

Wenn einem das klar ist geht es auch einfacher. So kann man mit write() ein Array versenden. Und damit auch z.B. einfach die Adresse eines longs auf byte* casten. Oder mit einer Union arbeiten

Am Rande: Ohne besondere Vorkehrungen sollte man nicht mehr als 2 AVR Master auf dem Bus haben. Ab 3 besteht eine Deadlock Gefahr.

ich Danke euch! klingt jetzt makaber aber so ganz steige ich noch nicht dahinter. die Daten sollten auch in beiden Richtungen versendet werden.

Serenifly: einfach klingt momentan sehr gut hast du ein kleines Beispiel wo man Array hin und her sendet?

Was hast du genau vor? Sollen periodisch immer eine bestimmte Anzahl an longs gesendet werden?

Du sprichst von mehreren Arduinos. Wie sind die angeordnet? Sollen mehrere Arduinos etwas an einen zentralen schicken? Das ist wichtig, da das entscheidet ob man einfach immer senden kann, oder ob man besser den Master Daten von den Slaves fordern lässt.

die gewünschte Anordnung ist 1 Master und 4 Slaves. der Master sendet ein Sollwert an den entsprechenden Slave - er sollte zwischendurch fragen könne was der momentane Ist-wert ist und der Slave sendet von alleine den Ist wert wen er mit den Sollwert übereinstimmt.

ich möchte 4 Stepper über TB6560 ansteuern. da ich die Schrittdauer genau beeinflussen moechte ("Beschleunigung, Geschwindigkeit") bin ich angewiesen jeden Motor ein Nano zu spendieren.

Mfg Alex

der Slave sendet von alleine den Ist wert wen er mit den Sollwert übereinstimmt.

Slaves dürfen nicht unaufgefordert Senden

Hier mal ein Master der zwei long Werte an einen Slave schickt. Der Slave inkrementiert die Werte um 1 (einfach damit man was sieht) und der Master liest die Werte danach sofort wieder zurück (das geht wenn der Slave nichts großes damit macht. Serial Ausgabe kann das schon verzögern).

Wenn man nur einen Wert hat, dann kann man die Union auf ein Array der Größe 4 ändern. Das struct kann dann entfallen

Master:

#include <Wire.h>

union Data
{
  byte asArray[8];    //2 * 4 Bytes. Muss unbedingt mit der Größe des structs übereinstimmen!
  struct 
  {
    unsigned long value1;
    unsigned long value2;
  };
};

Data slaveOne;

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

void loop()
{
  slaveOne.value1 = 100000;
  slaveOne.value2 = 200000;
  writeValues(1, slaveOne);      //Daten senden

  if (getValues(1, slaveOne))    //Daten anfordern
  {
    Serial.println("Master:");
    Serial.println(slaveOne.value1);
    Serial.println(slaveOne.value2);
    Serial.println();
  }

  delay(1000);
}

void writeValues(byte slave, union Data& values)
{
  Wire.beginTransmission(slave);
  Wire.write(values.asArray, sizeof(values));
  Wire.endTransmission();
}

bool getValues(byte slave, union Data& values)
{
  Wire.requestFrom(slave, sizeof(values));
    
  if (Wire.available() > 0)
  {
    for (unsigned int i = 0; i < sizeof(values); i++)
      values.asArray[i] = Wire.read();

    return true;
  }
  else
    return false;
}

Slave:

#include <Wire.h>

union Data
{
  byte asArray[8];
  struct
  {
    unsigned long value1;
    unsigned long value2;
  };
};

Data values;

void setup() 
{
  Wire.begin(1);

  Wire.onReceive(receiveHandler);
  Wire.onRequest(requestHandler);
}

void loop() 
{
}

void receiveHandler(int numBytes)
{
  if (Wire.available() > 0)
  {
    for (unsigned int i = 0; i < sizeof(values); i++)
      values.asArray[i] = Wire.read();
  }

  values.value1++;
  values.value2++;
}

void requestHandler()
{
  //hier geht nur einmal write() !!
  
  Wire.write(values.asArray, sizeof(values));
}

union, struct und pointer, hoffentlich steigt Alex da durch 8)

Serenifly: Wobei das ein Workaround war.

Wo Du es schreibst, fällt es mir auch wieder ein. Aber dennoch funktioniert es prima :)

Serenifly: Slaves dürfen nicht unaufgefordert Senden

Drum kannst Du entweder den Master pollen lassen oder spendierst den Slaves eine Meldeleitung, mit der sie beim Master Gesprächsbedarf anmelden können. Die Meldeleitung kann mit einem Interrupt beim Master verbunden werden, ich nutze lieber einen im passenden Moment abgefragten normalen Eingang.

ich danke euch, das ist einfach klasse !! es ist natürlich richtig das Slave (von sich aus) nicht senden dürfen. ich versuche gerade das Beispiel auf ein Multimaster System um zu münzen.

Das mit einer Zusätzlichen Ader zumachen habe ich mir auch überlegt- aber es sind halt 1x4 Adern.

ardu-uno: Das mit einer Zusätzlichen Ader zumachen habe ich mir auch überlegt- aber es sind halt 1x4 Adern.

Es genügt auch eine, dann muß der Master halt suchen, welcher Slave was will. Oder jeder Slave sendet ein spezifisches serielles Bitmuster oder eine Zeit.

Nur aufpassen, daß sich zwei Ausgänge nicht gegenseitig zerstören, also quasi einen Einbitbus kreieren.

ardu-uno: ich möchte 4 Stepper über TB6560 ansteuern. da ich die Schrittdauer genau beeinflussen moechte ("Beschleunigung, Geschwindigkeit") bin ich angewiesen jeden Motor ein Nano zu spendieren.

Wenn du mit 800mA auskommst dann würde ich dir einen TMC222 empfehlen - dieser I2C Baustein hat nicht nur Rampengenerator und Positionszähler sondern auch eine echte Schrittüberwachung. Gewünschte Position, Beschleunigungswert und Geschwindigkeit - fertig ... den Rest macht der Baustein alleine. Und wenn vorzeitig eine Richtungsumkehr kommt - macht alles der Baustein. Dein Thema interessiert mich aber sehr.

Zu #8 Sketch für Master:

Wire.requestFrom(1, sizeof(values));

sollte den Parameter slave verwenden:

Wire.requestFrom(slave, sizeof(values));

Bin zufällig beim Ausprobieren über eine Warnung gestolpert :)

Ja, das wäre nicht verkehrt wenn man doch mal eine andere Adresse verwendet :)