Kommunikation zwischen 2 Arduinos

Hallo zusammen,
habe jetzt die letzte Zeit nicht weiter machen können an dem Projekt. Habe aber den Sketch mittlerweile ziemlich start reduziert und einen Punkt gefunden, der den Fehler verursacht. Wäre super, wenn ihr mir sagen könntet, warum das so ist :slight_smile:

Folgendes Problem: Slave1 schickt Sensorwerte an den Master in der folgenden Zeichenkette: "master,temperatur-station-X,yy" (also Ziel,Station und Temp.wert). Der Master liest die Nachricht ein, aber nur wenn in der Nachricht "master" vorne steht. Er schaut sich die Temperatur z.B. für Station 2 an und sagt, welchen Zustand (0,1 oder 2) die LED am Slave1 haben soll -> Dies geschieht über die Nachricht: "slave1,LEDx,y". Der Slave1 liest nochmal ein, aber nur wenn "slave1" vorne in der Nachricht steht. Bei Zustand 0 geht nur blau an, bei 1 gehen beide an und bei 2 geht nur rot an. Funktioniert wunderbar!

Jetzt muss ich allerdings noch einen 2. Slave ansteuern können vom Master aus. Also schreibe ich eine 2. Textnachricht vom Master raus in der Form: "slave2,TSx,Zustandy". Sobald ich diese Nachricht in den Sketch aufnehme, funktioniert die LED Regelung am Slave1 nicht mehr. Die LED geht am Anfang einmal an, ändert aber dann nicht mehr ihren Zustand, egal welcher Temperaturwert. Der Richtungsaustausch Slave1 -> Master (mit LED-Anzeige) funktioniert aber dann noch.

Habt ihr dazu eine Erklärung??

Slave1:

#include <INTERVAL.h>

// #################Initialisierung von Temperatur-Sensor 2 - MLX90615 #################
#include <MLX90615.h>       // Library für Temp-Sensor "MLX90615"
#include <I2cMaster.h>     // Library für Temp-Sensor "MLX90615"
#define SDA_PIN A0   //define the SDA pin
#define SCL_PIN A1   //define the SCL pin
SoftI2cMaster i2c(SDA_PIN, SCL_PIN);
MLX90615 mlx90615(DEVICE_ADDR, &i2c);     // Sensor-Objekt "mlx90615" erstellen aus Klasse MLX90615

//-------------------------- Messung für Temp.sensor 2----------------------------------
unsigned long interval_Messung_T2 = 2000;    // Interval zwischen zwei Messungen(T2)

int led_rot_2 = 7;
int led_blau_2 = 5;

//Ausgangswerte für SerialEvent-Funktion
String inputString = "";         // a string to hold incoming data
boolean stringComplete = false;  // whether the string is complete


void setup() {
  
  pinMode(7, OUTPUT);      //Pin 7 als OUTPUT-Pin definieren
  pinMode(2, OUTPUT);      //Pin 2 als OUTPUT-Pin definieren
  Serial.begin(9600);
  inputString.reserve(200);   // Länge für eingehenden String definieren
}


void loop() {

  // ######## MESSUNG SENSOR 2 - mlx90615 ##################

  INTERVAL(interval_Messung_T2)
  {
    char buf2[100];
    int wert_mlx90615 = mlx90615.getTemperature(MLX90615_AMBIENT_TEMPERATURE);
    sprintf(buf2, "master,temperatur-station-2,%d", wert_mlx90615);

    Serial.println(buf2);
    delay(200);     //Zeit zwischen Übertragung T2 und T3 -> kein Einfluss auf Intervall, solange kleiner T(Intervall)

  }


  if (stringComplete) {                       // print the string when a newline arrives:

    String ziel = getValue(inputString, ',', 0);

    if (ziel == "slave1")
    {
      String LEDkennung = getValue(inputString, ',', 1);
      String LED_zustand = getValue(inputString, ',', 2);
      int LED_zustand_zahl = LED_zustand.toInt();


      //Reglung LED 2
      if (LEDkennung == "LED2")
      {
        if (LED_zustand_zahl == 0)
        {
          digitalWrite(led_blau_2, HIGH);   // blau an
          digitalWrite(led_rot_2, LOW);   // rot aus
        }
        else if (LED_zustand_zahl == 1)
        {
          digitalWrite(led_blau_2, HIGH);   // blau an
          digitalWrite(led_rot_2, HIGH);   // rot an
        }
        else if (LED_zustand_zahl == 2)
        {
          digitalWrite(led_rot_2, HIGH);   // rot an
          digitalWrite(led_blau_2, LOW);   // blau aus

        }

      }

      delay(100);

      inputString = "";    // clear the string:
      stringComplete = false;


    }
  }


}


