Untitled

Anonymous
plain_text
02/23/2026 8:15 PM
3.9 KB
11
Indexable
/*
  CAR (Receiver) — 1 TT motor (drive) + 1 servo (steering) + NRF24L01 + L298N

  Arduino Uno pins:
  - L298N (use Channel A):
      IN1 -> D8
      IN2 -> D7
      ENA -> D9  (PWM)   // REMOVE the ENA jumper on L298N
      Motor -> OUT1/OUT2

  - Servo:
      Signal -> D3
      (Red -> 5V, Brown -> GND)

  - NRF24L01 (basic, no antenna):
      VCC -> 3.3V
      GND -> GND
      CE  -> D4
      CSN -> D10
      MOSI-> D11
      MISO-> D12
      SCK -> D13

  Libraries:
    - RF24 by TMRh20 (install)
    - SPI.h and Servo.h are built-in

  Notes:
  - 47uF capacitor across 3.3V and GND near NRF ( + to 3.3V, - to GND )
  - ALL grounds must be common: Arduino GND, L298N GND, servo GND, NRF GND
*/

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

RF24 radio(4, 10);               // CE, CSN
const byte address[6] = "CAR01"; // must match transmitter

struct Packet {
  int16_t x; // steering: 0..1023
  int16_t y; // throttle: 0..1023
};

Servo steer;

// Motor pins (L298N Channel A)
const int IN1 = 8;
const int IN2 = 7;
const int ENA = 9;

// Servo pin
const int SERVO_PIN = 3;

// Failsafe
unsigned long lastRecvMs = 0;
const unsigned long FAILSAFE_MS = 350;

// Helpers
int clampi(int v, int lo, int hi) {
  if (v < lo) return lo;
  if (v > hi) return hi;
  return v;
}

int stickToPWM(int v) {
  v = clampi(v, 0, 1023);
  int d = v - 512;
  if (abs(d) < 40) return 0;           // deadband
  long out = (long)d * 255L / 512L;    // scale to -255..255
  return clampi((int)out, -255, 255);
}

int stickToServoAngle(int v) {
  v = clampi(v, 0, 1023);
  // keep away from hard limits to avoid binding
  int ang = map(v, 0, 1023, 30, 150);
  return clampi(ang, 30, 150);
}

void motorStop() {
  digitalWrite(IN1, LOW);
  digitalWrite(IN2, LOW);
  analogWrite(ENA, 0);
}

void motorDrive(int pwmSigned) {
  pwmSigned = clampi(pwmSigned, -255, 255);

  if (pwmSigned == 0) {
    motorStop();
    return;
  }

  if (pwmSigned > 0) {
    digitalWrite(IN1, HIGH);
    digitalWrite(IN2, LOW);
    analogWrite(ENA, pwmSigned);
  } else {
    digitalWrite(IN1, LOW);
    digitalWrite(IN2, HIGH);
    analogWrite(ENA, -pwmSigned);
  }
}

void setup() {
  pinMode(IN1, OUTPUT);
  pinMode(IN2, OUTPUT);
  pinMode(ENA, OUTPUT);

  motorStop();

  steer.attach(SERVO_PIN);
  steer.write(90); // center

  radio.begin();
  radio.setPALevel(RF24_PA_LOW);
  radio.setDataRate(RF24_250KBPS);
  radio.openReadingPipe(1, address);
  radio.startListening();

  lastRecvMs = millis();
}

void loop() {
  Packet p;

  if (radio.available()) {
    radio.read(&p, sizeof(p));
    lastRecvMs = millis();

    // Steering
    steer.write(stickToServoAngle(p.x));

    // Throttle
    int pwm = stickToPWM(p.y);

    // limit top speed a bit (helps prevent resets)
    const int MAX_PWM = 220;
    pwm = (int)((long)pwm * MAX_PWM / 255L);

    motorDrive(pwm);
  }

  // failsafe: stop if signal lost
  if (millis() - lastRecvMs > FAILSAFE_MS) {
    motorStop();
    steer.write(90);
  }
}
Editor is loading...
Leave a Comment