Go Down

Topic: I2C- Übertragung zu einfach gedacht? (Read 4356 times) previous topic - next topic

HotSystems

Wenn du Probleme hast, 4-stellige Zahlen zu versenden, warum fängst du nicht einfacher an und schickst ein Byte (256) ?
Wenn das funktioniert kannst du dich doch an deine endgültige Version machen.
Gruß Dieter

I2C = weniger ist mehr: weniger Kabel, mehr Probleme. 8)

Eisebaer

hi,

klar kann man das in C/C++ machen, aber warum nicht das (arduino-) highByte und lowByte?

oder versteh' ich das falsch?

gruß stefan

Chris72622

#17
Mar 24, 2017, 06:02 pm Last Edit: Mar 24, 2017, 06:03 pm by Chris72622
Wenn du Probleme hast, 4-stellige Zahlen zu versenden, warum fängst du nicht einfacher an und schickst ein Byte (256) ?
Wenn das funktioniert kannst du dich doch an deine endgültige Version machen.
Weil ich Funksteckdosen habe, die z.B. solch einen Befehl erwarten:

myTx.send(1394004, 24);

Bisher habe ich es so gemacht, dass ich die einzelnen zu sendenden Befehle im ATtiny hinterlegt habe und diese dann bei Empfang einzelner bestimmten Zeichen via 433MHz versendet wurden. Sprich, kam ein 'A' an, wurde "Befehl A" gesendet, usw.

Damit ich nun nicht immer den ATtiny mit neu dazugekommenen Befehlen "füttern" muss, würde ich die zu sendenden "Befehle"/ Zahlen nun gerne direkt via I2C übertragen. Dazu kommt, dass der ATtiny leider etwas verbaut ist und ich es auch so pauschal gerne mal wissen würde, wie "man" das macht.

Gruß Chris
Bilnk wtiohut daley.

HotSystems

Weil ich Funksteckdosen habe, die z.B. solch einen Befehl erwarten:
Ok, dann musst du dich ranmachen und entsprechend der Doku den Code erstellen.
Wobei das nun gut beschrieben ist.
Gruß Dieter

I2C = weniger ist mehr: weniger Kabel, mehr Probleme. 8)

Eisebaer

hi,

also geht's ja nicht unbedigt um 2 byte, das kann ja laut Deinem beispiel auch länger sein.

wenn Du in google nach arduino longint i2c suchst, findest Du einiges (ich hab' das problem nicht, will nicht wirklich lesen). aber dann ist vielleicht auch das senden als einzelne ziffern eine option.

gruß stefan

ElCaron

aber dann ist vielleicht auch das senden als einzelne ziffern eine option.
Nochmal: Warum zum Geier sollte man irgendwas in DEZIMALZIFFERN aufteilen? Konvertiert doch gleich ins Sexagesimalsystem, macht auch keinen Sinn, ist aber etwas effizienter.

Chris72622

#21
Mar 25, 2017, 09:09 am Last Edit: Mar 25, 2017, 12:14 pm by Chris72622
So, mit einem unsigned int läuft es nun. Hab viel gelernt.

Anbei die Sketche. Zuerst unsigned int, dann unsigned long.

Mit der unsigned long Variante müsste man theoretisch auch kleinere Datentypen als unsigned long via I2C senden können. Dies muss ich jedoch erst noch genauer untersuchen.

Gruß Chris

Code: [Select]
//  I2C-SENDER

#include <Wire.h>

unsigned int zu = 4116;
unsigned int auf = 4117;

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

void loop()
{
  Serial.println("zu");
  Wire.beginTransmission(0x26);  // Startet die I2C-Übertragung an 0x26 (ATtiny85)
 
  // Wire.write(zu >> 8);    // Sendet zuerst das obere Byte des Integers (b00010100, d20) via Bit-Verschiebung
  // Wire.write(zu & 0xff);  // Sendet dann das untere Byte des Integers (b00010000, d16) via Maskierung
 
  Wire.write(highByte(zu));  // Sendet zuerst das obere Byte des Integers
  Wire.write(lowByte(zu));   // Sendet dann das untere Byte des Integers
 
  Wire.endTransmission();        // Stoppt die I2C-Übertragung
  delay(10000);
  Serial.println("auf");
  Wire.beginTransmission(0x26);  // Startet die I2C-Übertragung an 0x26 (ATtiny85)
  // Wire.write((byte *)&auf, sizeof(auf));
  Wire.write(highByte(auf));  // Sendet zuerst das obere Byte des Integers
  Wire.write(lowByte(auf));   // Sendet dann das untere Byte des Integers
  Wire.endTransmission();        // Stoppt die I2C-Übertragung
  delay(10000);
}


Code: [Select]
/*  I2C-EMPFÄNGER

    Anschluss des Attiny85 an den Uno:

                    1 |  \/  | 8  5V
                    2 |      | 7  SCL, Arduino A5, 4,7kOhm Pullup
   433MHz TX-Modul  3 |      | 6
               GND  4 |      | 5  SDA, Arduino A4, 4,7kOhm Pullup

*/

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

#define I2C_SLAVE_ADDR  0x26            // i2c slave address (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()
{
  unsigned int val = 0;
  if (TinyWireS.available())
  {
    while (TinyWireS.available())
    {
      val = TinyWireS.receive();      // highByte
      val <<= 8;
      val |= TinyWireS.receive();     // lowByte
    }
    digitalWrite(ledPin, HIGH);
    for (int i = 0; i < sendCnt - 1; i++)
    {
      myTx.send(val, 24);
    }
    digitalWrite(ledPin, LOW);
  }
}


..google nach arduino longint i2c suchst
Ja, danke. Sehr interessant.

unsigned int-Variante:

Code: [Select]
//  I2C-SENDER

#include <Wire.h>

unsigned long val = 1397079;  // Das zu sendende unsigned long ("Leselampe aus")

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

void loop()
{
  Serial.println("zu");
  Wire.beginTransmission(0x26);  // Startet die I2C-Übertragung an 0x26 (ATtiny85)
 
  byte longArray[4];            // Beinhaltet den unsigned long Wert (aufgeteilt in vier Bytes)

  longArray[0] = val >> 24;     // Das erste Byte des unsigned longs
  longArray[1] = val >> 16;     // Das zweite Byte des unsigned longs
  longArray[2] = val >> 8;      // Das dritte Byte des unsigned longs
  longArray[3] = val & 0xFF;    // Das letzte Byte des unsigned longs

  Wire.write(longArray, 4);     // Sendet das komplette unsigned long (über longArray)

  Wire.endTransmission();        // Stoppt die I2C-Übertragung
  delay(5000);
}


Code: [Select]
/*  I2C-EMPFÄNGER

    Anschluss des Attiny85 an den Uno:

                    1 |  \/  | 8  5V
                    2 |      | 7  SCL, Arduino A5, 4,7kOhm Pullup
   433MHz TX-Modul  3 |      | 6
               GND  4 |      | 5  SDA, Arduino A4, 4,7kOhm Pullup

*/

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

#define I2C_SLAVE_ADDR  0x26            // i2c slave address (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()
{
  unsigned long val = 0;
  if (TinyWireS.available())
  {
    while (TinyWireS.available())
    {
      val <<= 8;
      val |= TinyWireS.receive();
    }
    digitalWrite(ledPin, HIGH);
    for (int i = 0; i < sendCnt - 1; i++) myTx.send(val, 24);
    digitalWrite(ledPin, LOW);
  }
}
Bilnk wtiohut daley.

HotSystems

Und schon wieder diese merkwürdige Bezeichnung für I2C: "Sender und Empfänger", die gibt es nicht.
Gruß Dieter

I2C = weniger ist mehr: weniger Kabel, mehr Probleme. 8)

