Cirkit Designer LogoCirkit DesignerYour all-in-one circuit design IDE Launch Cirkit Designer App

Arduino Nano Controlled Wireless Robot with NRF24L01 and L298N Motor Driver

View and Edit Project In Cirkit DesignerImage of Arduino Nano Controlled Wireless Robot with NRF24L01 and L298N Motor Driver

Circuit Documentation

Summary

This circuit is designed to control a robot with two DC motors using an L298N motor driver. It features wireless communication capabilities through an NRF24L01 module, allowing the robot to receive commands such as moving forward, backward, turning, stopping, and returning to its origin by retracing its steps. The Arduino Nano serves as the central microcontroller, interfacing with the motor driver and the wireless module. Power is supplied by a 4 x AAA battery mount.

Component List

Arduino Nano

NRF24L01

L298N DC Motor Driver

4 x AAA Battery Mount

Hobby Gearmotor with 48:1 Gearbox (x2)

Wiring Details

Arduino Nano

NRF24L01

L298N DC Motor Driver

4 x AAA Battery Mount

Hobby Gearmotor with 48:1 Gearbox (Motor A)

Hobby Gearmotor with 48:1 Gearbox (Motor B)

Documented Code

/*
 * This Arduino sketch controls a robot with two motors using an L298N driver
 * and an NRF24L01 module for wireless communication. The robot can move
 * forward, backward, turn left, turn right, and stop based on commands
 * received wirelessly. It also has a feature to return to its origin by
 * retracing its steps.
 */

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

// Motor control pins
const int IN1 = 2;
const int IN2 = 3;
const int ENA = 6;  // PWM for Motor A
const int IN3 = 4;
const int IN4 = 5;
const int ENB = 7;  // PWM for Motor B

RF24 radio(9, 10); // NRF24L01 CE, CSN pins
const byte address[6] = "00001";

// Commands from the transmitter
enum Commands {
  FORWARD,
  BACKWARD,
  LEFT,
  RIGHT,
  STOP,
  RETURN_TO_ORIGIN
};

// Variables for tracking path and command
Commands command = STOP;
Commands path[100];   // Array to store movement commands for dead reckoning
int pathIndex = 0;    // Tracks path storage index
bool returnToOrigin = false;

void setup() {
  // Set motor pins as outputs
  pinMode(IN1, OUTPUT);
  pinMode(IN2, OUTPUT);
  pinMode(ENA, OUTPUT);
  pinMode(IN3, OUTPUT);
  pinMode(IN4, OUTPUT);
  pinMode(ENB, OUTPUT);

  // NRF24L01 setup
  radio.begin();
  radio.openReadingPipe(0, address);
  radio.setPALevel(RF24_PA_LOW);
  radio.startListening();
}

void loop() {
  // Check if a command is received
  if (radio.available()) {
    radio.read(&command, sizeof(command));

    // If not in return-to-origin mode, store the command in path
    if (!returnToOrigin && command != RETURN_TO_ORIGIN) {
      path[pathIndex++] = command; // Store command
      if (pathIndex >= 100) pathIndex = 99; // Prevent overflow
    }

    // Trigger return to origin if commanded
    if (command == RETURN_TO_ORIGIN) {
      returnToOrigin = true;
      pathIndex--; // Set to last command position
    }
  }

  // Execute the current command or start return-to-origin sequence
  if (!returnToOrigin) {
    executeCommand(command);  // Normal driving mode
  } else {
    returnToOriginSequence(); // Retracing path to origin
  }
}

// Function to execute a command
void executeCommand(Commands cmd) {
  switch (cmd) {
    case FORWARD:
      driveForward();
      break;
    case BACKWARD:
      driveBackward();
      break;
    case LEFT:
      turnLeft();
      break;
    case RIGHT:
      turnRight();
      break;
    case STOP:
      stopMotors();
      break;
  }
}

// Function to retrace steps back to origin
void returnToOriginSequence() {
  if (pathIndex >= 0) {
    // Execute the opposite of each command in reverse order
    switch (path[pathIndex--]) {
      case FORWARD:
        driveBackward();
        break;
      case BACKWARD:
        driveForward();
        break;
      case LEFT:
        turnRight();
        break;
      case RIGHT:
        turnLeft();
        break;
      case STOP:
        stopMotors();
        break;
    }
  } else {
    // Reached origin; reset state
    stopMotors();
    returnToOrigin = false;
    pathIndex = 0;  // Reset path index for future tracking
  }
}

// Movement functions for tank-style control
void driveForward() {
  analogWrite(ENA, 255);  // Full speed for Motor A
  analogWrite(ENB, 255);  // Full speed for Motor B
  digitalWrite(IN1, HIGH);
  digitalWrite(IN2, LOW);
  digitalWrite(IN3, HIGH);
  digitalWrite(IN4, LOW);
}

void driveBackward() {
  analogWrite(ENA, 255);  // Full speed for Motor A
  analogWrite(ENB, 255);  // Full speed for Motor B
  digitalWrite(IN1, LOW);
  digitalWrite(IN2, HIGH);
  digitalWrite(IN3, LOW);
  digitalWrite(IN4, HIGH);
}

void turnLeft() {
  analogWrite(ENA, 100);  // Reduce speed for inner wheel
  analogWrite(ENB, 255);  // Full speed for outer wheel
  digitalWrite(IN1, HIGH);
  digitalWrite(IN2, LOW);
  digitalWrite(IN3, HIGH);
  digitalWrite(IN4, LOW);
}

void turnRight() {
  analogWrite(ENA, 255);  // Full speed for outer wheel
  analogWrite(ENB, 100);  // Reduce speed for inner wheel
  digitalWrite(IN1, HIGH);
  digitalWrite(IN2, LOW);
  digitalWrite(IN3, HIGH);
  digitalWrite(IN4, LOW);
}

void stopMotors() {
  analogWrite(ENA, 0);
  analogWrite(ENB, 0);
}

This code is responsible for controlling the robot's movements based on wireless commands received via the NRF24L01 module. It includes functions for driving the motors forward and backward, turning left and right, stopping the motors, and a feature to return the robot to its starting position by reversing the commands it has