I2C- Übertragung zu einfach gedacht?

Die Adresse in Hex macht es leichter lesbar wenn man sie aus der Binärdarstellung ableiten muss. I2C Adressen sind oft aus 3-4 festen Bits und 3-4 über Pins einstellbaren Bits zusammengesetzt.

gutes beispiel, fliege. hatten wir erst vorgestern_

http://forum.arduino.cc/index.php?topic=465004.0

gruß stefan

hi,

nicht versucht, aber wäre eine union aus unsigned long und einem array hier eine vereinfachende lösung oder unschön?

gruß stefan

Chris72622:
Ok, danke für den Hinweis.

Achtung Anfänger:

Die Bezeichnungen I2C-SENDER und I2C-EMPFÄNGER innerhalb meiner Sketche beziehen sich ausschließlich auf meinen Anwendungsfall.

Danke, dass du es geändert hast.

Gerne.

Ich hänge hier jetzt mal noch etwas zu dem Thema Passendes an, um nicht einen weiteren Thread zu eröffnen.

Durch das schnelle Wachstum des Projekts ergab sich mittlerweile der Umstand, dass in Zukunft mehrere ATtiny85 (I2C-Slaves) angesprochen werden sollen.

Dies bedingt, dass mit der Speicherung der zu übertragenden Werte zusätzlich nun jeweils die Slave-ID mitgespeichert werden muss.

Um dies zu ermöglichen erstellte ich zwei Arrays, die jeweils auf identische Art und Weise ausgelesen werden. Ich meine damit, dass wenn z.B. beim "unsigned long Wertearray" (im Sketch fifo genannt) der Index 2 ausgelesen wird, ich im "byte Slave-ID-Array" (im Sketch fifoID genannt) ebenfalls den gleichen Index auslese.

Nun frage ich mich, wie ich den folgenden schlecht lesbaren Abschnitt lesbarer machen und evtl. vereinfachen und/oder verbessern/kürzen kann:

void tinySend()
{ 
  Wire.beginTransmission(fidoIDread()); // Startet die I2C-Übertragung an einen definierten ATtiny85
  Wire.write(fifoRead());               // Senden des Wertes
  Wire.endTransmission();               // Stoppt die I2C-Übertragung
}

byte fidoIDread()                       // Übergibt die Slave-ID des ATtiny85 an den ein Wert gesendet werden soll
{
  return fifoID[fifoReadIndex];         // Slave-ID zum Abschluss aus der Funktion übergeben
}

unsigned long fifoRead()                                                                     // Lesefunktion
{
  unsigned long c;                                                                  // unsigned long initialisieren
  c = fifo[fifoReadIndex];                                                          // Wert aus Ringbuffer lesen
  fifoReadIndex++;                                                                  // Leseindex um eine Stelle erhöhen
  if (fifoReadIndex >= FIFOSIZE) fifoReadIndex = 0;                                 // Beim erreichen des Arrayendes den Leseindex auf null zurücksetzen
  return c;                                                                         // Zeichen zum Abschluss aus der Funktion übergeben
}

Es geht hierbei konkret um das Auslesen der beiden o.a. Arrays, gefolgt vom Sendevorgang.

Gruß Chris

Hast Du Dich schon mal in Deinem Buch über struct schlau gemacht und Arrays aus Structs?

Gruß Tommy

PS: "fifo" hat in der IT eine fest definierte Bedeutung, die in Deinem Sketch wohl nicht gegeben ist. Du solltest es anders nennen.

Gruß Tommy

Jein. Von "structs" las ich mal. Arrays aus ihnen sind mir gänzlich fremd. Mein C++ Schmöker liegt nun wieder im Wohnzimmer. Ein zweiter Anlauf sollte vieles nachhaltig klären. Ab heute wird wieder gelesen. :slight_smile:

Das fifo-Array funktioniert wie ein Ringpuffer und wurde innerhalb meines Sketches eben deshalb von mir so benannt.

Gruß Chris

Hallo, ich schaue jetzt nur auf #31.

 Wire.write(fifoRead());
...
unsigned long fifoRead()
{
  unsigned long c;
...
  return c;
}

Mit write kannst Du nur ein Byte schicken, unsigned long hat derer vier. Da paßt was nicht, oder?

Stimmt. So sollte es nun passen:

