Verständnisfrage „Schleife“

Einen wunderschönen guten Morgen euch allen.
Ich wundere mich derzeit über das was ich mir hier zusammengestrickt habe (siehe „code“ unten).

Warum wird immer nur die Letzte Slave-request aktualisiert?

Beispiel:

(die Slave’s übertragen beim Tastendruck eine „1“).

Wenn ich (mit dem unten gezeigtem code) beim „Slave-9“ den Taster für „L1“ drücke dann wird „L1“ nicht „aktualisiert“. Wenn ich wiederrum den Taster für „L1“ beim „Slave-12“ drücke dann wird auch eine „1“ übernommen.

Wenn ich jetzt im Code, den „Slave-9-codeschnipsel“ in der Schleifenabfolge unter
„Slave-12“ schreibe dann wird „Slave-9“ bearbeitet aber „Slave-12“ /10 dann wieder nicht.

Augenscheinlich wird immer nur der Letzte Slave in der Codeabfolge „Aktualisiert“ , sehe ich das richtig?

Ich habe hier anscheinend ein Verständnisproblem wie das ganze hier abläuft, geschweige denn wie ich dieses „Problem“ lösen kann

Ich danke euch ihr seid eine super Community.

Lieben Gruß


#include <Wire.h>

const byte slave80 = 80; 
const byte slave9 = 9;
const byte slave10 = 10;
const byte slave12 = 12;
 
byte L1 =0;
byte L2 =0;
byte L3 =0;
byte L4 =0;
byte L5 =0;
byte L6 =0;
byte L7 =0;
byte L8 =0;
byte L9 =0;
byte L10 =0;
byte L11 =0;
byte L12 =0;
byte L13 =0;
byte L14 =0;
byte L15 =0;
byte L16 =0;
byte L17 =0;
byte L18 =0;
byte L19 =0;
byte L20 =0;
byte L21 =0;


byte slave9ArrayData[4];
byte slave10ArrayData[4];
byte slave12ArrayData[4];



volatile byte Array_1[21]; 

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


void loop()
{

///////////////////////////////////Slave-9//////////////////////////////////////////////
mainSlaveRequest(slave9,slave9ArrayData);
L1= slave9ArrayData[0];
L2= slave9ArrayData[1];
L3= slave9ArrayData[2];
L4= slave9ArrayData[3];
///////////////////////////////////End Slave-9///////////////////////////////////////////
//
///////////////////////////////////Slave-10//////////////////////////////////////////////
mainSlaveRequest(slave10,slave10ArrayData);
L1= slave10ArrayData[0];
L2= slave10ArrayData[1];
L3= slave10ArrayData[2];
L4= slave10ArrayData[3];
///////////////////////////////////End Slave-10//////////////////////////////////////////
//
///////////////////////////////////Slave-12//////////////////////////////////////////////
mainSlaveRequest(slave12,slave12ArrayData);
L1= slave12ArrayData[0];
L2= slave12ArrayData[1];
L3= slave12ArrayData[2];
L4= slave12ArrayData[3];
///////////////////////////////////End Slave-12//////////////////////////////////////////


  Array_1[0] = L1;
  Array_1[1] = L2;
  Array_1[2] = L3;
  Array_1[3] = L4;
  Array_1[4] = L5; 
  Array_1[5] = L6;
  Array_1[6] = L7; 
  Array_1[7] = L8;
  Array_1[8] = L9; 
  Array_1[9] = L10;
  Array_1[10] = L11; 
  Array_1[11] = L12;
  Array_1[12] = L13;
  Array_1[13] = L14;
  Array_1[14] = L15; 
  Array_1[15] = L16;
  Array_1[16] = L17; 
  Array_1[17] = L18;
  Array_1[18] = L19; 
  Array_1[19] = L20;
  Array_1[20] = L21; 


Wire.beginTransmission(slave80);
Wire.write((byte*)Array_1,sizeof(Array_1));
Wire.endTransmission();



}


void mainSlaveRequest(const byte mainSlaveRequestAdress, byte mainSlaveRequestArray[4])
{
byte slaveArrayData[4];
    
Wire.requestFrom(mainSlaveRequestAdress, sizeof(slaveArrayData));
  byte* pte = (byte*)slaveArrayData;

  for (unsigned int re = 0; re < sizeof(slaveArrayData); re++)
  {
    *pte = Wire.read();
    pte++;
  }

  mainSlaveRequestArray[0]= slaveArrayData[0];
  mainSlaveRequestArray[1]= slaveArrayData[1];
  mainSlaveRequestArray[2]= slaveArrayData[2];
  mainSlaveRequestArray[3]= slaveArrayData[3];

}