void serialEvent() {
  while (Serial.available()) {
    char inChar = (char)Serial.read();
    inputString += inChar;
    if (inChar == '\n') {
      stringComplete = true;
    }
  }
}


String getValue(String data, char separator, int index)
{
  int found = 0;
  int strIndex[] = { 0, -1  };
  int maxIndex = data.length() - 1;
  for (int i = 0; i <= maxIndex && found <= index; i++) {
    if (data.charAt(i) == separator || i == maxIndex) {
      found++;
      strIndex[0] = strIndex[1] + 1;
      strIndex[1] = (i == maxIndex) ? i + 1 : i;
    }
  }
  return found > index ? data.substring(strIndex[0], strIndex[1]) : "";
}

Master:

#include <LiquidCrystal.h>
LiquidCrystal lcd(12, 11, 5, 4, 3, 2);

String inputString = "";         // a string to hold incoming data
boolean stringComplete = false;  // whether the string is complete

// --------------------------Temperaturbereiche für Temp.sensor 2--------------------------
int temp_grenze_T2_1 = 30;
int temp_grenze_T2_2 = 35;


void setup() {

  lcd.begin(16, 2);
  lcd.clear();

  Serial.begin(9600);
  inputString.reserve(200);
}


void loop() {

  if (stringComplete) {                       // print the string when a newline arrives:
    //delay(500);

    String ziel = getValue(inputString, ',', 0);

    if (ziel == "master")
    {
      String sensorkennung = getValue(inputString, ',', 1);
      String slave1_temp = getValue(inputString, ',', 2);
      int slave1_temp_zahl = slave1_temp.toInt();


      //Prüfen Temperaturstation 2
      if (sensorkennung == "temperatur-station-2")
      {
        // Anzeige der Temperatur 1 an LCD
        lcd.setCursor(9, 0);
        lcd.print("2: ");
        lcd.print(slave1_temp_zahl);
        lcd.print("'C");

        if (slave1_temp_zahl < temp_grenze_T2_1)
        {
          Serial.println("slave1,LED2,0");    //0 bedeutet, dass nur blau leuchtet
          delay(200);
          //Serial.println("slave2,TS2,zustand0");    //PROBLEM !!!!!!!!!!!!!!!!!!!!!!!
        }
        else if (slave1_temp_zahl >= temp_grenze_T2_1 and slave1_temp_zahl < temp_grenze_T2_2)
        {
          Serial.println("slave1,LED2,1");    //1 bedeutet, dass blau und rot leuchtet
          delay(200);
          //Serial.println("slave2,TS2,zustand1");   //PROBLEM !!!!!!!!!!!!!!!!!!!!!!!
        }
        else if (slave1_temp_zahl >= temp_grenze_T2_2)
        {
          Serial.println("slave1,LED2,2");    //2 bedeutet, dass nur rot leuchtet
          delay(200);
          //Serial.println("slave2,TS2,zustand2");    //PROBLEM !!!!!!!!!!!!!!!!!!!!!!!
        }
      }

      delay(100);

      inputString = "";    // clear the string:
      stringComplete = false;


    }
  }

}


void serialEvent() {
  while (Serial.available()) {
    char inChar = (char)Serial.read();
    inputString += inChar;
    if (inChar == '\n') {
      stringComplete = true;
      delay(50);
    }
  }
}


String getValue(String data, char separator, int index)
{
  int found = 0;
  int strIndex[] = { 0, -1  };
  int maxIndex = data.length() - 1;
  for (int i = 0; i <= maxIndex && found <= index; i++) {
    if (data.charAt(i) == separator || i == maxIndex) {
      found++;
      strIndex[0] = strIndex[1] + 1;
      strIndex[1] = (i == maxIndex) ? i + 1 : i;
    }
  }
  return found > index ? data.substring(strIndex[0], strIndex[1]) : "";
}

mach beim slave1 debug Ausgaben rein und finde raus, wie er auf die Nachricht reagiert.

bleibt das Verhalten identisch, wenn du die Hardware der Slaves gegeneinander austauschst?

Wie machst du die Kommunikation untder den dreien untereinander Hast du am Master "zwei Slaves" an der seriellen Schnittstelle?
Vom Grund Prinzip lässt sich das alles schon z.B. mit dies er LIB. Diese ist zwar für RS485 hat aber auch ein klein wenig Sichherheit drin.
Du brauchst ja auch nicht einen String mit floats Zahlen drin und "klartexte" wenn du fests Strukturen hast kannst du deine zu übertragenden Daten an die Reichtige stelle im struct schreiben und diese dann auf der Slave Seite auswerten.

