Go Down

Topic: Arduinos finden sich nicht über I2C (Read 4038 times) previous topic - next topic

Tommy56

Du kannst auf dem Sensornano doch laufend messen. Evtl. während der Messung eine andere Variable nutzen und danach umkopieren. Damit kann der Sensornano immer den letzten gültigen Wert sofort bereit stellen.

Du musst dem Sensornano (SN) auch noch sagen, welchen Messwert Du haben willst (das werden ja 2 verschiedene werden.
Also z.B. 1 zum SN  = gib mir RPM, 2 = gib mir den anderen Wert.

Gruß Tommy
"Wer den schnellen Erfolg sucht, sollte nicht programmieren, sondern Holz hacken." (Quelle unbekannt)

Serenifly

Lesetipp, wobei union data_u der springende Punkt ist.
Das ist wieder ein schlechtes Beispiel. Das ist für TinyWire, wo man mit send() wirklich nur ein Byte schicken kann. Mit Wire() geht mit write() ein ganzes Array. Dadurch wird es wesentlich einfacher.

Ich mache mal ein aktuelles und korrektes Beispiel. Und dann bitte in Zukunft darauf verlinken. Und nicht auf veralteten oder speziellen Code.

Serenifly

#32
Feb 18, 2017, 09:04 pm Last Edit: Feb 18, 2017, 10:52 pm by Serenifly
Ok hier mal was rein für Wire. Es werden alle Werte auf einmal übertragen. Dadurch spart man sich erst mal einen Index zu setzen.

Master:
Code: [Select]

#include <Wire.h>

const int SLAVE_ADR = 5;
const unsigned int NUMBER_OF_VALUES = 2;

union data_u
{
  unsigned int i[NUMBER_OF_VALUES];
  byte b[sizeof(i)];
};

data_u values;

void setup()
{
  Serial.begin(9600);
  Serial.println("Master");
  Wire.begin();

  getData();
}

void loop()
{
}

void getData()
{
  Wire.requestFrom(SLAVE_ADR, sizeof(values.b));
  for (byte i = 0; i < sizeof(values.b); i++)
      values.b[i] = Wire.read();

  Serial.println(values.i[0]);
  Serial.println(values.i[1]);
}


Slave:
Code: [Select]

#include <Wire.h>

const int SLAVE_ADR = 5;
const unsigned int NUMBER_OF_VALUES = 2;

union data_u
{
 unsigned int i[NUMBER_OF_VALUES];
 byte b[sizeof(i)];
};

data_u values;

void setup()
{
 Wire.begin(SLAVE_ADR);
 Wire.onRequest(requestEvent);

 values.i[0] = 123;
 values.i[1] = 45678;
}

void loop()
{
}

void requestEvent()
{
 Wire.write(values.b, sizeof(values.b));
}


Der Master fordert einfach das gesamte Array an und der Slave sendet das gesamte Array.

Die Union ist nötig weil man im Request Event Handler nur einmal write() machen kann. Also kann man ein Byte Array auf einmal senden. Auf dem Empfänger schreibt man auch in eine union und hat so direkt den Integer Wert.




______________________________________________________________________



Achtung: der I2C Puffer hat nur 32 Byte! Wenn man also wie hier innerhalb der Grenzen bleibt geht es so einfach (also 16 ints oder 8 longs/floats). Wenn man mehr auf einmal übertragen will, dann kann erst mal vom Master den Index des gesuchten Integers an den Slave senden und dann pro Request nur einen Integer übertragen


Das geht so:

Master:
Code: [Select]

#include <Wire.h>

const int SLAVE_ADR = 5;
const unsigned int NUMBER_OF_VALUES = 10;

union data_u
{
  unsigned int i;
  byte b[sizeof(i)];
};

data_u values[NUMBER_OF_VALUES];

void setup()
{
  Serial.begin(9600);
  Serial.println("Master");
  Wire.begin();

  getData();
}

void loop()
{
}

void getData()
{
  for (byte i = 0; i < NUMBER_OF_VALUES; i++)
  {
    Wire.beginTransmission(SLAVE_ADR);
    Wire.write(i);
    Wire.endTransmission();
    Wire.requestFrom(SLAVE_ADR, sizeof(values[0].i));

    for (byte j = 0; j < sizeof(values[0].i); j++)
      values[i].b[j] = Wire.read();
  }

  for (byte i = 0; i < NUMBER_OF_VALUES; i++)
    Serial.println(values[i].i);
}


Slave:
Code: [Select]

#include <Wire.h>

const int SLAVE_ADR = 5;
const unsigned int NUMBER_OF_VALUES = 10;

union data_u
{
  unsigned int i;
  byte b[sizeof(i)];
};

data_u values[NUMBER_OF_VALUES];
byte index;

void setup()
{
  values[0].i = 1;
  values[1].i = 4;
  values[2].i = 12;
  values[3].i = 45;
  values[4].i = 123;
  values[5].i = 456;
  values[6].i = 1234;
  values[7].i = 12345;
  values[8].i = 1000;
  values[9].i = 10000;
 
  Wire.begin(SLAVE_ADR);
  Wire.onRequest(requestEvent);
  Wire.onReceive(receiveEvent);
}

void loop()
{
}

void receiveEvent(int)
{
  index = Wire.read();
}

void requestEvent()
{
  Wire.write(values[index].b, sizeof(values[0].b));
}



Dabei beachten, dass die Datenstruktur etwas anders ist. Die Union hat nur einen Integer und man hat ein Array aus unions. Das macht die Sache mit dem Index leichter lesbar. Ansonsten müsste man den Index im Byte Array berechnen.

Der Master schickt erst den Index des Integers und fordert dann einen Integer an. Der Slave sendet alle Bytes dieses Integers.


Doc_Arduino

Hallo,

schönes Bsp.   Hat union einen Vorteil gegenüber struct oder ist das egal?


Tschau
Doc Arduino '\0'

Messschieber auslesen: http://forum.arduino.cc/index.php?topic=273445
EA-DOGM Display - Demos: http://forum.arduino.cc/index.php?topic=378279

agmue

#34
Feb 18, 2017, 09:15 pm Last Edit: Feb 18, 2017, 09:44 pm by agmue
Das ist wieder ein schlechtes Beispiel. Das ist für TinyWire, wo man mit send() wirklich nur ein Byte schicken kann.
Weil beide #include "Wire.h" enthalten, war mir das nicht aufgefallen :-[

Hat union einen Vorteil gegenüber struct oder ist das egal?
Mit meinen Worten erklärt: struct faßt verschiedene Variablen zusammen, während union einen Speicherbereich mit zwei Namen und Typen ansprechbar macht. Im Programm nutze ich die Variablen entsprechend ihrem Typ, für die Übertragung wird dann der Typ byte genutzt. Auf der anderen Seite dann umgekehrt.

struct kann ein Teil von union sein:

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


Ich mache mal ein aktuelles und korrektes Beispiel.
Beim ersten Master fehlen zwei Zeilen:
Code: [Select]
#include <Wire.h>
const int SLAVE_ADR = 5;
Die Vorstellungskraft ist wichtiger als Wissen, denn Wissen ist begrenzt. (Albert Einstein)

Doc_Arduino

Hallo,

ich hatte deshalb gefragt, weil meine RS485 Verbindung auf dem Code vom Nick Gammon aufbaut. Diese benutzt struct statt union.
In der Zwischenzeit habe ich nachgelesen. Dabei besteht mit union eine Gefahr des überschreiben der anderen Variablen innherhalb von union, falls man eine unerwartet ändert. So verstehe ich das. Stell ich mir aktuell so ähnlich vor als wenn man unkontrolliert im Speicher schreibt wenn man den Null-Terminator bei char arrays vergisst.
http://openbook.rheinwerk-verlag.de/c_von_a_bis_z/015_c_strukturen_009.htm#mj9e030e6d45f3619a80b6814a2ba14bea
Tschau
Doc Arduino '\0'

Messschieber auslesen: http://forum.arduino.cc/index.php?topic=273445
EA-DOGM Display - Demos: http://forum.arduino.cc/index.php?topic=378279

Serenifly

Dabei besteht mit union eine Gefahr des überschreiben der anderen Variablen innherhalb von union, falls man eine unerwartet ändert.
Das ist der ganze Sinn der Sache. Die Variablen belegen den gleichen Speicher! Man kann also eine Variable sowohl als Integer als auch als Byte Array ansprechen

schUk0

Also,

Der Vorschlag von Serenifly hat genau das gebracht was ich brauche.
Nach meinem Verständnis folgt das auch dem Vorschlag von Tommy56.

Und auf die 2 fehlenden Zeilen bin ich noch gerade so selbst gekommen. :D

Ist es eigentlich egal, wo man Funktionen im Code platziert?


Auf jeden Fall erstmal vielen Dank an alle die mitgeholfen haben.

Gruß

schUk0

Tommy56

Ist es eigentlich egal, wo man Funktionen im Code platziert?
In der ArduinoIde eigentlich jam da die die Deklarationszeilen oben einfügt. Manches Mal packt sie das aber nicht richtig.
Deshalb ist es nicht verkehrt, Funktionen vor ihrer Verwendung zu schreiben.

Gruß Tommy
"Wer den schnellen Erfolg sucht, sollte nicht programmieren, sondern Holz hacken." (Quelle unbekannt)

schUk0

Deshalb ist es nicht verkehrt, Funktionen vor ihrer Verwendung zu schreiben.

Scheint für mich auch sinnvoller aber man sieht in vielen Beispielen, dass sie nach dem Loop stehen.


Gruß

schUk0

agmue

Und auf die 2 fehlenden Zeilen bin ich noch gerade so selbst gekommen. :D
Manchmal habe ich den Eindruck, er macht das absichtlich gegen stumpfes Kopieren ohne Verstehen. Da würde er dann in der Tradition von da Vinci stehen :)
Die Vorstellungskraft ist wichtiger als Wissen, denn Wissen ist begrenzt. (Albert Einstein)