AFAIK übergibst Du so eine Kopie des Arrays, im Hauptprogramm ändert sich nichts. Besser byte&.

Und Code bitte in Code Tags </> posten!

dein code ist kaum lesbar. Drück mal strg t in der IDE und poste den code noch mal in code Tags!(!!!).

Mir kommt vor du schreibst deine Ergebnisse immer wieder in die gleichen Variablen, kein Wunder dass dann nur der letzte Aufruf für dich über bleibt.

und wenn du sowas hinschreibst, dann muss dir ja eigentlich der Finger schon beim reintippen abfaulen...

byte L1 =0;
byte L2 =0;
byte L3 =0;
byte L4 =0;

Wozu gibt es Arrays?

oder sowas ist auch nicht wirklich besser:

const byte slave80 = 80;
const byte slave9 = 9;
const byte slave10 = 10;
const byte slave12 = 12;

ernsthaft? Kommt sicher gut wenn slave9 mal Adresse 10 und slave10 Adresse 80 bekomm.t

Deine Annahme ist falsch.
Du überschreibst den Inhalt.
Und der letzte Inhalt belibt dann zur Übergabe erhalten.

Oha...

Wie meinst du das genau ? :open_mouth:

Das ist wahr... ich weiß aber nicht besser wie ich es anders umsetzen kann.

lieben Gruß

Erklär doch mal mit ner Handvoll Worte.
Ich sehe irgendwie L1 bis L21, aber nur L1-L4 benutzt.
Wenn da was kommentiert wäre oder die Variablen "sprechende" Namen, könnte man sich da was zusammenreimen....

"L" soll für LED stehen die dann auf einem MEGA2560 (Slave80) aktiviert wird.
Und später sollen dann die anderen "LED / L1....L21" implementiert werden (mit noch 30 weiteren Slaves).

Der Master soll quasi die Signale weiterleiten.

Danke dir :slight_smile:

Das habe ich mir fast schon so gedacht. Wie behebe ich das am besten?
Und ich dachte, dass mein Vorgehen so legitim und augenscheinlich einfach funktioniert.
:sweat_smile:

Kannst Du mal den hier laufen lassen?
Der soll einen Slave abfragen und die abgefragten Infos an den Master senden.
Dann 2 Sekunden Pause, damit Du auf dem Master auch was siehst und den nächsten Slave etc...
Kontrollausgabe auf dem Seriellen Monitor.

#include <Wire.h>

constexpr byte master {80};
constexpr byte slaveNums {3};
constexpr byte slave[slaveNums] {9, 10, 12};
byte slaveData[4];

void setup()
{
  Wire.begin();
  Serial.begin(9600);
  Serial.println(F("Start..."));
}


void loop()
{
  for (byte b = 0; b < slaveNums; b++)
  {
    mainSlaveRequest(slave[b]);
    printDebugData(slave[b]);
    setMasterData(master);
    delay(2000);
  }
}

void mainSlaveRequest(const byte mainSlaveRequestAdress)
{
  Wire.requestFrom(mainSlaveRequestAdress, sizeof(slaveData));
  byte *pte = (byte *)slaveData;
  for (unsigned int re = 0; re < sizeof(slaveData); re++)
  {
    *pte = Wire.read();
    pte++;
  }
}
void setMasterData(const byte masterAdress)
{
  Wire.beginTransmission(masterAdress);
  Wire.write((byte *)slaveData, sizeof(slaveData));
  Wire.endTransmission();
}
void printDebugData(const byte slaveNumber)
{
  Serial.print(F("Daten von Slave: "));
  Serial.println(slaveNumber);
  for (byte b = 0; b < sizeof(slaveData); b++)
  {
    Serial.print(slaveData[b]);
    Serial.print(' ');
  }
  Serial.println();
}

Ich auch!
So viele durchnummerierte Variablen habe ich wohl noch nie gesehen.
Das solltest du evtl. überarbeiten.

Zugegeben:
Mir fehlt völlig der Überblick.

Wieviel cm Kabel kommen da zusammen, für den I2C Bus?
Auf 20cm passt das wohl nicht....

Oha… das ging ja schnell, jetzt gucke ich mir das mal an und versuche zu verstehen was da so abläuft.

Richtig Testen kann ich leider erst morgen ab 19 Uhr, da habe ich wieder Zeit dafür.

Aber so wie ich das auf den ersten Blicke sehe fragst du in der „for“ alles Adressen nacheinander ab.
Das ist ja cool!!! (bestimmt sind das „basics“).

Wenn die „for“ die Bedingung 3 erreicht ist Schluss richtig oder fängt die dann von vorne an ?

danke dir :slight_smile:

https://en.cppreference.com/w/cpp/keyword/for

