RF24 wireless zwei Wege Problem

Hallo, schon wieder ich.
Ich habe ein Problem mit zwei rf24l01 Modulen. Was soll gemacht werden? Ich versuche es so knapp wie möglich zu beschreiben:

Arduino1 fungiert als Fernbedienung. Auf Tastendruck startet ein Timer (4 Digit 7 Segment), dann soll per RF24 ein Signal von Arduino2 (und später noch zwei weiteren) empfangen werden welches die Zeit auf dem 7-Segment Display nicht mehr weiter aktualisiert.
Das Signal von Arduino2 soll dann gesendet werden wenn ein Piezosensor einen bestimmten Wert überschreitet. Gleichzeitig wechseln an Arduino2 LEDs von rot auf grün. Diese LEDs wiederum werden erst wieder rot, wenn an Arduino1 ein anderer Taster betätigt wird.

Nun zum Problem: Piezo funktioniert, LEDs werden grün, allerdings empfängt die "Fernbedienung" das Signal zum Timer-Stop nicht. Der Reset-Taster um die LEDs wieder rot zu schalten funktioniert allerdings.
Wieder einmal bin ich absolut neu auf dem Gebiet (wireless), ich habe verschiedenste Tutorials geschaut und Beispielcodes gelesen, aber ich finde meinen Fehler nicht.

Arduino1/Fernbedienung:

#include "nRF24L01.h" //NRF24L01 library created by TMRh20 https://github.com/TMRh20/RF24
#include "RF24.h"
#include "SPI.h"

#include <TM1637.h>




int CLK = 2;
int DIO = 3;

TM1637 tm(CLK, DIO);

#define SwitchPin 6 //Reset
#define StartPin 5 //Start

int SentMessage[1] = {000};
int ReceivedMessage[1] = {000};

int Target1 = 0;
int Target2 = 0;
int Target3 = 0;
int Started = 0;

// variables for digits
int Hundertstel, Zehntel, Eins, Zehn;



unsigned long Startmillis = 0;
unsigned long Messung = 0;

RF24 radio(9, 10); // NRF24L01 used SPI pins + Pin 9 and 10 on the NANO
const uint64_t pipe[2] = {0xF0F0F0F0E1LL, 0xF0F0F0F0D2LL};

//const uint64_t pipe = 0xE6E6E6E6E6E6; // Needs to be the same for communicating between 2 NRF24L01
//const uint64_t pipe2 = 0xE8E8F0F0E1LL;

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

  pinMode(SwitchPin, INPUT_PULLUP);
  digitalWrite(SwitchPin, HIGH);

  radio.begin(); // Start the NRF24L01

  //   radio.openReadingPipe(1, pipe); // Get NRF24L01 ready to receive
  //      radio.openWritingPipe(pipe); // Get NRF24L01 ready to transmit

  tm.init();
  // set brightness; 0-7
  tm.set(4);
  tm.display(0, 0);
  tm.display(1, 0);
  tm.point(1);
  tm.display(2, 0); //10==A
  tm.display(3, 0); //11==B...




}

void loop(void) {

  if (digitalRead(SwitchPin) == LOW)    // RESET ALL
  {
    radio.stopListening();
    radio.openWritingPipe(pipe[1]);
    SentMessage[0] = 111;
    radio.write(SentMessage, 1);      // Send pressed data to NRF24L01
    SentMessage[0] = 222;
    radio.write(SentMessage, 1);      //
    SentMessage[0] = 333;
    radio.write(SentMessage, 1);      // 111,222,333 = Reset 1,2,3
    SentMessage[0] = 000;
    radio.write(SentMessage, 1);      // Send idle data to NRF24L01
    Started = 0;
    displayNumber(0000);
  }

  if (digitalRead(StartPin) == LOW && Started == 0) {
    Started = 1;
    Target1 = 0;
    Target2 = 0;
    Target3 = 0;
    Startmillis = millis();
  }


  if (Started == 1) {

    //Start Timer

    Messung = millis() - Startmillis;


    radio.openReadingPipe(1, pipe[0]);
    radio.startListening(); // Listen to see if information received
    while (radio.available())
    {
      radio.read(ReceivedMessage, 1); // Read information from the NRF24L01
      if (ReceivedMessage[0] == 444) {
        Target1 = 1;
      }
      if (ReceivedMessage[0] == 555) {
        Target2 = 1;
      }
      if (ReceivedMessage[0] == 666) {
        Target3 = 1;
      }
    }


    Serial.println(Target1);


    Hundertstel = (Messung / 10) % 10;
    Zehntel = (Messung / 100) % 10;
    Eins = (Messung / 1000) % 10;
    Zehn = (Messung / 10000) % 10;

    if (Target1 == 1) { //&& Target2 == 1 && Target3 == 1
      radio.stopListening();
      Started = 0;

    }

    if (Target1 == 0) { // && Target2 == 0 && Target3 == 0
      tm.display(3, Hundertstel);
      tm.display(2, Zehntel);
      tm.display(1, Eins);
      tm.display(0, Zehn);

    }




  }

}

