Simple software differential for RC car

Finally finished a first version of a (LEGO based :face_with_hand_over_mouth:) RC car with 2 in-wheel brushless motors. The car includes a simple software differential running on an Arduino Nano Every.

Since this forum helped me enormously during the project, it felt good to return the favour and share the code being used.

It's pretty straight forward and it works! When fully 'on' the car has serious oversteer. When no diff is applied (potmeter turned to 0), the car has understeer. Somewhere between 'factor' 0 and 2 is the ideal setting for the car.

Posted a video of the car here: LEGO car with independent 2 wheel drive - the LBOW iWD2 - YouTube

Motor ESC's on port 4 and 5.
RC receiver channel 1 - steering - on port 6
RC receiver channel 2 - throttle - on port 8

#include <Servo.h>

volatile int PW_TH;
volatile int PW_ST;

const int p_TH =  8;
const int p_ST =  6;
const int p_ESC1 =  4;
const int p_ESC2 =  5;
const int p_POT =  A4;

int ST = 1500;
int TH = 1500;
int mid_ST;
int mid_TH;
int TH_L;
int TH_R;
int val;

const float weight = 0.2;
float factor = 0.0;

Servo ESC1;
Servo ESC2;

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

  pinMode(p_TH, INPUT);
  attachInterrupt(digitalPinToInterrupt(p_TH), get_TH_PW, CHANGE);
  pinMode(p_ST, INPUT);
  attachInterrupt(digitalPinToInterrupt(p_ST), get_ST_PW, CHANGE);
  pinMode(p_POT, INPUT);

  delay(500);

  mid_ST = PW_ST;
  mid_TH = PW_TH;

  ESC1.attach(p_ESC1, 1000, 2000);
  ESC2.attach(p_ESC2, 1000, 2000);

  ESC1.writeMicroseconds(mid_TH);
  ESC2.writeMicroseconds(mid_TH);
}

void loop() {

  val = analogRead(A4);
  factor = map(val, 0 , 1023, 0, 10) / 5.0; // 0.0 = no diff (understeer) <===>  2.0 = very active diff (oversteer)

  val = PW_TH; val -= mid_TH;              // Fetch latest throttle pulse and normalize value -500 <=> +500
  TH = weight * val + (1 - weight) * TH;   // Remove spikes
  val = PW_ST; val -= mid_ST;              // Fetch latest steering pulse and normalize value -500 <=> +500
  ST = weight * val + (1 - weight) * ST;   // Remove spikes

  //==== Do the diff! Please refer to seperate explanantion =========
  
  TH_L = (1.0 - factor * (ST / 500.0)) * TH + mid_TH;
  TH_R = (1.0 + factor * (ST / 500.0)) * TH + mid_TH;

  ESC1.writeMicroseconds(TH_L);
  ESC2.writeMicroseconds(TH_R);

}

void get_ST_PW() {
  static unsigned long start = 0;

  if (digitalRead(p_ST) == HIGH) start = micros();
  else {
    PW_ST = micros() - start;
  }
}

void get_TH_PW() {
  static unsigned long start = 0;

  if (digitalRead(p_TH) == HIGH) start = micros();
  else {
    PW_TH = micros() - start;
  }
}
1 Like

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