Arduino Nano sensor (ld2410) communicating via nrf24l01 with another nano

Hello everyone, i'm trying to get this project to work properly. My transmitter is an arduino nano, connected to a ld2410 sensor which gives data about whether there's a human in range, his state, and at what range he is. This data is then sent to the receiver via nrf24l01, which prints it on an lcd and updates the distance. What i need to add, is the possibility to disable the transmitter ld2410 sensor, via a button on the receiver. The transmitter will transmit its data, and then listen for a short while, to ensure it can receive the necessary packets. However my button is giving me an inconsistent behaviour: While it is set to only trigger after a long press (1000ms), once i even press it for a minimal amount of time, somehow makes the receiver start receiving modified data, you'll see what i mean in the code section later. Long presses instead freeze the code, for a reason to me unknown. I would love any kind of feedback, cheers!

Transmitter code:

#include <SPI.h>
#include <nRF24L01.h>
#include <RF24.h>
#include <ld2410.h>

// nRF24L01 pins configuration
#define CE_PIN   7
#define CSN_PIN  8

RF24 radio(CE_PIN, CSN_PIN);
const byte address[6] = "00001"; // Address for communication

ld2410 radar;
unsigned long lastReading = 0;
unsigned long lastSwitchTime = 0;
bool radarEnabled = true; // Flag to control radar
bool listeningForControl = true; // Flag to switch between listening and sending

void setup() {
  Serial.begin(256000); // Initialize hardware serial for radar
  Serial.println("Initializing radar...");

  bool initialized = false;
  for (int attemptCount = 0; attemptCount < 10; attemptCount++) { // Retry initialization up to 10 times
    if (radar.begin(Serial)) { // Initialize LD2410 radar module with hardware serial
      initialized = true;
      Serial.println("Radar initialized successfully.");
      break; // Exit the loop if initialization succeeds
    } else {
      Serial.println("Radar initialization failed. Retrying...");
      delay(500); // Wait 500ms before retrying
    }
  }

  if (!initialized) {
    Serial.println("Radar initialization failed after 10 attempts. Exiting setup.");
    // Handle initialization failure here, if needed
  }

  // Initialize nRF24L01 communication
  Serial.println("Initializing radio module...");
  radio.begin();
  radio.setDataRate(RF24_250KBPS);
  radio.openWritingPipe(address);
  radio.setPALevel(RF24_PA_MIN);

  // Print radio module details for debug
  radio.setAutoAck(false);
  radio.setChannel(115);
  radio.printPrettyDetails();
  radio.openWritingPipe(address);
  radio.startListening();
  Serial.println("Radio module initialized.");
}

void loop() {
  unsigned long currentMillis = millis();
  // Switch between listening for control and sending data every second
  if (currentMillis - lastSwitchTime >= 1000) {
    listeningForControl = !listeningForControl;
    if (listeningForControl) {
      radio.startListening();
      Serial.println("Switched to listening for control messages.");
    } else {
      radio.stopListening();
      Serial.println("Switched to sending radar data.");
    }
    lastSwitchTime = currentMillis;
  }

  if (listeningForControl && radio.available()) {
    char controlMessage[10];
    radio.read(&controlMessage, sizeof(controlMessage));
    Serial.print("Control message received: ");
    Serial.println(controlMessage);

    // Parse control message
    int controlFlag;
    if (sscanf(controlMessage, "CTRL:%d", &controlFlag) == 1) {
      radarEnabled = controlFlag;
      Serial.print("Radar enabled: ");
      Serial.println(radarEnabled);
    }
  }

  // Only process radar data if the radar is enabled and not listening for control messages
  if (!listeningForControl && radarEnabled && radar.isConnected() && millis() - lastReading > 800) {
    radar.read();
    lastReading = millis();
    if (radar.presenceDetected()) {
      Serial.println("Presence Detected.");
      if (radar.movingTargetDetected() && radar.movingTargetDistance() < 10000) {
        int distance = radar.movingTargetDistance();
        Serial.println("Moving Target Detected.");
        Serial.print(F("Moving target: "));
        Serial.print(radar.movingTargetDistance());
        Serial.print(F("cm energy:"));
        Serial.print(radar.movingTargetEnergy());
        
        // Prepare the data to send over nRF24L01
        char dataToSend[50];
        sprintf(dataToSend, "Target Dist: %d cm", distance);

        // Print the data to be sent for debugging
        Serial.println("Data to be sent:");
        Serial.println(dataToSend);

        // Send data over nRF24L01
        bool success = radio.write(&dataToSend, sizeof(dataToSend));
        if (success) {
          Serial.println("Data sent successfully.");
        } else {
          Serial.println("Failed to send data.");
        }

        // Wait for a brief moment to prevent rapid consecutive transmissions
        delay(1200);
      } else {
        Serial.println("No Moving Target Detected.");
      }
    } else {
      Serial.println("No Presence Detected.");
    }
  }
}

Receiver Code:

#include <SPI.h>
#include <nRF24L01.h>
#include <RF24.h>
#include <LiquidCrystal.h>

// nRF24L01 pins configuration
#define CE_PIN 7
#define CSN_PIN 8

RF24 radio(CE_PIN, CSN_PIN);
const byte address[6] = "00001"; // Address for communication

// LCD pin configuration
LiquidCrystal lcd(9, 6, 2, 3, 4, 5); // RS, E, D4, D5, D6, D7

// Button pin
const int buttonPin = 10; // Pin for button