Doc_Arduino

Hallo,

@ schUk0:
Vorsicht, du verwechselst da was. Das eine ist der reine Code der Funktionen. Das andere ist die Funktionsdeklaration, also die Bekanntmachung für den Compiler das diese Funktion existiert. Genau das nimmt einem die IDE ab. Nur ganz ganz selten kann sie das nicht. Manchmal bei progmem, sind seltene Ausnahmen.

In der IDE sieht das normalerweise so aus.
Code: [Select]
void setup() {

}

void loop() {
  Testfunktion();
}


// *** ab hier eigene Funktionen *** //
void Testfunktion()
{

}



Normalerweise ist eine Deklaration der Funktionen notwendig,  was einem wie gesagt die IDE abnimmt.
Das würde außerhalb von der Arduino IDE Welt so aussehen.
Code: [Select]
// *** hier Funktionsdeklarationen *** //
void Testfunktion();


int main(void) // entspricht setup
{  
   
    while (1) // entspricht loop
    {  
Testfunktion();
    }
}


// *** ab hier eigene Funktionen *** //
void Testfunktion()
{

}


Kannste alles erstmal wieder vergessen. Nur das du es mal gesehen hast.
Tschau
Doc Arduino '\0'

Messschieber auslesen: http://forum.arduino.cc/index.php?topic=273445
EA-DOGM Display - Demos: http://forum.arduino.cc/index.php?topic=378279