//Funktion   displayNumber(XXXX);
void displayNumber(int num) {
  tm.display(3, num % 10);
  tm.display(2, num / 10 % 10);
  tm.display(1, num / 100 % 10);
  tm.display(0, num / 1000 % 10);
}

Arduino2/Piezo+LEDs

#include <Adafruit_NeoPixel.h>
#include "nRF24L01.h" // NRF24L01 library created by TMRh20 https://github.com/TMRh20/RF24
#include "RF24.h"
#include "SPI.h"

#ifdef __AVR__
#include <avr/power.h> // Required for 16 MHz Adafruit Trinket
#endif

#define LED_PIN 5
#define LED_COUNT 6
const int buzzer = 3;
int Treffer = 0;

int ReceivedMessage[1] = {000}; // Used to store value received by the NRF24L01
int SentMessage[1] = {000};

RF24 radio(9, 10); // NRF24L01 SPI pins. Pin 9 and 10 on the Nano

//const uint64_t pipe = 0xE6E6E6E6E6E6; // Needs to be the same for communicating between 2 NRF24L01
//const uint64_t pipe2 = 0xE8E8F0F0E1LL;
const uint64_t pipe[2] = {0xF0F0F0F0E1LL, 0xF0F0F0F0D2LL};


Adafruit_NeoPixel strip(LED_COUNT, LED_PIN, NEO_GRB + NEO_KHZ800);

void setup() {

  Serial.begin(115200);
  strip.begin();           // INITIALIZE NeoPixel strip object (REQUIRED)
  strip.show();            // Turn OFF all pixels ASAP
  strip.setBrightness(200);

  for (int i = 0; i < LED_COUNT; i++) {   // Set all LEDs to red Status "off"
    strip.setPixelColor(i, 255, 0, 0);
  }
  strip.show();


  radio.begin(); // Start the NRF24L01
  //   radio.openReadingPipe(1, pipe); // Get NRF24L01 ready to receive
  //      radio.openWritingPipe(pipe); // Get NRF24L01 ready to transmit



}



void loop() {

  if (Treffer == 0) {


    int val = analogRead(A0);         // Piezo an A0 lesen
    //Serial.println(val, DEC);         //Ausgabe A0 an Serial Monitor
    if (val > 100) {                   //Treffer
      //ZUERST AN FERNBEDIENUNG SENDEN
      //radio.openWritingPipe(pipe); // Get NRF24L01 ready to transmit

      radio.stopListening();
      radio.openWritingPipe(pipe[0]); // Get NRF24L01 ready to transmit
      SentMessage[0] = 444;     // TARGET1 555 und 666 für 2&3

      radio.write(SentMessage, 1);      // Send pressed data to NRF24L01
      delay(200);

      Treffer = 1;
      for (int i = 0; i < LED_COUNT; i++) {     // LEDs grün
        strip.setPixelColor(i, 0, 255, 0);
      }
      strip.show();
      tone(buzzer, 4700);                         //Beep
      delay(300);
      noTone(buzzer);
    }
  }

  if (Treffer == 1) {
    //Warten auf Reset von Fernbedienung


    radio.openReadingPipe(1, pipe[1]); // Get NRF24L01 ready to receive
    radio.startListening(); // Listen to see if information received

    while (radio.available())
    {
      radio.read(ReceivedMessage, 1); // Read information from the NRF24L01
    }

    if (ReceivedMessage[0] == 111) // Indicates switch is pressed
    {
      Treffer = 0;

      for (int i = 0; i < LED_COUNT; i++) {   // Set all LEDs to red
        strip.setPixelColor(i, 255, 0, 0);
      }
      strip.show();

    }
  }


}

Über Hilfe und Anregungen bin ich wie immer dankbar!

erste Hilfe: nicht besonders knapp sondern besondrs ausführlich beschreiben was geht und was nicht geht.

zweite Hilfe und Anregung:
schreibe was du mit einfachen Testprogrammen getestet hast.
Zu nRF24 gibt es Testprogramme. Außerdem geben die meisten functions mindestens einen boolschen Wert zurück den man auswerten kann.

Also online nachschauen was es für deine nRF24-library für Democodes gibt und in der
nRF24L01.h und in der nRF24L01.h nachschauen welche Funktion gibt was für Werte zurück

hier ein Beispiel wie das aussieht das stammt aber aus einer anderen library die RF24.h heißt

  // initialize the transceiver on the SPI bus
  if (!radio.begin()) {
    Serial.println(F("radio hardware is not responding!!"));
    while (1) {} // hold in infinite loop
  }

aus diesem Demo-Code. Habe ich personlich nicht getestet

/*
 * See documentation at https://nRF24.github.io/RF24
 * See License information at root directory of this library
 * Author: Brendan Doherty (2bndy5)
 */

/**
 * A simple example of sending data from 1 nRF24L01 transceiver to another.
 *
 * This example was written to be used on 2 devices acting as "nodes".
 * Use the Serial Monitor to change each node's behavior.
 */
#include <SPI.h>
#include "printf.h"
#include "RF24.h"

// instantiate an object for the nRF24L01 transceiver
RF24 radio(7, 8); // using pin 7 for the CE pin, and pin 8 for the CSN pin

