Bräuchte einen Tipp... (master slave communication)

Moin,

ich bin gerade an einem recht einfachen Projekt dran (und bin noch ein blutiger Anfänger).
Ich will zwei Arduinos miteinander kommunizieren lassen und zwar wie folgt:

Arduino 1 hat auf seinem breadsheet ein LCD display und ein Voltmeter. Ich will die Spannung von Batterien messen. Das funktioniert soweit auch ziemlich gut. Nun will ich, wenn ein bestimmter Wert erreicht wird (z.B. 3,5 Volt) einen Befehl an den zweiten Arduino schicken, der dann, bei Erhalt des Befehls, einen DC Motor anwirft (über ein Relais, bei der Einführung ist das quasi die Lerneinheit 22).

Beide funktionieren einzeln gut, aber mir fehlt das know how für die Kommunikation zwischen den beiden Arduinos. Ich habe den Code mal angehängt, den ich verwende - vielleicht ist es ja ein ganz dummer Fehler. Ggf. hilft mir auch die Umwandlung von dem Wert meiner float Variablen in eine integer Variable (da meckert der Editor nämlich).

Viele Grüße!

Voltmeter_3_motor_master.ino (1.02 KB)

Voltmeter_3_motor_slave.ino (1.3 KB)

Nachtrag:
Einen Float-Wert musst du hier eigentlich nicht übertragen. Ein Byte für An oder Aus sollte reichen. Dazu muss man keine Verrenkungen anstellen.

Unten ist aber erklärt wie man beliebige Datentypen senden und empfangen kann
/edit

Da ist einiges an überflüssigem Code drin

Aber schau dir mal die Dokumentation zu Wire.read() und write() an! write() sendet entweder ein Byte oder ein Array aus Bytes. Da andere Datentypen zu übergeben ist unsinnig

Die Umwandlung von Float (oder anderen Datentypen) in ein Byte Array ist nicht sehr kompliziert. Es gibt zwei Optionen

1.) Eine Union aus einem Byte Array und einem Float:

union Data
{
  float asFloat;
  byte asBytes[sizeof(float)];
} data;

Dann kann man einfach in data.asFloat schreiben und das Array so senden:

Wire.write(data.asBytes, sizeof(data));

Und zum Auslesen mit einer for-Schleife in das Array schreiben. Die beiden Variablen belegen den gleichen Speicherbereich

2.) Zeiger auf andere Datentypen casten:

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

  float f = 9.09;
  byte* b = reinterpret_cast<byte*>(&f);

  for (byte i = 0; i < sizeof(float); i++)
     Serial.println(b[i]);

  f = *(reinterpret_cast<float*>(b));
  Serial.println(f);
}

Nimmt einfach die Adresse des Floats und castet diese auf einen Zeiger auf Byte. Array-Variablen entsprechen einem Zeiger auf das erste Element.

Zum Einlesen ein Array der Größe sizeof(float) anlegen. Dieses Array castet man auf eine Zeiger auf Float und dereferenziert diesen

Du könntest dir ja auch einfach mal einen der zahlreichen Beiträge im Web durchlesen.

Z.B. diesen hier und daraus lernen.

Und dann deinen Sketch hier direkt posten.
Setze den bitte in Code-Tags.

Verwende dazu die Schaltfläche </> oben links im Editorfenster.
Das kannst du auch nachträglich machen.
Dazu den Sketch markieren und die Schaltfläche klicken.

Damit wird dieser für alle besser lesbar.

HotSystems:
Z.B. diesen hier und daraus lernen.

Das ist insgesamt ziemlich gut und es erklärt wie man Bytes und wie man Arrays sendet. Multi-Byte Integer werden mal mit Bit-Schieben behandelt. Aber die Verbindung dazwischen, beliebige Datentypen wie Arrays zu verwenden, fehlt

Hier mal ein Beispiel, wie ein NodeMCU über I2C einen UNO/Nano steuern kann.

Gruß Tommy