aus dem Beispiel:
Du kannst auch floats in das struct reinpacken dann werden die 4Bytes des Floats "automatisch" übertragen und im Empfangsstruct steckt da dann auch ein float drin.

struct
  {
  byte address;
  byte switches [10];
  int  status;
  }  message;

Evtl auch ein paar Ansätze hier meinem RS485 Thread:
Hier geht es auch um austschausch von Daten die für den bestimmten Slave sind/ geht auch in die Master Richtung.
Gruß
DerDani

Teste mal den Code :

#include <INTERVAL.h>

// #################Initialisierung von Temperatur-Sensor 2 - MLX90615 #################
#include <MLX90615.h>       // Library für Temp-Sensor "MLX90615"
#include <I2cMaster.h>     // Library für Temp-Sensor "MLX90615"
#define SDA_PIN A0   //define the SDA pin
#define SCL_PIN A1   //define the SCL pin
SoftI2cMaster i2c(SDA_PIN, SCL_PIN);
MLX90615 mlx90615(DEVICE_ADDR, &i2c);     // Sensor-Objekt "mlx90615" erstellen aus Klasse MLX90615

//-------------------------- Messung für Temp.sensor 2----------------------------------
unsigned long interval_Messung_T2 = 2000;    // Interval zwischen zwei Messungen(T2)

int led_rot_2 = 7;
int led_blau_2 = 5;

//Ausgangswerte für SerialEvent-Funktion
String inputString = "";         // a string to hold incoming data
boolean stringComplete = false;  // whether the string is complete


void setup() {
 
  pinMode(9, OUTPUT);      //Pin 7 als OUTPUT-Pin definieren
  pinMode(2, OUTPUT);      //Pin 2 als OUTPUT-Pin definieren
  Serial.begin(9600);
  inputString.reserve(200);   // Länge für eingehenden String definieren
}


void loop() {

  // ######## MESSUNG SENSOR 2 - mlx90615 ##################

  INTERVAL(interval_Messung_T2)
  {
    char buf2[100];
    int wert_mlx90615 = mlx90615.getTemperature(MLX90615_AMBIENT_TEMPERATURE);
 //   int wert_mlx90615 = random(30);
    sprintf(buf2, "master,temperatur-station-2,%d", wert_mlx90615);

    Serial.println(buf2);
 //   delay(200);     //Zeit zwischen Übertragung T2 und T3 -> kein Einfluss auf Intervall, solange kleiner T(Intervall)

  }


  if (stringComplete) {                       // print the string when a newline arrives:
    String ziel = getValue(inputString, ',', 0);
    // inputString="";
    if (ziel == "slave1")
    {
      String LEDkennung = getValue(inputString, ',', 1);
      String LED_zustand = getValue(inputString, ',', 2);
      int LED_zustand_zahl = LED_zustand.toInt();


      //Reglung LED 2
      if (LEDkennung == "LED2")
      {
        Serial.print("LED: ");
        Serial.println(LED_zustand_zahl);
        
        if (LED_zustand_zahl == 0)
        {
          digitalWrite(led_blau_2, HIGH);   // blau an
          digitalWrite(led_rot_2, LOW);   // rot aus
        }
        else if (LED_zustand_zahl == 1)
        {
          digitalWrite(led_blau_2, HIGH);   // blau an
          digitalWrite(led_rot_2, HIGH);   // rot an
        }
        else if (LED_zustand_zahl == 2)
        {
          digitalWrite(led_rot_2, HIGH);   // rot an
          digitalWrite(led_blau_2, LOW);   // blau aus

        }

      }

    //  delay(100);



    }
      inputString = "";    // clear the string:
      stringComplete = false;
    
  }


}


void serialEvent() {
  while (Serial.available()) {
    char inChar = (char)Serial.read();
    inputString += inChar;
    if (inChar == '\n') {
      stringComplete = true;
      Serial.println(inputString);
      
    }
  }
}


String getValue(String data, char separator, int index)
{
  int found = 0;
  int strIndex[] = { 0, -1  };
  int maxIndex = data.length() - 1;
  for (int i = 0; i <= maxIndex && found <= index; i++) {
    if (data.charAt(i) == separator || i == maxIndex) {
      found++;
      strIndex[0] = strIndex[1] + 1;
      strIndex[1] = (i == maxIndex) ? i + 1 : i;
    }
  }
  return found > index ? data.substring(strIndex[0], strIndex[1]) : "";
}

Habt ihr dazu eine Erklärung??

inputString wurde nur innerhalb der if zurückgesetzt. Muss aber IMMER nach erfolgter (auch erfolgloser) Auswertung zurückgesetzt werden.