// Let these addresses be used for the pair
uint8_t address[][6] = {"1Node", "2Node"};
// It is very helpful to think of an address as a path instead of as
// an identifying device destination

// to use different addresses on a pair of radios, we need a variable to
// uniquely identify which address this radio will use to transmit
bool radioNumber = 1; // 0 uses address[0] to transmit, 1 uses address[1] to transmit

// Used to control whether this node is sending or receiving
bool role = false;  // true = TX role, false = RX role

// For this example, we'll be using a payload containing
// a single float number that will be incremented
// on every successful transmission
float payload = 0.0;

void setup() {

  Serial.begin(115200);
  while (!Serial) {
    // some boards need to wait to ensure access to serial over USB
  }

  // initialize the transceiver on the SPI bus
  if (!radio.begin()) {
    Serial.println(F("radio hardware is not responding!!"));
    while (1) {} // hold in infinite loop
  }

  // print example's introductory prompt
  Serial.println(F("RF24/examples/GettingStarted"));

  // To set the radioNumber via the Serial monitor on startup
  Serial.println(F("Which radio is this? Enter '0' or '1'. Defaults to '0'"));
  while (!Serial.available()) {
    // wait for user input
  }
  char input = Serial.parseInt();
  radioNumber = input == 1;
  Serial.print(F("radioNumber = "));
  Serial.println((int)radioNumber);

  // role variable is hardcoded to RX behavior, inform the user of this
  Serial.println(F("*** PRESS 'T' to begin transmitting to the other node"));

  // Set the PA Level low to try preventing power supply related problems
  // because these examples are likely run with nodes in close proximity to
  // each other.
  radio.setPALevel(RF24_PA_LOW);  // RF24_PA_MAX is default.

  // save on transmission time by setting the radio to only transmit the
  // number of bytes we need to transmit a float
  radio.setPayloadSize(sizeof(payload)); // float datatype occupies 4 bytes

  // set the TX address of the RX node into the TX pipe
  radio.openWritingPipe(address[radioNumber]);     // always uses pipe 0

  // set the RX address of the TX node into a RX pipe
  radio.openReadingPipe(1, address[!radioNumber]); // using pipe 1

  // additional setup specific to the node's role
  if (role) {
    radio.stopListening();  // put radio in TX mode
  } else {
    radio.startListening(); // put radio in RX mode
  }

  // For debugging info
  // printf_begin();             // needed only once for printing details
  // radio.printDetails();       // (smaller) function that prints raw register values
  // radio.printPrettyDetails(); // (larger) function that prints human readable data

} // setup

void loop() {

  if (role) {
    // This device is a TX node

    unsigned long start_timer = micros();                    // start the timer
    bool report = radio.write(&payload, sizeof(float));      // transmit & save the report
    unsigned long end_timer = micros();                      // end the timer

    if (report) {
      Serial.print(F("Transmission successful! "));          // payload was delivered
      Serial.print(F("Time to transmit = "));
      Serial.print(end_timer - start_timer);                 // print the timer result
      Serial.print(F(" us. Sent: "));
      Serial.println(payload);                               // print payload sent
      payload += 0.01;                                       // increment float payload
    } else {
      Serial.println(F("Transmission failed or timed out")); // payload was not delivered
    }

    // to make this example readable in the serial monitor
    delay(1000);  // slow transmissions down by 1 second

  } else {
    // This device is a RX node

    uint8_t pipe;
    if (radio.available(&pipe)) {             // is there a payload? get the pipe number that recieved it
      uint8_t bytes = radio.getPayloadSize(); // get the size of the payload
      radio.read(&payload, bytes);            // fetch payload from FIFO
      Serial.print(F("Received "));
      Serial.print(bytes);                    // print the size of the payload
      Serial.print(F(" bytes on pipe "));
      Serial.print(pipe);                     // print the pipe number
      Serial.print(F(": "));
      Serial.println(payload);                // print the payload's value
    }
  } // role

  if (Serial.available()) {
    // change the role via the serial monitor

    char c = toupper(Serial.read());
    if (c == 'T' && !role) {
      // Become the TX node

      role = true;
      Serial.println(F("*** CHANGING TO TRANSMIT ROLE -- PRESS 'R' TO SWITCH BACK"));
      radio.stopListening();

    } else if (c == 'R' && role) {
      // Become the RX node

      role = false;
      Serial.println(F("*** CHANGING TO RECEIVE ROLE -- PRESS 'T' TO SWITCH BACK"));
      radio.startListening();
    }
  }

} // loop

vgs

Hier habe ich aufgehört den mit unzähligen Leerzeilen versehenden Code zu lesen:

  pinMode(SwitchPin, INPUT_PULLUP);
  digitalWrite(SwitchPin, HIGH);

  radio.begin(); // Start the NRF24L01

  //   radio.openReadingPipe(1, pipe); // Get NRF24L01 ready to receive
  //      radio.openWritingPipe(pipe); // Get NRF24L01 ready to transmit

Nochmal von Vorn. Schaue in die Beispiele!
Schaue nochmal in die Beispiele!
Nimm eines dieser Beispiele - mache ein PingPong und verstehe was Du für jede Seite benötigst.

