RC Car Project - Update 3

With most of the body completed it was now time to do some fine tuning to the steering and throttle. Steering adjustments were relatively straight forward, I wanted there to be a dead zone where the car could go straight even with the bike not being in perfect center. In order to achieve this I put in some simple logic to the code:


if (tilt <= 75 ) {
      tilt = tilt + 20;
      front.write(tilt);
}
else if (tilt >= 105) {
      tilt = tilt - 20;
      front.write(tilt);
}
else {
      front.write(90);
}


Originally, I didn’t include the ‘20’ constant which had the effect of making the steering swing wildly to catch up with the true bike position immediately after exiting the dead zone. The ’20’ constant reigned in that swing and made the steering feel much more natural.

With the steering completed, I turned my attention to the throttle. Ever since I picked this project up the throttle was ‘digital’, meaning it had only one speed forward and one speed for reverse (check the code below to see the old code). This made fine control nearly impossible so my goal here was to find a way to directly map the bike’s throttle to the speed of the car.


 //    if (throttleIN > 100 && brakeIN < 100) {
//      //drive = 99; //Value 1
//      //drive = 100;  //Value 2
//      //drive = 100.5;
//    }
//    if (throttleIN < 100 && brakeIN > 100) {
//      drive = 80;
//    }
//    if (throttleIN > 100 && brakeIN > 100) {
//      drive = 90;
//    }
//    if (throttleIN < 100 && brakeIN < 100) {
//      drive = 90;
//    }
//
//    rear.write(drive);


I spent several hours trying to figure out which values correlated to what speeds but nothing ever seemed to make sense (and still doesn’t). I kept thinking, “This would be so simple if I just could see the output from the original remote” but I couldn’t think of a clever way to do so. That was until I looked at the original receiver for the car. I realized that I could probably just plug an Uno into the throttle channel on the receiver and use the Arduino to print out the control values it sends based on the throttle from the original controller! I hooked everything up and wrote this simple sketch:


int ch1;
int ch1A;
int ch2;
int ch3;

void setup() {
  Serial.begin(115200);
  pinMode(A1,INPUT);
}

void loop() {
  ch1 = pulseIn(A0, HIGH);
  ch1A = pulseIn(A1, HIGH);
  ch2 = pulseIn(A2,HIGH);
  ch3 = pulseIn(A3, HIGH);

  Serial.print(ch1);
  Serial.print("\t");
  Serial.print(ch1A);
  Serial.print("\t");
  Serial.print(ch2);
  Serial.print("\t");
  Serial.print(ch3);
  Serial.println("");
}


Using the pulseIn function I was able to capture the throttle’s signal, in microseconds. Knowing that the servo library has a method for using microseconds as a control input I swapped the project from SoftwareServo to normal Servo and swapped the servo.write() instructions to servo.writeMicroseconds(). The new and improved sketch is below:


#include <EasyTransfer.h>
#include <Servo.h>

EasyTransfer ETin;

Servo front;
Servo rear;
//SoftwareServo front;
//SoftwareServo rear;

struct RECEIVE_DATA_STRUCTURE {
  int throttle;
  int brake;
  int steering;
  //  int boost;
  //  int kill;
};

RECEIVE_DATA_STRUCTURE rxdata;

void setup() {

  Serial.begin(9600);
  ETin.begin(details(rxdata), &Serial);

  front.attach(3);
  rear.attach(5);
  rear.write(40);

}

void loop() {

  for (int i = 0; i < 5; i++) {
    ETin.receiveData();
  //  SoftwareServo::refresh();

    int drive;
    int reverse;
    int tilt;
    int throttleIN = rxdata.throttle;
    int steeringIN = rxdata.steering;
    int brakeIN = rxdata.brake;
  
    tilt = map(steeringIN, 250, 730, 180, 0);
    //-----------------------------------NEW CODE-----------------
    drive = map(throttleIN, 0,835, 1470, 1700);
    reverse = map(brakeIN, 20,360, 1470, 1150);
    if(drive > 1470){
       rear.writeMicroseconds(drive);
    }
    else if(reverse < 1470){
      rear.writeMicroseconds(reverse);
    }
      //-----------------------------END OF NEW CODE-------------
//
//    if (throttleIN > 100 && brakeIN < 100) {
//      //drive = 99; //Value 1
//      //drive = 100;  //Value 2
//      //drive = 100.5;
//    }
//    if (throttleIN < 100 && brakeIN > 100) {
//      drive = 80;
//    }
//    if (throttleIN > 100 && brakeIN > 100) {
//      drive = 90;
//    }
//    if (throttleIN < 100 && brakeIN < 100) {
//      drive = 90;
//    }
//
//    rear.write(drive);

    if (tilt <= 75 ) {
      tilt = tilt + 20;
      front.write(tilt);
    }
    else if (tilt >= 105) {
      tilt = tilt - 20;
      front.write(tilt);
    }
    else {
      front.write(90);
    }
  }
}



As it turns out neutral throttle is 1470, full forward is ~2000 and full reverse is ~900. I made two simple maps and used them as the control signal enabling that smooth variable acceleration I was looking for. With that done I just need to set the top speed in both directions and clean the code up and the project should be all set.

-Andrew

No comments:

Post a Comment