Chris72622

Was ist denn daran merkwürdig?

Der Sender sendet einen I2C-Befehl an den Empfänger dieser Nachricht.
Dieser wiederum hat einen 433MHz-Sender verbaut, der den entsprechenden Befehl umsetzt.

Gruß Chris
Bilnk wtiohut daley.

HotSystems

Was ist denn daran merkwürdig?

Der Sender sendet einen I2C-Befehl an den Empfänger dieser Nachricht.
Dieser wiederum hat einen 433MHz-Sender verbaut, der den entsprechenden Befehl umsetzt.

Gruß Chris
Weil es keinen eindeutigen Sender bzw. Empfänger bei I2C gibt.
Es sind immer noch Master und Slave.
Die können immer beides, senden und empfangen.
Ein Master kann von sich aus senden, ein Slave erst auf Anforderung.

Ich erwähne es nur, damit Anfänger keine falschen Infos erhalten.
Und du hast es doch in deinem Anfangspost auch schon geändert.
Gruß Dieter

I2C = weniger ist mehr: weniger Kabel, mehr Probleme. 8)

Chris72622

#25
Mar 25, 2017, 01:26 pm Last Edit: Mar 25, 2017, 02:16 pm by 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.

Welchen Sinn macht es eigentlich, dass Slaveadressen meistens (immer?) hexadezimal angegeben werden?

Gruß Chris

Edit: Anbei nun die zwei finalen Sketche, mit denen sich Werte von bool bis unsigned long an einen definierten Slave übertragen lassen. valA bis valD dienen zur testweisen Übertragung vordefinierter Werte. Bzgl. Optimierungspotential bitte ich um Hinweise.

Code: [Select]
// I2C-SENDER (MASTER)

#include <Wire.h>

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

static unsigned long valC = 4116;  // Das zu sendende unsigned long ("Dunstabzugshaube aus")
static 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(valB, 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)
  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
}


Code: [Select]
// 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;

  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);
  }
}
Bilnk wtiohut daley.

Eisebaer

hi,

Quote
Welchen Sinn macht es eigentlich, dass Slaveadressen meistens (immer?) hexadezimal angegeben werden?
keinen natürlich...

das einzige, das noch sinnloser ist, ist das:


Quote
static byte id = 0x26;               // ID des ATtiny85
#define I2C_SLAVE_ADDR  0x26            // I2C Slave-Adresse (38)
mal so, mal so, und dann schreibst Du im  kommentar, wie Du es WIRKLICH denkst. dann schreib' es doch gleich dezimal hin.
ist Dein gutes recht, wenn Du dezimal denkst.

wenn man schon länger programmiert, tut man sich binär einfach leichter, weil auch der prozessor/controller so denkt. hex ist dann nur eine kurze schreibweise für binär.

gerade bei der kommunikation ist es extrem hilfreich, immer vor sich zu sehen, was sich "auf der leitung" wirklich abspielt, elektrisch gesehen. ein logic analyser kann einem da die augen öffnen.

gruß stefan

Serenifly

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.

Eisebaer

gutes beispiel, fliege. hatten wir erst vorgestern_

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

gruß stefan

Eisebaer

hi,

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

gruß stefan

Go Up