Baue aus den Beispielen eine Kommunikation.
PIN's beachten.
Geht - geht nicht - geht manchmal?

Warum benutzt du diese feste Rollenverteilung, zwischen Tx und Rx Knoten?

Ich fahre mit der Philosophie "Wenn ich nichts zu senden habe, empfange ich" sehr gut,
das funktioniert super mit einem Kommando - Antwort Ablauf.

Warum sendest du zwei Bytes gefolgt von 30 Nullen in jedem Paket?

enableDynamicPayloads ist dagegen hilfreich.

Warum verwendest du einelementige Arrays?

Warum verschickst du vier Pakete unmittelbar hintereinander?
Der Paket-Fifo ist nur drei Elemente tief, warum willst du den für knösige 8 Bytes stressen?

Warum verwendest du so viele octale Nullen?
Das kann überraschend werden, wenn die mal ungleich Null werden sollen.

P.S. delay() hat in Kommunikationsprogrammen nichts zu suchen.

Ich muss gestehen dass ich mir Codeschnipsel aus Beispielen und Tutorials zusammengestückelt habe. Deswegen kann ich die Fragen gar nicht alle beantworten.

Die vier Pakete hintereinander verschicke ich um die drei Piezo-Arduinos abzudecken, #1 soll "111", #2 "222" und #3 "333" empfangen. Das funktioniert ja auch, zumindest mit der "111", die anderen beiden Piezo-Arduinos existieren bisher noch nicht.

Was aber eben nicht funktioniert: Wenn der Piezowert überschritten wurde, dann leuchten zwar die LEDs grün wie gewollt, aber die Fernbedienung empfängt das Stopp-Signal für den Timer nicht. Das ist das einzige Problem bisher.

Also gestalten wir es vielleicht mal simpler. Brauche ich mehr als eine Pipe um zwischen TX und RX zu wechseln?
Brauche ich nach einem "stopListening" zwangsläufig nochmal ein "OpenWritingPipe" oder reicht das wenn ich einmalig die WritingPipe und die ReadingPipe öffne?

Also ein mit dem Hammer eingepasstes Puzzle? Unteroptimal.

Vier Pakete in Folge für drei Empfänger? Komisch.

Dafür wäre es sinnvoll jedem Knoten eine eigene Adresse zu geben, zwischen denen man mit openWritingPipe umschaltet,
oder die Verwendung einer Adresse, die alle Knoten empfangen, in dem Fall aber ohne Acknowledgements.

Erläutere doch mal, was du wirklich erreichen willst.

Das mit den vier Paketen hab ich jetzt schon geändert, das war ein Denkfehler von mir. Das war zum resetten gedacht, aber dafür reicht ein Paket, welches alle Targets empfangen können.

Also nochmal:
Es gibt drei separate Arduinos mit Piezo und LEDs und eine Fernbedienung (ebenfalls Arduino) mit einem Timer und Buttons.
Drückt man den Startbutton auf der Fernbedienung startet der Timer, welcher dann stoppen soll wenn alle Piezo-Arduinos den Piezo-Wert überschritten haben.
die Piezo-Arduinos schalten bei Überschreiten des Piezo-Wertes LEDs von rot auf grün, welche wiederum erst von einem zweiten Button auf der Fernbedienung wieder auf rot geschaltet werden (alle zusammen) => Resetten.

Das Resetten funktioniert, also die Piezo-Arduinos empfangen das Signal der Fernbedienung. Allerdings stoppt der Timer auf der Fernbedienung nicht, wenn die Piezos den Wert überschritten haben.

Ich hab die Codes mal etwas aktualisiert, mit zwei Pipes, dennoch kein Erfolg bisher:

Piezo:

#include <Adafruit_NeoPixel.h>
#include "nRF24L01.h" // NRF24L01 library created by TMRh20 https://github.com/TMRh20/RF24
#include "RF24.h"
#include "SPI.h"

#ifdef __AVR__
#include <avr/power.h> // Required for 16 MHz Adafruit Trinket
#endif

#define LED_PIN 5
#define LED_COUNT 6
const int buzzer = 3;
int Treffer = 0;

int ReceivedMessage[1] = {000}; // Used to store value received by the NRF24L01
int SentMessage[1] = {000};

RF24 radio(9, 10); // NRF24L01 SPI pins. Pin 9 and 10 on the Nano

const uint64_t pipe[2] = {0xF0F0F0F0E1LL, 0xF0F0F0F0D2LL};

Adafruit_NeoPixel strip(LED_COUNT, LED_PIN, NEO_GRB + NEO_KHZ800);

void setup() {

  Serial.begin(115200);
  strip.begin();           // INITIALIZE NeoPixel strip object (REQUIRED)
  strip.show();            // Turn OFF all pixels ASAP
  strip.setBrightness(200);

  for (int i = 0; i < LED_COUNT; i++) {   // Set all LEDs to red Status "off"
    strip.setPixelColor(i, 255, 0, 0);
  }
  strip.show();


  radio.begin(); // Start the NRF24L01


}