void tinySend()
{ 
  Wire.beginTransmission(fidoIDread()); // Startet die I2C-Übertragung an einen definierten ATtiny85
  unsigned long x = fifoRead();         // Laden des unsigned long aus dem fifo-Array
  byte longArray[4];                    // Beinhaltet den unsigned long Wert (aufgeteilt in vier Bytes)
  longArray[0] = x >> 24;               // Das erste Byte des unsigned long
  longArray[1] = x >> 16;               // Das zweite Byte des unsigned long
  longArray[2] = x >> 8;                // Das dritte Byte des unsigned long
  longArray[3] = x & 0xFF;              // Das letzte Byte des unsigned long
  Wire.write(longArray, 4);             // Sendet das komplette unsigned long (über longArray)
  Wire.endTransmission();               // Stoppt die I2C-Übertragung
}

byte fidoIDread()                       // Übergibt die Slave-ID des ATtiny85 an den ein Wert gesendet werden soll
{
  return fifoID[fifoReadIndex];         // Slave-ID zum Abschluss aus der Funktion übergeben
}

unsigned long fifoRead()                                                                     // Lesefunktion
{
  unsigned long c;                                                                  // unsigned long initialisieren
  c = fifo[fifoReadIndex];                                                          // Wert aus Ringbuffer lesen
  fifoReadIndex++;                                                                  // Leseindex um eine Stelle erhöhen
  if (fifoReadIndex >= FIFOSIZE) fifoReadIndex = 0;                                 // Beim erreichen des Arrayendes den Leseindex auf null zurücksetzen
  return c;                                                                         // Zeichen zum Abschluss aus der Funktion übergeben
}

Werd mich aber trotzdem mal in die structs einlesen.

unsigned long x = fifoRead();         // Laden des unsigned long aus dem fifo-Array

byte longArray[4];                    // Beinhaltet den unsigned long Wert (aufgeteilt in vier Bytes)
 longArray[0] = x >> 24;               // Das erste Byte des unsigned long
 longArray[1] = x >> 16;               // Das zweite Byte des unsigned long
 longArray[2] = x >> 8;                // Das dritte Byte des unsigned long
 longArray[3] = x & 0xFF;              // Das letzte Byte des unsigned long
 Wire.write(longArray, 4);             // Sendet das komplette unsigned long (über longArray)

unsigned long x = fifoRead(); // Laden des unsigned long aus dem fifo-Array
~~ byte longArray[4]; // Beinhaltet den unsigned long Wert (aufgeteilt in vier Bytes)~~
~~ longArray[0] = x >> 24; // Das erste Byte des unsigned long~~
~~ longArray[1] = x >> 16; // Das zweite Byte des unsigned long~~
~~ longArray[2] = x >> 8; // Das dritte Byte des unsigned long~~
~~ longArray[3] = x & 0xFF; // Das letzte Byte des unsigned long~~
Wire.write((byte *)&x, sizeof(x)); // Sendet das komplette unsigned long x

Hi combie,

ich bekomme das so wie von Dir vorgeschlagen via 433MHz leider nicht gesendet, wenn ich an der Empfängerseite (I2C-Slave) dann so "decodiere":

void i2cReceive()
{
  unsigned long val = 0;

  if (TinyWireS.available())
  {
    digitalWrite(ledPin, HIGH);
    while (TinyWireS.available())
    {
      val <<= 8;                   // Bitshift nach links
      val |= TinyWireS.receive();  // Hinzufügen der untersten acht Bits
    }
    for (int i = 0; i < sendCnt - 1; i++) myTx.send(val, 24);
    digitalWrite(ledPin, LOW);
  }
}

Gruß Chris

void i2cReceive()
{
  unsigned long val = 0;
  byte * p = (byte*) &val;

  if (TinyWireS.available())
  {
    digitalWrite(ledPin, HIGH);
    for (int i = 0; i < sizeof(val); i++)
         *p++ = TinyWireS.receive();
    for (int i = 0; i < sendCnt - 1; i++) myTx.send(val, 24);
    digitalWrite(ledPin, LOW);
  }
}

leider ungetestet
Habe gerade nicht die nötige Infrastruktur im Zugriff

Es funktioniert! :slight_smile: Vielen Dank für Deine Hilfe.

Der Code ist nun eine gute Basis für mich zum Üben. Mir ist (noch) nicht klar, was da innerhalb der gesendeten Bytes übertragen wird.