// State variables
bool buttonPressed = false; // Button press state
unsigned long buttonPressTime = 0; // Time when button was first pressed
const unsigned long pressDuration = 1000; // 1 second press duration required
bool displayState = false; // False for "O", True for "I"
bool radioEnabled = true; // State to track radio transmission enable/disable

void setup() {
  Serial.begin(9600);
  Serial.println("Initializing receiver...");

  // Initialize the LCD
  lcd.begin(16, 2); // Adjust this based on your LCD dimensions (cols, rows)
  lcd.setCursor(0, 0);
  lcd.print("Sen1: xxx cm");
  lcd.setCursor(15, 0);
  lcd.print("O");

  // Initialize nRF24L01 communication
  SPI.begin();
  if (!radio.begin()) {
    Serial.println(F("Radio hardware not responding!"));
    while (1) {} // Hold program in infinite loop to prevent subsequent errors
  }

  radio.setDataRate(RF24_250KBPS);
  radio.openReadingPipe(1, address); // Use pipe 1 for reading
  radio.setPALevel(RF24_PA_MIN);
  radio.setAutoAck(false);
  radio.setChannel(115);
  radio.startListening();

  // Print radio module details for debug
  radio.printDetails(); // Print module details
  Serial.println("Radio module initialized.");

  // Set button pin as input with internal pull-up resistor
  pinMode(buttonPin, INPUT_PULLUP);
}

void loop() {
  // Check button press
  checkButtonPress();

  if (radioEnabled && radio.available()) {
    char receivedMessage[32] = {0}; // Ensure buffer is large enough
    radio.read(&receivedMessage, sizeof(receivedMessage));

    // Print received message to Serial Monitor
    Serial.print("Received data: ");
    Serial.println(receivedMessage);

    // Extract and display distance from received message
    int distance = 0;
    if (sscanf(receivedMessage, "Target Dist: %d cm", &distance) == 1 || sscanf(receivedMessage, "Target Dist: %d cm", &distance) == 1) {
      lcd.setCursor(6, 0);
      lcd.print(distance);
      lcd.print(" cm");
    } else {
      Serial.println("Invalid message received.");
    }

    delay(2000); // Delay before clearing LCD for next display
    lcd.setCursor(0, 1);
    lcd.print("                "); // Clear the second line
  }
}

void checkButtonPress() {
  // Read the button state
  int reading = digitalRead(buttonPin);

  if (reading == LOW) {
    if (!buttonPressed) {
      buttonPressed = true;
      buttonPressTime = millis();
    } else {
      if (millis() - buttonPressTime >= pressDuration) {
        // Button has been pressed for at least 1 second
        displayState = !displayState; // Toggle the display state
        radioEnabled = !radioEnabled; // Toggle the radio enabled state
        updateDisplay(); // Update LCD to reflect the state

        // Debug message
        Serial.print("Button pressed, displayState: ");
        Serial.println(displayState ? "I" : "O");
        Serial.print("Radio state: ");
        Serial.println(radioEnabled ? "Enabled" : "Disabled");

        // Reset button press state to avoid multiple triggers
        buttonPressed = false;
      }
    }
  } else {
    buttonPressed = false; // Reset the button press state if the button is released
  }
}

// Function to update the LCD display
void updateDisplay() {
  lcd.setCursor(15, 0);
  if (displayState) {
    lcd.print("I");
  } else {
    lcd.print("O");
  }
}

Expected output Receiver:

Initializing receiver...
Radio module initialized.
Received data: Target Dist: "xxx" cm

Output after short button press:

Initializing receiver...
Radio module initialized.
Received data: �������������������������������K
Invalid message received.
Received data: BTarget Dist: 63 cm

What kind of inconsistent behaviour?

It's all written either in the post itself, or below the receiver and transmitter code! TLDR tho: Short button presses bug out the incoming transmission, modifying it (see below the code) , long press freezes the code entirely.

Don't clear the buttonPressed until the button is really released, reading a HIGH from the button input. Now it's cleared after being noticed and handled.

Thanks for the tip. I changed the checkButtonPress to this

void checkButtonPress() {
  // Read the button state
  int reading = digitalRead(buttonPin);

  if (reading == LOW && !buttonPressed) {
    // Button just pressed
    buttonPressed = true;
    buttonPressTime = millis();
  } else if (reading == HIGH && buttonPressed) {
    // Button just released
    buttonPressed = false;
    unsigned long pressDuration = millis() - buttonPressTime;
    if (pressDuration >= 1000) {
      // Button was pressed for at least 1 second
      displayState = !displayState; // Toggle the display state
      radioEnabled = !radioEnabled; // Toggle the radio enabled state
      updateDisplay(); // Duh
      Serial.print("Button released after long press, displayState: ");
      Serial.println(displayState ? "I" : "O");
      Serial.print("Radio state: ");
      Serial.println(radioEnabled ? "Enabled" : "Disabled");
    } else {
      Serial.println("Button released after short press, no state change.");
    }
  }
}

However the result is still the same: a short button press, while it should give me an error message, instead changes the received message to BTarget Dist: 69 cm. Long press still freezes program

It's hard to just dry read code and tell.

I suggest You make a test code just exercising the button detection and make that work.
When it works, install the button part of the code in the main project.
Using debugging serial.print is a valuable tool You can use, but I don't have.

Surprisingly indeed, if i just extrapolate the button portion, it works properly. Once i get it into the code to, it does... that

This topic was automatically closed 180 days after the last reply. New replies are no longer allowed.