void loop() {

  if (Treffer == 0) {

    radio.stopListening();
    radio.openWritingPipe(pipe[0]); // Get NRF24L01 ready to transmit

    int val = analogRead(A0);         // Piezo an A0 lesen

    if (val > 100) {                   //Treffer
      //ZUERST AN FERNBEDIENUNG SENDEN
      SentMessage[0] = 444;     // TARGET1 555 und 666 für 2&3
      radio.write(SentMessage, 1);      // Send pressed data to NRF24L01

      Treffer = 1;
      for (int i = 0; i < LED_COUNT; i++) {     // LEDs grün
        strip.setPixelColor(i, 0, 255, 0);
      }
      strip.show();
      tone(buzzer, 4700);                         //Beep
      delay(300);
      noTone(buzzer);
    }
  }

  if (Treffer == 1) {
    //Warten auf Reset von Fernbedienung

    radio.openReadingPipe(1, pipe[1]); // Get NRF24L01 ready to receive
    radio.startListening(); // Listen to see if information received

    while (radio.available())
    {
      radio.read(ReceivedMessage, 1); // Read information from the NRF24L01
      if (ReceivedMessage[0] == 111) // Indicates switch is pressed
      {
        Treffer = 0;
        radio.stopListening();
        for (int i = 0; i < LED_COUNT; i++) {   // Set all LEDs to red
          strip.setPixelColor(i, 255, 0, 0);
        }
        strip.show();

      }
    }

  }

}

Fernbedienung:

#include "nRF24L01.h" //NRF24L01 library created by TMRh20 https://github.com/TMRh20/RF24
#include "RF24.h"
#include "SPI.h"

#include <TM1637.h>


int CLK = 2;
int DIO = 3;

TM1637 tm(CLK, DIO);

#define SwitchPin 6 //Reset
#define StartPin 5 //Start

int SentMessage[1] = {000};
int ReceivedMessage[1] = {000};

int Target1 = 0;
int Target2 = 0;
int Target3 = 0;
int Started = 0;


int Hundertstel, Zehntel, Eins, Zehn;


unsigned long Startmillis = 0;
unsigned long Messung = 0;

RF24 radio(9, 10); // NRF24L01 used SPI pins + Pin 9 and 10 on the NANO
const uint64_t pipe[2] = {0xF0F0F0F0E1LL, 0xF0F0F0F0D2LL};


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

  pinMode(SwitchPin, INPUT_PULLUP);
  digitalWrite(SwitchPin, HIGH);

  radio.begin(); // Start the NRF24L01

  tm.init();
  // set brightness; 0-7
  tm.set(4);
  tm.display(0, 0);
  tm.display(1, 0);
  tm.point(1);
  tm.display(2, 0); //10==A
  tm.display(3, 0); //11==B...


}

void loop(void) {

  if (digitalRead(SwitchPin) == LOW)    // RESET ALL
  {
    radio.stopListening();
    radio.openWritingPipe(pipe[1]);
    SentMessage[0] = 111;
    radio.write(SentMessage, 1);      // Send pressed data to NRF24L01
    Started = 0;
    displayNumber(0000);
  }

  if (digitalRead(StartPin) == LOW && Started == 0) {
    Started = 1;
    Target1 = 0;
    Target2 = 0;
    Target3 = 0;
    Startmillis = millis();
  }


  if (Started == 1) {

    //Start Timer

    Messung = millis() - Startmillis;


    radio.openReadingPipe(1, pipe[0]);
    radio.startListening(); // Listen to see if information received
    if (radio.available())
    {
      radio.read(ReceivedMessage, 1); // Read information from the NRF24L01


      if (ReceivedMessage[0] == 444) {
        Target1 = 1;
      }
      if (ReceivedMessage[0] == 555) {
        Target2 = 1;
      }
      if (ReceivedMessage[0] == 666) {
        Target3 = 1;
      }
    }


    Hundertstel = (Messung / 10) % 10;
    Zehntel = (Messung / 100) % 10;
    Eins = (Messung / 1000) % 10;
    Zehn = (Messung / 10000) % 10;

    if (Target1 == 1) { //&& Target2 == 1 && Target3 == 1
      radio.stopListening();
      Started = 0;

    }

    if (Target1 == 0) { // && Target2 == 0 && Target3 == 0
      tm.display(3, Hundertstel);
      tm.display(2, Zehntel);
      tm.display(1, Eins);
      tm.display(0, Zehn);

    }


  }

}

//Funktion   displayNumber(XXXX);
void displayNumber(int num) {
  tm.display(3, num % 10);
  tm.display(2, num / 10 % 10);
  tm.display(1, num / 100 % 10);
  tm.display(0, num / 1000 % 10);
}

Warum sendest du nur das LOW BYTE von 444?

Warum verwendest du immer noch einelementige Arrays?

While available - stopListening klingt ziemlich merkwürdig.

Warum liest du nur das LOW BYTE des angeblich empfangenen ints?

Da du dich jetzt entschieden hast ein Multicast zum Reset zu benutzen,
musst du auch die Acknowledgments auf der RX-Pipe abschalten. setAutoAck

Auf der anderen Seite solltest du enableDynamicAck und write (Multicast) verwenden.

enableDynamicPayloads sollte in alle Sketches.

Warum ist Treffer ein int? Sieht mir eher nach einer booleschen Verwendung aus.