Gruß Chris

Anbei für evtl. Interessierte:

// I2C-SENDER (MASTER)

#include <Wire.h>

const unsigned long valA = 1397079;  // Das zu sendende unsigned long ("Leselampe ein")
const unsigned long valB = 1397080;  // Das zu sendende unsigned long ("Leselampe aus")

const unsigned long valC = 4116;  // Das zu sendende unsigned long ("Dunstabzugshaube aus")
const unsigned long valD = 4117;  // Das zu sendende unsigned long ("Dunstabzugshaube ein")

static byte id = 0x26;               // ID des ATtiny85

void setup()
{
  delay(1000);
  Wire.begin(); // Masterdresse optional (wird hier nicht verwendet)
  i2cSend(valA, id);
}

void loop()
{
}

void i2cSend(unsigned long x, byte y) // x = zu sendender Wert, y = ID des ATtiny85
{
  Wire.beginTransmission(y);          // Startet die I2C-Übertragung an 0x26 (ATtiny85)
  Wire.write((byte *)&x, sizeof(x));  // Sendet das komplette unsigned long
  Wire.endTransmission();             // Stoppt die I2C-Übertragung
}
// I2C-EMPFÄNGER (SLAVE)

#include "TinyWireS.h"                  // wrapper class for I2C slave routines
#include <RCSwitch.h>

#define I2C_SLAVE_ADDR  0x26            // I2C Slave-Adresse (38)

// 433MHz Modul

RCSwitch myTx = RCSwitch();

const byte txPin = 4;                   // Ausgang Sender-Daten an ATtiny Pin 3  (kein Tippfehler!)
const byte sendCnt = 4;                 // max. Anzahl der Aussendungen
const byte ledPin = 3;                  // Pin 2 (kein Tippfehler!)

void setup()
{
  TinyWireS.begin(I2C_SLAVE_ADDR);      // init I2C Slave mode
  pinMode (txPin, OUTPUT);              // 433MHz Modul
  pinMode (ledPin, OUTPUT);             // LED
  myTx.enableTransmit(txPin);           // Übertragung ermöglichen
  myTx.setPulseLength(375);             // Pulsweite
}

void loop()
{
  i2cReceive();
}

void i2cReceive()
{
  unsigned long val = 0;
  byte * p = (byte*) &val;

  if (TinyWireS.available())
  {
    digitalWrite(ledPin, HIGH);
    for (int i = 0; i < sizeof(val); i++) *p++ = TinyWireS.receive();
    for (int i = 0; i < sendCnt - 1; i++) myTx.send(val, 24);
    digitalWrite(ledPin, LOW);
  }
}

Chris72622:
Es funktioniert! :slight_smile: Vielen Dank für Deine Hilfe.

Der Code ist nun eine gute Basis für mich zum Üben. Mir ist (noch) nicht klar, was da innerhalb der gesendeten Bytes übertragen wird

Dann lass dir doch jedes einzelne Byte auf dem seriellen Monitor oder auf einem LCD anzeigen.

Ja, das war auch mein Gedanke. Leider habe ich aber zum Einen nur einen Uno und einen ATtiny85 hier und zum Anderen führte folgende Eingabe nur zu Fehlermeldungen:

Serial.println((byte *)&x, sizeof(x));

Gruß Chris

Was willst du dir denn da anzeigen lassen?

Weiterhin:
Solange du die Sprache, welche du verwendest, nicht beherrscht, bleibt eine Arbeit ein wildes chaotisches stochern im Nebel.

Merksatz:
Nacktes "Ausprobieren" ist keine tragfähige Strategie um stabile, fehlerfreie, Programme zu erstellen.

combie:
Was willst du dir denn da anzeigen lassen?

Den Inhalt der übertragenen Bytes.

Gruß Chris

Ich kann es nur wiederholen: Du verstehst von dem, was Du tust, fast nichts.

Du fragst so lange, bis Dir jemand einen Codeschnipsel gibt, den kopierst Du rein und hast keinerlei Interesse, ihn zu verstehen. Anders kann man das nach knapp 1300 Posts nicht mehr ausdrücken.
Du musst das Buch lesen, das Du immer erwähnst, und verstehen was Du kopierst, nicht nur das Buch irgendwo hin legen und so weiter machen, wie bisher.

Gruß Tommy

Ich bin dabei, danke.

Gruß Chris