Gibt's sogar speziell für Arduino:

for - Arduino Reference

Obwohl man so früh wie möglich wissen sollte, dass das alles von einem richtigen C++ Compiler verarbeitet wird. Und deshalb deutlich mehr geht, als die Arduino Referenz erwähnt.

Allerdings!
Das kann ich nur ausdrücklich bestätigen.
z.B. fehlt der Arduino Doku der, aus meiner Sicht, wichtige/elegante "range based for loop"

Von daher würde ich sagen:

Gibts sogar abgespeckt/verstümmelt für Arduino User

Ansonsten gibts ja auch noch endlos viele C++ Bücher und Tutorials (in wechselhafter Qualität)

Nachtrag: (aus der Arduino Doku)

int x = 1;
for (int i = 0; i > -1; i = i + x) 

Ganz böse! Ganz böse!
Da wird auf einen int Überlauf gewartet, welcher ein undefiniertes Verhalten verursacht. Das ist der Todesstoß für das ganze Programm.
Der Schreiber des Tutorials hat sich damit 6 Monate Urlaub auf einer Streckbank seiner Wahl verdient.

E:\Programme\arduino\portable\sketchbook\sketch_nov30d\sketch_nov30d.ino: In function 'setup':
E:\Programme\arduino\portable\sketchbook\sketch_nov30d\sketch_nov30d.ino:11:29: warning: iteration 32767 invokes undefined behavior [-Waggressive-loop-optimizations]
   11 |   for (int i = 0; i > -1; i = i + x) ;
      |                           ~~^~~~~~~
E:\Programme\arduino\portable\sketchbook\sketch_nov30d\sketch_nov30d.ino:11:21: note: within this loop
   11 |   for (int i = 0; i > -1; i = i + x) ;
      |                   ~~^~~~

Das ist einer der gruseligsten Stellen in der Arduino Doku.

Ja, ich weiß, das funktioniert so, wie es da steht (der Überlauf wird abgefangen), aber eine gute Idee ist das nicht.....

"undefiniertes Verhalten" kann man aus Spaß aber gerne mal ausprobieren.
Ist was anderes als z.B. Vin mit 24V zu beschicken.

Man kann trefflich diskutieren, dass es einem nix nutzt, wenn man weiß, was bei undefiniertem Verhalten tatsächlich passiert. (Weil der Compiler frei ist, in der nächsten Version was anderes zu machen und z.B. zu meckern)

Da stimme ich dir schon zu, aber ein pädagogisches Konzept, erstmal nur Teile der Wahrheit zu erzählen, ist durchaus gebräuchlich. Und dass die Arduino Doku nun mal da ist, sollte jemand, der eine Verständnisfrage „Schleife“ stellt, mindestens auch wissen

Das ist gut - da kann ich mich evtl. wieder mit dran beteiligen. Vorausgesetzt der Netbook ist aufgeladen :wink:

Bis dahin lektüre downloaden: ArduinoForum.de - Das deutschsprachige Forum rund um den Arduino - Arduino Code-Referenz (deutsch)
Und anfangen zu lesen. Wichtig: Vorne ist der Anfang. Ohne den wird das nix.

Man liest sich.

Danke für die Unterstützung.
Lesen ist klar … aber probieren möchte ich auch, ich muss sowas dann auch immer gleich sehen… :sweat_smile:

Naja..
Ich halte die Arduino Doku für sehr nützlich, für die Dinge, welche Arduino mit bringt.

Für die Sprache, ist die Sprachdoku das Maß der Dinge.
Für die einzelnen µC, oder Bausteine, das jeweilige Datenblatt.

Die Arduino Doku mixt das etwas zu dolle für meinen Geschmack.
Da ist von "Arduino Sprache" die Rede.
Dort werden Macros bei den Funktionen eingeordnet.
und vieles weitere

Ja dem ist so.
Aber auch hier schießt die Arduino Doku manchmal drüber hinaus, und verbreitet Falschinformation.
Das ist für mich ganz was anderes, als Information in Häppchen aufzuteilen.

Da habe ich volles Verständnis für!

z.B. ein Kapitel im Buch lesen, und solange damit testen, spielen und modifizieren, bis man das Thema (möglichst vollständig) begriffen hat.
Dann zum nächsten Thema,......

Da möchte ich nicht wissen, was du zu @my_xy_projekt s Link in #17 sagst. Immerhin wird da schon im Vorwort auf S.3 verraten, dass als "Arduino-Sprache" auch alle sonstigen C/C++ Befehle benutzt werden können. Ist auf jeden Fall sehr Arduino-spezifisch und keine reine Übersetzung der Arduino Referenz, die es übrigens auch auf deutsch gibt.