Für deine Tastenbehandlung solltest du die Zustandsänderung auswerten,
im Moment sendest du Pakete, solange die Taste gedrückt ist.

Ich würde dafür Bounce2 verwenden.

Deine startListening/stopListening Verwendung in der Fernbedienung ist merkwürdig und unnötig kompliziert.

Auch hier ist es wieder sinnvoller Zustandsänderungen zu verarbeiten und nicht nur stumpf alles
auf den augenblicklichen Zustand auszurichten.

Nach dem Reset lauscht man auf die Antworten, bis alle da sind,
oder eine Maximalzeit überschritten ist.

Ich sende bis jetzt nur die 444 weil bisher nur ein Piezo-Arduino physisch existiert, sobald die anderen beiden gebaut sind. Oder was meinst du?

Einelementige Arrays: Das war so im Beispielcode. Ich habe probiert die 111 / 444 usw gegen einfache Integer zu ersetzen, ohne Array-Definition. Dann funktioniert nicht mal mehr der Reset.
Also ich habe aus dem Code einfach nur die Zahlen auf einstellige Ziffern gekürzt und die Variablen als normalen INT definiert.

While available - stopListening klingt ziemlich merkwürdig. => Ja, das hab ich geändert.

Warum liest du nur das LOW BYTE des angeblich empfangenen ints?
=> Mache ich das? Ich habe wie gesagt nur den Code übernommen und versucht für mich anzupassen. Wie wäre es denn besser?

Multicast: Das muss ich dann testen wenn die anderen beiden Piezo-Arduinos gebaut sind.

Treffer könnte ich zu bool ändern, das stimmt.

Ich habe jetzt gerade mal noch probiert vom Piezo ausschließlich zu senden, also dort kein Listening drin zu lassen und an der Fernbedienung ausschließlich zu Empfangen, alles rausgeschmissen was mit Senden zu tun hat. Ich bekomme das Signal vom Piezo nicht an der Fernbedienung rein... Also liegt es an wohl an irgendwas anderem. Jetzt ist die Frage: Geht vom Piezo kein Signal raus oder an der Bedienung keins rein...

Du solltest mal die Dokumentation der NRF Library studieren,
zu mindestens die aller Funktionen die du benutzt.
Das Datenblatt des Chips gibt auch tiefe Einblicke in die Funktionsweise des Chips.

Wenn du den Code änderst, kann ich das nicht sehen, ohne dass du ihn postest.

Diese Frage kannst du dir selbst beantworten, wenn du beginnst zu Begreifen, was du machst.
Die von dir benutzten Funktionen haben eine Dokumentation, lies sie.

radio.read(ReceivedMessage, 1);

liest ein Byte in den Array ReceivedMessage.

radio.read(&ReceivedInt, 2);

liest zwei Byte in die integer Variable ReceivedInt.

Das ist richtig. Ich frage mich nur warum das, was in die eine Richtung gut funktioniert für meine Anwendung, nämlich das Resetten des Piezos durch Tastendruck, in die andere Richtung, also das stoppen des Timer bei Überschreitung des Piezowerts, wiederum nicht. Quasi exakt der gleiche Code nach Auslösung durch das jeweilige "Event", nur auf der anderen Pipe.

Ich wollte hier nicht alles mit nicht funktionierendem Code zuspammen, vor allem in dem nicht-optimierten Zustand. Das kann ich aber gerne morgen noch nachreichen.

Da ich wie gesagt von der Materie keine Ahnung habe und der Code in die eine Richtung funktioniert, dachte ich dass ich mich nicht erst derartig einlesen muss, da es für meinen Zweck wirklich nur drauf ankommt einmal das Signal zu senden/empfangen, nur eben in beide Richtungen. Ich werd dem aber mal nachkommen und sehen ob mir das weiterhilft.

Einen Tip wie du die einelementigen Arrays beseitigen kannst,
habe ich eben noch meiner letzten Nachricht hinzugefügt.

Freunde dich erst mal mit der Library an, das wird schon.

Nein, solltest du nicht, das solltest du direkt machen.

Alles, was du für nur zwei Knoten ändern musst, ist das Verhalten der Fernsteuerung,
die wartet halt nicht mehr auf drei, sondern nur noch auf einen.

Danke. Das in Kombination mit einstelligen Integern als gesendete Nachricht scheint erstmal zu funktionieren.
Jetzt versuch ich mich bezüglich Multicast schlau zu machen und baue die anderen beiden Piezo-Arduinos. Da werde ich mich dann nochmal dazu melden :slight_smile:

Gut, dann bist du die einelementigen Arrays jetzt los. :slightly_smiling_face:

Du solltest mal den aktuellen Kode beider Knoten posten, egal ob der schon ganz funktioniert.

