Bidirektionale Kommunikation mit nRF24L01+ und Mirf.h

Hallo zusammen,

ich stehe momentan wieder vor einer Herausforderung.

Momentaner Stand ist, dass ein Arduino Nano Befehle über einen nRF24L01 an einen Arduino Mega versendet. Dies funktioniert soweit.

Ich würde es nun begrüßen, wenn der Arduino Mega dies quittiert und auch selbstständig Informationen zurücksenden kann.

Soweit mir bekannt ist, ist ein Mischbetrieb möglich, stimmt das? (Bidirektional)

Meine Versuche bisher:

Sketch Auszug Mega:

 Mirf.setRADDR((byte *)"ardu01"); //Zuweisung eines Namen

  //####################################
  Mirf.setTADDR((byte *)"sender");
if (Mirf.dataReady()) {          //Wenn das Funkmodul bereit ist
    while (!Mirf.rxFifoEmpty()) {
      Mirf.getData((byte *) &mirfdata);   //Empfange die Funkdaten
    }
    if (mirfdata[0] != 0 && mirfdata != 0) {  //Wenn etwas empfangen wurde
      Serial.print("Folgendes empfangen: ");
      Serial.println(mirfdata);
      strcpy(eingabe, mirfdata);      //Kopiere den Wert aus den Empfangenen Zeichenketten in die Eingabe

      if (strcmp(eingabe, "reset") == 0) {    //strcmp = String-Compare = Überprüfe ob Eingabe dem Wert entspricht
        Serial2.println("LF");
        digitalWrite(fehler, HIGH);
        delay(100);
        digitalWrite(fehler, LOW);
        Endposition = true;
        Serial.println("RESET-----RESET-----RESET");

        //###################################################
        while( Mirf.isSending() ) ;
        Mirf.send("RESET durchgeführt");
        Serial.println("ACK versendet");
        //###################################################

Sketch Auszug Nano:

  Mirf.setTADDR((byte *)"ardu01"); // Name des Empfängers. 5 Zeichen!
  //####################################
  Mirf.setRADDR((byte *)"sender");
  //####################################
void loop() {
  while( Mirf.isSending() ) ;

  if (datenEinlesen(Serial, uewert, sizeof(uewert), serialIndex)== true){
    Mirf.send(uewert);
    Serial.print(uewert);
    Serial.println(" versendet");
  }
//###################################################################################
if (Mirf.dataReady()) {          //Wenn das Funkmodul bereit ist
    while (!Mirf.rxFifoEmpty()) {
      Mirf.getData((byte *) &mirfdata);   //Empfange die Funkdaten
    }
    if (mirfdata[0] != 0 && mirfdata != 0) {  //Wenn etwas empfangen wurde
      Serial.print("Folgendes empfangen: ");
      Serial.println(mirfdata);
    }
  
  }}

Mit der Library "mirf.h" habe ich bisher noch nicht gearbeitet, die Beispiele der Lib zeigen mir aber, das die bidirektionale Funktion möglich ist. Da mir die Erfahrung hier fehlt, kann ich auch keine weiteren Tipps geben.

Allerdings solltest du, um evtl. Fehler zu erkennen, deine kompletten Sketch posten.
Dann sind auch Zusammenhänge besser sichtbar.

Ok hier einmal die kompletten Sketche:

Mikrocontroller Verarbeitung:

 #include <SPI.h>
#include <Mirf.h>
#include <nRF24L01.h>
#include <MirfHardwareSpiDriver.h>



int start = 47;
int fehler = 46;
int distanz1 = 45;
int distanz2 = 44;
int distanz3 = 43;
int distanz4 = 42;
int distanz5 = 41;
int distanz6 = 40;

char eingabe[12];
char messwert[12];
char mirfdata[16];

float halteposition;
float arbeitswert;

byte serialIndex = 0;
byte serial2Index = 0;


boolean Endposition = true;

void setup() {
  /*Der nachfolgende Code wird einmalig ausgeführt,
  er dient der Initialisierung der beteiligten Schnittstellen. */
  
  Serial.begin(9600); //Serielle Schnittstelle des USB-Controller
  Serial2.begin(9600);  //Serielle Hardwarescchnittstelle zur Kommunikation Laser
 
  pinMode(start, OUTPUT);   //Zuweisung der Digitalschnittstelle
  pinMode(fehler, OUTPUT);
  pinMode(distanz1, OUTPUT);
  pinMode(distanz2, OUTPUT);
  pinMode(distanz3, OUTPUT);
  pinMode(distanz4, OUTPUT);
  pinMode(distanz5, OUTPUT);
  pinMode(distanz6, OUTPUT);

  Mirf.cePin  = 53;  // CE des Funkmodul ist am PIN D9 angeschlossen
  Mirf.csnPin = 48; // ...und der CSN-Pin beim Arduino an D10
  Mirf.spi = &MirfHardwareSpi;
  Mirf.init();
  Mirf.payload = 16;    //Größe der Übertragung
  Mirf.channel = 115;   //Kanal 115
  Mirf.config();
  Mirf.configRegister(RF_SETUP, 0x06);
  Mirf.setRADDR((byte *)"ardu01"); //Zuweisung eines Namen
  
  Serial.println("Setup abgeschlossen! Warte auf Funkbefehle!");
}




boolean datenEinlesen(Stream& serialtype, char* buffer, byte bufferSize, byte& index) {
  /* Funktion zum Einlesen der Daten über eine Schnittstelle, die über den Funktionsaufruf
    an die Funktion übergeben werden kann*/
  char c;
  if (serialtype.available() == 0) return false;  //wenn die serielle Schnittstelle nicht aktiv ist, melde Fehler
  if (index == 0) memset(buffer, 0, bufferSize);
  c = serialtype.read();
  if (c == 13) {                  //Wenn der Carriage Return (Abschlusssymbol) empfangen wurde
    buffer[index] = '\0';             //Füge ans Ende der empfangenen Kette eine 0
    index = 0;
    return true;
  } else if (c >= 32 && index < bufferSize - 1) {   //Zähle die Zeichen zur Kette hinzu
    buffer[index] = c;
    index++;
  } else ;
  return false;
}


void loop() {
  
 if (Mirf.dataReady()) {          //Wenn das Funkmodul bereit ist
    while (!Mirf.rxFifoEmpty()) {
      Mirf.getData((byte *) &mirfdata);   //Empfange die Funkdaten
    }
    if (mirfdata[0] != 0 && mirfdata != 0) {  //Wenn etwas empfangen wurde
      Serial.print("Folgendes empfangen: ");
      Serial.println(mirfdata);
      strcpy(eingabe, mirfdata);      //Kopiere den Wert aus den Empfangenen Zeichenketten in die Eingabe

      if (strcmp(eingabe, "reset") == 0) {    //strcmp = String-Compare = Überprüfe ob Eingabe dem Wert entspricht
        Serial2.println("LF");
        digitalWrite(fehler, HIGH);
        delay(100);
        digitalWrite(fehler, LOW);
        Endposition = true;
        Serial.println("RESET-----RESET-----RESET");
      } else if (strcmp(eingabe, "x") == 0) {   //strcmp = String-Compare = Überprüfe ob Eingabe dem Wert entspricht
        Endposition = true;
        digitalWrite(start, LOW);
        digitalWrite(fehler, LOW);
        digitalWrite(distanz1, LOW);   
        digitalWrite(distanz2, LOW);   
        digitalWrite(distanz3, LOW);       
        digitalWrite(distanz4, LOW);
        digitalWrite(distanz5, LOW);
        digitalWrite(distanz6, LOW);
        
        Serial.println("PC-Konnektivität hergestellt");
      } else if (strcmp(eingabe, "licht") == 0) {   //strcmp = String-Compare = Überprüfe ob Eingabe dem Wert entspricht
        Endposition = true;
        Serial.println("Lichttest");
        digitalWrite(start, HIGH);
        delay(100);
        digitalWrite(fehler, HIGH);
        delay(100);
        digitalWrite(distanz1, HIGH);
        delay(100);
        digitalWrite(distanz2, HIGH);
        delay(100);
        digitalWrite(distanz3, HIGH);
        delay(100);
        digitalWrite(distanz4, HIGH);
        delay(100);
        digitalWrite(distanz5, HIGH);
        delay(100);
        digitalWrite(distanz6, HIGH);
        delay(100);
        digitalWrite(start, LOW);
        delay(100);
        digitalWrite(fehler, LOW);
        delay(100);
        digitalWrite(distanz1, LOW);
        delay(100);
        digitalWrite(distanz2, LOW);
        delay(100);
        digitalWrite(distanz3, LOW);
        delay(100);
        digitalWrite(distanz4, LOW);
        delay(100);
        digitalWrite(distanz5, LOW);
        delay(100);
        digitalWrite(distanz6, LOW);
        delay(100);
      } else if (strcmp(eingabe, "start") == 0) {   //strcmp = String-Compare = Überprüfe ob Eingabe dem Wert entspricht
        Serial2.println("DW");              //DW ist das Startkommando für den Laser um eine kontinuierliche Messung zu starten
        Serial.println("Laser aktiv, warte auf Zielwert");
      } else {
        Endposition = false;
        halteposition = atof(eingabe);
      }
    }
 }
  

  if (Endposition == false) {           //Wenn die Endposition noch nicht erreicht wurde, dann
    if ((datenEinlesen(Serial2, messwert, sizeof(eingabe), serial2Index)) == true)  {   //Empfange den Wert, denn der Sensor ausgibt

      arbeitswert = atof(messwert);   //Wandle den messwert in die Gleitkommazahl arbeitswert

      //Serial.print("Halteposition ist ");
      //Serial.println(halteposition);
      Serial.print("Arbeitswert ist ");
      Serial.println(arbeitswert);

    
    //Definition der Abstände
      float abstand1 = 2;   
      float abstand2 = 1.5;
      float abstand3 = 1;
      float abstand4 = 0.5;
      float abstand5 = 0.2;
      float abstand6 = 0.1;

      //##########################################################################
    //Überprüfung der Abstände:

      if (arbeitswert >= (halteposition + abstand2) and (arbeitswert <= halteposition + abstand1)) {
        digitalWrite(distanz1, HIGH);
        //Serial.println("DISTANZ ZWISCHEN X+2 UND X+1.5 METER");
      } else if (arbeitswert < (halteposition + abstand2) and (arbeitswert >= (halteposition + abstand3))) {
        digitalWrite(distanz2, HIGH);
        //Serial.println("DISTANZ ZWISCHEN X+1.5 und X+1 METER");
      } else if (arbeitswert < (halteposition + abstand3) and (arbeitswert >= (halteposition + abstand4))) {
        digitalWrite(distanz3, HIGH);
        //Serial.println("DISTANZ ZWISCHEN X+1 und X+0.5 METER");
      } else if (arbeitswert < (halteposition + abstand4) and (arbeitswert >= (halteposition + abstand5))) {
        digitalWrite(distanz4, HIGH);
        //Serial.println("DISTANZ ZWISCHEN X+0.5 und X+0.2 METER");
      } else if (arbeitswert < (halteposition + abstand5) and (arbeitswert >= (halteposition + abstand6))) {
        digitalWrite(distanz5, HIGH);
        //Serial.println("DISTANZ ZWISCHEN X+0.2 und X+0.1 METER");
      } else if (arbeitswert < (halteposition + abstand6)) {
        digitalWrite(distanz6, HIGH);
        //Serial.println("DISTANZ UNTER X+0.1 METER");
      } else {
        digitalWrite(start, LOW);
        digitalWrite(fehler, LOW);
        digitalWrite(distanz6, LOW);
        digitalWrite(distanz5, LOW);
        digitalWrite(distanz4, LOW);
        digitalWrite(distanz3, LOW);
        digitalWrite(distanz2, LOW);
        digitalWrite(distanz1, LOW);

      }
   

        if (arbeitswert == halteposition) {   //Wenn die Halteposition dem aktuellen Wert entspricht, dann
          digitalWrite(start, HIGH);
          Serial.println("Zug steht");
         
            Serial.println(arbeitswert);
            delay(50);
            if (arbeitswert == halteposition) {
              Serial.println(" m Abschlussposition");
              Endposition = true;       //... beende den Einmessvorgang
            }
          }
        }
      
  }

  

}

Mikrocontroller Sender:

#include <Mirf.h>
#include <MirfHardwareSpiDriver.h>

char uewert[12];
byte serialIndex;
int x=0;

void setup() {
  Serial.begin(9600);
  // RF24/Mirf initalisieren
  Mirf.cePin  = 9;  // Sollte der CE-Pin  (3) an einem anderen Arduino-Port angeschlossen werden müssen (8: Standard)
  Mirf.csnPin = 10;  // Sollte der CSE-Pin (4) an einem anderen Arduino-Port angeschlossen werden müssen (7: Standard)
  Mirf.spi = &MirfHardwareSpi;
  Mirf.init();
  Mirf.payload = 16; // Wir werden einen String mit 15 Zeichen versenden
  Mirf.channel = 115; // Optional. Sende-/Empfangsfrequenz ändern
  Mirf.config();
  Mirf.configRegister(RF_SETUP, 0x06); // Optional. Soll die Datenrate angeblich auf 1MHz ändern, was zu besserer Reichweite führt
  Mirf.setTADDR((byte *)"ardu01"); // Name des Empfängers. 5 Zeichen!

  Serial.println("Einheit bereit für Befehle!");
  }

boolean datenEinlesen(Stream& serialtype, char* buffer, byte bufferSize, byte& index) {
  char c;
  if (serialtype.available() == 0) return false;
  if (index == 0) memset(buffer, 0, bufferSize);
  c = serialtype.read();
  if (c == 13) {
    buffer[index] = '\0';
    index = 0;
    return true;
  } else if (c >= 32 && index < bufferSize - 1) {
    buffer[index] = c;
    index++;
  } else ;
  return false;
}


void loop() {
  while( Mirf.isSending() ) ;

  if (datenEinlesen(Serial, uewert, sizeof(uewert), serialIndex)== true){
    Mirf.send(uewert);
    Serial.print(uewert);
    Serial.println(" versendet");
  }
  }

Ich habe mirf.h als Alternative zur bekannteren RF24 Bibliothek genommen, da es für mich etwas verständlicher aufgebaut ist. Ich hatte beim Testen der Alternativen das Gefühl, dass ich bei der RF24-Bibliothek ein vielfaches an Konfiguration habe.

Ich kenne diese Lib auch nicht. Was mir aber aufgefallen ist:

Entweder Dein Kommentar ist falsch oder der Name ist zu lang.

Mirf.setTADDR((byte *)"ardu01"); // Name des Empfängers. 5 Zeichen!

Beide Codes verwenden den gleichen Namen. Das ist wohl nicht im Sinne des Erfinders.

Gruß Tommy

Hallo Tommy,

da ist tatsächlich die Kommentierung mangelhaft, sicher durch Übertragungsfehler beim rumprobieren. Entschuldigung dafür.

Im Punkte "beide Codes verwenden den gleichen Namen" muss ich kurz widersprechen. Es handelt sich hierbei um zwei sehr ähnliche Befehle:

 Mirf.setTADDR(()); //Setzt den Namen des Absenders-> T
 Mirf.setRADDR(()); //Setzt den Namen des Empfängers -> R

Die beiden Sketche die ich gepostet habe funktionieren so.
Ich möchte nun noch eine Rückantwortende Kommunikation einbauen. (Siehe die beiden Versuche/Auszüge im ersten Post)

Ok, das R und T habe ich überlesen.

Gruß Tommy