Week 16: Wirless Network with nRF42's

The assignment this week was to make a "network" of some kind.
The "network" I choose to make was a wireless network with the use of two nRF42 modules.

What these do is communicate wirelessly by sending or receiving information.

The key is that one of them have to be the receiver and the other the sender.
They can't do both at the same time, but they can switch roles if you want.

This video shows some basic servo function on a hexapod leg over a wireless network.

One nRF42 is acting as a reciever and the other as the sender.

Below is the code for the transimitter radio that sends data.

// HexapodLegTx.ino
#include <SPI.h>
#include <nRF24L01.h>
#include <RF24.h>

// --- Radio Configuration ---
RF24 radio(2, 4); // CE, CSN
const byte address[6] = "RxAAA"; // Address must match Receiver

// --- Data Packet Structure ---
// We send this exact package over the air
struct DataPacket {
  byte servoID; // 1, 2, or 3
  byte angle;   // 0 - 180
};

DataPacket data;

void setup() {
  Serial.begin(115200);
  
  if (!radio.begin()) {
    Serial.println("Radio hardware not responding!");
    while (1) {} // Halt if radio fails
  }
  
  radio.openWritingPipe(address);
  radio.setPALevel(RF24_PA_LOW); // Low power for close range testing
  radio.stopListening(); // Transmitter mode
  
  Serial.println("Transmitter Ready. Enter: ID Angle (e.g., '1 90')");
}

void loop() {
  if (Serial.available()) {
    // 1. Read input from Serial Monitor
    int id = Serial.parseInt();
    int ang = Serial.parseInt();
    
    // Clear the buffer (remove newline characters)
    while (Serial.available()) Serial.read();

    // 2. Validate and Send
    if (id >= 1 && id <= 3 && ang >= 0 && ang <= 180) {
      
      data.servoID = id;
      data.angle = ang;
      
      bool report = radio.write(&data, sizeof(DataPacket));
      
      if (report) {
        Serial.printf("Sent: Servo %d -> %d deg\n", data.servoID, data.angle);
      } else {
        Serial.println("Transmission Failed (Check Receiver Power)");
      }
    } else {
      Serial.println("Invalid Input. Use: 1-3 for ID, 0-180 for Angle");
    }
  }
}

Below is the receiver code that recives the data and tells the servos how to move.

// HexapodLegRx.ino 
#include <SPI.h>
#include <nRF24L01.h>
#include <RF24.h>
#include <ESP32Servo.h>

// --- Radio Configuration ---
RF24 radio(2, 4); // CE, CSN
const byte address[6] = "RxAAA";

// --- Servo Configuration ---
Servo servos[3];
const int servoPins[] = {25, 26, 27}; // The pins your servos are on

// --- Data Packet Structure ---
// MUST match the Transmitter exactly
struct DataPacket {
  byte servoID;
  byte angle;
};

DataPacket receivedData;

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

  // 1. Setup Servos
  for (int i = 0; i < 3; i++) {
    servos[i].attach(servoPins[i]);
    servos[i].write(90); // Start at neutral
  }

  // 2. Setup Radio
  if (!radio.begin()) {
    Serial.println("Radio hardware not responding!");
    while (1) {}
  }
  
  radio.openReadingPipe(0, address);
  radio.setPALevel(RF24_PA_LOW);
  radio.startListening(); // Receiver mode
  
  Serial.println("Receiver Ready. Waiting for commands...");
}

void loop() {
  if (radio.available()) {
    // 1. Read the data
    radio.read(&receivedData, sizeof(DataPacket));

    // 2. Validate ID to prevent crashing
    if (receivedData.servoID >= 1 && receivedData.servoID <= 3) {
      
      // Subtract 1 because array index starts at 0 (ID 1 = Index 0)
      int servoIndex = receivedData.servoID - 1;
      
      servos[servoIndex].write(receivedData.angle);
      
      Serial.printf("Moved Servo %d to %d\n", receivedData.servoID, receivedData.angle);
      
    } else {
      Serial.println("Received invalid Servo ID");
    }
  }
}

This video shows some kinematics in action with a button using the same system I used above.

Heres a link to where I got the kinematics code.

Its called "Basic Repetitive Movement Code and Library"