Soo, sorry für die Verzögerung. Ich hab jetzt noch eine andere Library gefunden, weil ich doch wieder Probleme hatte. Ich nutze jetzt die RF24Network.h, weil das für mich halbwegs nachvollziehbar ist. Oder auch nicht, denn es gibt neue Probleme:
Ich habe jetzt zwei Piezos und eine Fernbedienung. Timer Starten und stoppen wenn die beiden Piezos den Wert überschritten haben funktioniert. Reset beider Piezos funktioniert auch von der Fernbedienung aus.
Aber: Problem 1: Bei beiden Piezos kommt es häufig vor, dass der Wert überschritten wird und auch an den Timer/Fernbedienung das Signal geschickt wird für Timerstopp, aber die LEDs schalten nicht von rot auf grün. Ich finde meinen Fehler in der Logik nicht, da ja theoretisch nach dem überschreiten des Wertes die Schleife einmal komplett abgearbeitet werden sollte?!
Problem 2: Der erste Durchlauf nach anschließen der Stromquelle funktioniert bei meinen Tests immer problemlos. Resette ich aber die Piezos über die Fernbedienung, dann kommt es in ca 25% der Tests dazu, dass bereits ein überschrittener Piezo den Timer anhält, obwohl der zweite Piezo noch nichts gesendet hat. Ich vermute da ist noch irgendwas mit meiner Datenübertragung falsch und die Fernbedienung kriegt noch irgendein Signal was sie in dem Moment nicht haben soll?!

Piezos:

#include <Adafruit_NeoPixel.h>
#include <RF24.h>
#include <RF24Network.h>
#include <SPI.h>

#ifdef __AVR__
#include <avr/power.h> // Required for 16 MHz Adafruit Trinket
#endif

#define LED_PIN 5
#define LED_COUNT 6
Adafruit_NeoPixel strip(LED_COUNT, LED_PIN, NEO_GRB + NEO_KHZ800);

const int buzzer = 3;
int Treffer = 0;
int Hitgo = 0;

unsigned long data;
unsigned long data1;
const uint16_t this_node = 02;                                  // HIER ANPASSEN: 01/02/03
const uint16_t node00 = 00;

RF24 radio(9, 10); // nRF24L01 (CE,CSN)
RF24Network network(radio); // Include the radio in the network


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

  strip.begin();
  strip.show();
  strip.setBrightness(200);

  for (int i = 0; i < LED_COUNT; i++) {   //Rot bei boot
    strip.setPixelColor(i, 255, 0, 0);
  }
  strip.show();

  SPI.begin();
  radio.begin();
  network.begin(90, this_node); //(channel, node address)
  radio.setDataRate(RF24_2MBPS);
}



void loop() {
  network.update();

  //Ready
  if (Treffer == 0) {
    int val = analogRead(A0);         // Piezo an A0 lesen
    if (val > 150 && Hitgo == 0) {
      Hitgo = 1;
    }
  }

  //Treffer
  if (Hitgo == 1) {
    //ZUERST AN FERNBEDIENUNG SENDEN
    data = 456;                                             //HIER ANPASSEN 123/456/789
    RF24NetworkHeader header8(node00);                      //HIER ANPASSEN header7/header8/header9
    bool ok = network.write(header8, &data, sizeof(data));  //HIER ANPASSEN header7/header8/header9

    for (int i = 0; i < LED_COUNT; i++) {     // LEDs grün
      strip.setPixelColor(i, 0, 255, 0);
    }
    strip.show();

    Treffer = 1;
    Hitgo = 0;
    // tone(buzzer, 4700);                         //Beep
    // delay(300);
    // noTone(buzzer);
  }


  if (Treffer == 1) {
    //Warten auf Reset von Fernbedienung

    network.update();
    if ( network.available() ) { // Is there any incoming data?
      RF24NetworkHeader header;
      network.read(header, &data, sizeof(data)); // Read the incoming data
      if (header.from_node == 0) { // If data comes from Node 01
        data1 = data;
      }
      if (data == 111) {
        Treffer = 0;
        for (int i = 0; i < LED_COUNT; i++) {   //Rot
          strip.setPixelColor(i, 255, 0, 0);
        }
        strip.show();
      }
    }

  }
}

Fernbedienung:

#include <RF24.h>
#include <RF24Network.h>
#include <SPI.h>
#include <TM1637.h>

int CLK = 2;
int DIO = 3;

TM1637 tm(CLK, DIO);

#define SwitchPin 6 //Reset
#define StartPin 5 //Start

int Target1 = 0;
int Target2 = 0;
int Target3 = 0;
int Started = 0;

int Hundertstel, Zehntel, Eins, Zehn;

unsigned long Startmillis = 0;
unsigned long Messung = 0;

RF24 radio(9, 10); // nRF24L01 (CE,CSN)
RF24Network network(radio); // Include the radio in the network

const uint16_t this_node = 00; // Address of our node in Octal format
unsigned long data; 

const uint16_t node01 = 01;
const uint16_t node02 = 02;
const uint16_t node03 = 03;

unsigned long data1;
unsigned long data2;
unsigned long data3;


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

  pinMode(SwitchPin, INPUT_PULLUP);
  digitalWrite(SwitchPin, HIGH);

  SPI.begin();
  radio.begin();
  network.begin(90, this_node); //(channel, node address)
  radio.setDataRate(RF24_2MBPS);

  tm.init();
  tm.set(4); // set brightness; 0-7
  tm.display(0, 0);
  tm.display(1, 0);
  tm.point(1);
  tm.display(2, 0); //10==A
  tm.display(3, 0); //11==B...


}