Mhhh, wenn ich mir das nochmal genauer durchlese sehe ich dass der Code eigentlich nicht zur Problembeschreibung passt. In dem Code wird versucht einen Float-Wert zu senden. Das geht mit dem Code aus #1

Eigentlich braucht man das hier aber nicht. Das wäre angebracht z.B. wenn das LCD am Slave hängt. Aber hier kann man auch die Abfrage der Schaltschwelle auf dem Master erledigen und nur 0 = AUS und 1 = AN senden oder was ähnliches. Dann muss man nur ein Byte hin und schicken

Das ist richtig, aber oft erwächst aus einer Idee eine Erweiterung, die dann zusätzliche Anforderungen hat.

Gruß Tommy

Ob man jetzt ein Byte oder ein Byte-Array wie in #5 übertragen möchte ist egal. Das ist das gleiche Prinzip. Und beides wird von der Wire Library direkt unterstützt, da es beide Varianten von write() gibt

Komplizierter wird es erst bei beliebigen Variablen, da Wire das nicht von selbst erledigen kann.

Serenifly:
Komplizierter wird es erst bei beliebigen Variablen, da Wire das nicht von selbst erledigen kann.

Das stimmt. Da könnte man templates benutzen, muss aber die Daten evtl. teilen, wenn sie länger als der TWI-Buffer sind.
Das habe ich mal für einen FRAM gemacht.

Gruß Tommy

Ich finde, Wire wird total gerne unterschätzt.
:o :o

Hier mal ein Master Slave Päärchen aus meiner Wühlkiste.

#include <Streaming.h>
#include <Wire.h>

void setup() 
{
  Serial.begin(9600);
  Serial << "Start: "<< __FILE__ << endl;
  Wire.begin();
}

void loop() 
{
  if(Wire.requestFrom(2, 20))
  {
    int test = Wire.parseInt();
    Serial << "gelesen: " << test << endl; 
  }
}

#include <Streaming.h>
#include <Wire.h>

volatile int count;

void request()
{
  Wire << count++;
}

void setup() 
{
  Serial.begin(9600);
  Serial << "Start: "<< __FILE__ << endl;
  Wire.begin(2);
  Wire.onRequest(request);
}

void loop() 
{
}

Die Übertragung als Text hat 2 kleine Vorteile, man muss sich weder um Alignment noch um Enianness kümmern.

Benötigt man mehr Variationen, könnte man als Prolog ein Kommandobyte senden und erwarten.

Die Übertragung als Text hat 2 kleine Vorteile, man muss sich weder um Alignment noch um Enianness kümmern.

Wenn es aber wie hier um float geht, müsste man erstmal rauskriegen, wie man bei Streaming.h die Stellenzahl einstellt. :slight_smile:
Oder verwendet das Arduino.print ohne den Streaming-Zucker außen rum.
Oder man kriegt raus, dass man doch keine float-Zahl braucht.
Oder man will doch lieber binär übertragen und hofft prüft, dass die "Endianness" bei allen Arduinos gleich ist und

Wire.write((byte*) &myfloat, sizeof(float));

mit dem entsprechenden

float empfang;
byte * in =(byte*) &empfang;
wile (Wire.available()) *in++ = Wire.read();
Serial.print("Gelesen: ");
Serial.println(empfang,5); // kein Genauigkeitsverlust bei binärer Übertragung

zusammenspielt.

Hi

Zur aller größten Not schickt man eine 'Prüfsumme' hinterher, Die 2 größer als die Zahl ist.
Wenn der Schmarn nicht zusammen passt, vll. in der anderen Reihenfolge.
Dann muß man 'nur' drauf achten, daß nicht auf Einem der beiden Teilnehmer ein Überlauf die 'Prüfsumme' von Der des Anderen abweichen lässt.

MfG

Moin, ich danke für eure sehr hilfreichen Antworten. Ich konnte es nun mit einem byte-array lösen. Bei meinem nächsten posting werde ich auch den sketch dazu posten und erstmal vorher suchen. Freu mich auf jeden Fall grade wie hulle wieder was gelernt zu haben und dass es funktioniert! :slight_smile:

Grüße