Doc_Arduino

Das ist der ganze Sinn der Sache. Die Variablen belegen den gleichen Speicher! Man kann also eine Variable sowohl als Integer als auch als Byte Array ansprechen
Okay, man muss wie immer wissen was man tut.  :)
Tschau
Doc Arduino '\0'

Messschieber auslesen: http://forum.arduino.cc/index.php?topic=273445
EA-DOGM Display - Demos: http://forum.arduino.cc/index.php?topic=378279

Serenifly

Manchmal habe ich den Eindruck, er macht das absichtlich gegen stumpfes Kopieren ohne Verstehen.
Nein, das ist beim Kopieren passiert einfach so passiert :)

Aber wenigstens hat wurde mal mit gedacht. Viele Leute schaffen es nicht Demo-Code auf ihre eigenen Anforderungen anzupassen :(

schUk0

Nein, das ist beim Kopieren passiert einfach so passiert :)

Aber wenigstens hat wurde mal mit gedacht. Viele Leute schaffen es nicht Demo-Code auf ihre eigenen Anforderungen anzupassen :(
Naja... dass was fehlt sagt einem schon der Compiler.
Und damit es so geht, wie ich es brauchte musste schon noch ein bisschen was passieren.

Ich verstehe die Sache zwar noch nicht in ihrem kompletten Ausmaß, aber das kommt noch.
War bei allen anderen Teilstücken des Projekts auch so und das ist ja auch das tolle daran.
Was heute noch böhmische Dörfer sind, kann man morgen vielleicht schon im Handumdrehen.
Und dann kommt die nächste Hürde die man meistern muss und dabei lernt man dann auch wieder was dazu.

Gruß

schUk0


Go Up