void loop(void) {
  //network.update();

  if (digitalRead(SwitchPin) == LOW)    // RESET ALL
  {
    data = 111;
    RF24NetworkHeader header1(node01); //789
    bool oka = network.write(header1, &data, sizeof(data));
    RF24NetworkHeader header2(node02); //789
    bool okb = network.write(header2, &data, sizeof(data));
    RF24NetworkHeader header3(node03); //789
    bool okc = network.write(header3, &data, sizeof(data));

    Started = 0;
    data = 0;
    data1 = 0;
    data2 = 0;
    data3 = 0;
    displayNumber(0000);
  }

  if (digitalRead(StartPin) == LOW && Started == 0) {
    Started = 1;
    Target1 = 0;
    Target2 = 0;
    Target3 = 0;
    data = 0;
    data1 = 0;
    data2 = 0;
    data3 = 0;
    Startmillis = millis();
  }


  if (Started == 1) {
    Messung = millis() - Startmillis;

    network.update();
    if ( network.available() ) {
      RF24NetworkHeader header;
      network.read(header, &data, sizeof(data)); // Read the incoming data

      if (header.from_node == 1) { // If data comes from Node 01
        data1 = data;
        if (data1 == 123) {
          Target1 = 1;
        }
      }

      if (header.from_node == 2) { // If data comes from Node 02
        data2 = data;
        if (data2 == 456) {
          Target2 = 1;
        }
      }

      if (header.from_node == 3) { // If data comes from Node 03
        data3 = data;
        if (data2 == 789) {
          Target3 = 1;
        }
      }
    }

    if (Target1 == 1 && Target2 == 1) {// && Target3 == 1
      Started = 0;
    }

    Hundertstel = (Messung / 10) % 10;
    Zehntel = (Messung / 100) % 10;
    Eins = (Messung / 1000) % 10;
    Zehn = (Messung / 10000) % 10;
    
    tm.display(3, Hundertstel);
    tm.display(2, Zehntel);
    tm.display(1, Eins);
    tm.display(0, Zehn);
  }
}

//Funktion displayNumber(XXXX);
void displayNumber(int num) {
  tm.display(3, num % 10);
  tm.display(2, num / 10 % 10);
  tm.display(1, num / 100 % 10);
  tm.display(0, num / 1000 % 10);
}

Dann wirst du jetzt auf meine Hilfe verzichten müssen.

Viel Erfolg.

Du hast zwar eine vergleichsweise detaillierte Beschreibung gepostet worin die Fehler bestehen. Aber aus der Beschreibung jetzt nachzuvollziehen wie dein Programm funktioniert braucht man
schätzungsweise 2 Stunden Analyse. Das mache ich nicht.

Wenn du zu dieser Beschreibung noch ein Protokoll mitlieferst das einen typischen Ablauf zeigt und du Hinweise dazuschreibst in welcher Code-Zeile du den Fehler vermutest dann schaue ich mir das näher an. Sonst nicht.

Du kannst dir aber sehr gut selber helfen wenn du debug-output in deinen code einbaust.
Ich habe mir dazu zwei Makros geschrieben mit denen man wenig Schreibarbeit hat
Das Makro dbg gibt bei jedem Aufruf auf den seriellen Monitor aus

Das Makro dbgi kann man in schnell durchlaufenden Schleifen verwenden weil es nur alle so und so viel Millisekunden einmal ausgibt. Wie viele Millisekunden kann man in einem dritten Parameter angeben.

Ich empfehle in den Fixtext des Makroaufrufs eine fortlaufende Nummer zu schreiben damit man die Ausgabestelle im Code über diese Nummer eindeutig identifizieren kann.

Das sind die beiden Makros. Die fügst du einfach oben in dein Programm ein.

#define dbg(myFixedText, variableName) \
        Serial.print( F(#myFixedText " "  #variableName"=") ); \
        Serial.println(variableName); 
// usage: dbg("1:my fixed text",myVariable); 
// myVariable can be any variable or expression that is defined in scope

#define dbgi(myFixedText, variableName,timeInterval) \
  do { \
    static unsigned long intervalStartTime; \
    if ( millis() - intervalStartTime >= timeInterval ){ \
      intervalStartTime = millis(); \
      Serial.print( F(#myFixedText " "  #variableName"=") ); \
      Serial.println(variableName); \
    } \
  } while (false);
// usage: dbgi("2:my fixed text",myVar,myInterval); 
// myVar can be any variable or expression that is defined in scope
// myInterval is the time-interval which must pass by before the next
// print is executed

Einsatz von dbgi:

void loop() {
  dbgi("0:top of loop vor network.update",Treffer,500); 
  network.update();
  dbgi("1:direkt nach network.update",Treffer,500); 

Einsatz von dbgi/dbg:

  if (Treffer == 0) {
    int val = analogRead(A0);         // Piezo an A0 lesen
    dbgi("1: Treffer==0 A0",val,500); 
    
    if (val > 150 && Hitgo == 0) {
      Hitgo = 1;
      dbg("2:val > 150 && Hitgo == 0)",val);
    }
  }

usw.
vgs

3 Likes