Calibrating ESC with Arduino Mega 2560

I've bought a car from Redcat Racing (brushed motor) and connected the ESC to the Arduino. I'm using the Servo library to work with it, however, giving it the same value will give it a completely different speed after turning it off and on again. The posts I've found for calibration doesn't seem to work for this. How would I calibrate this?

Here’s the code I’ve been using to try to calibrate it

#include <Servo.h>

Servo esc;

void setup() {
  //Attach to the ESC
  esc.attach(A0);
  
  //Write the max value
  esc.write(180);
  delay(2000);
  //Write the min value
  esc.write(0);
  delay(2000);
  //Write value to start moving forwards
  esc.write(110);
}

void loop() {
}

Those values may be out of range for the ESC.

I suggest using microsecond writes instead of angles.

Try 2100us for high and 1900us for low. I think you'll have a better chance of success with these values than the extremes used by the servo library.

I tried with the code

#include <Servo.h>

Servo servo;

void setup() {
  Serial.begin(9600);
  servo.attach(A0);
  servo.writeMicroseconds(2100);
  Serial.println("Waiting 2 seconds...");
  delay(2000);
  Serial.println("2 seconds over...");
  servo.writeMicroseconds(1900);
  delay(2000);
}

void loop() {
  if(Serial.available()){
    int parsed = Serial.parseInt();
    servo.writeMicroseconds(parsed);
    Serial.println(parsed);
  }
}

However after trying multiple values from 1900 to 2100 in the loop area the motor didn’t start at all

The normal arming sequence is hold the throttle fully off for long enough.

  servo.write (0) ;
  delay (3000) ;

Remember throttles mechanically default to 90 degrees / 1500 microseconds, and generally ESCs won't arm if the throttle is at the default since that means you aren't in control. I've seen several brands of ESC that will arm if held at minimum for a few seconds. Experiment with a ESC tester is the usual approach, these little units are dead handy.

MarkT: Experiment with a ESC tester is the usual approach, these little units are dead handy.

What sort of tester to you have in mind?

Google gives me a wide variety of "ESC tester" results. Some are just the little servo testers (which I think are also dead handy).

Anything that generates a servo signal, the little ones are what I meant really as they are cheap and simple

MarkT: Anything that generates a servo signal, the little ones are what I meant really as they are cheap and simple

I also think those cheap ones are great.

I think would be good for testing ESCs. I think the ability to see the pulse length used would be really handy.

Of course one could make their own with a pot, 7-segment display and a microcontroller.

MarkT: The normal arming sequence is hold the throttle fully off for long enough.

  servo.write (0) ;
  delay (3000) ;

Remember throttles mechanically default to 90 degrees / 1500 microseconds, and generally ESCs won't arm if the throttle is at the default since that means you aren't in control. I've seen several brands of ESC that will arm if held at minimum for a few seconds. Experiment with a ESC tester is the usual approach, these little units are dead handy.

I got it to arm with the code

  servo.write(90);
  delay(3000);

After which it does a long beep (which according to the paper means that it self-calibrated and is ready to run). However, to say that it's volatile is an understatement. Giving it the value 80 will make it go backwards, 110 will make it go forwards, and giving it 80 again will make it stop. I can get it to go backwards successfully by doing 80 -> 90 -> 110 -> 90 -> 80 (90 being no throttle). But if I try the code:

void loop(){
  servo.write(110);
  delay(1000);
  servo.write(90);
  delay(1000);
  servo.write(80);
  delay(1000);
  servo.write(90);
  delay(1000);
}

then it will go forwards, stop, and go forwards again...

Sorry, I didn't read your original post carefully enough. Whenever I see ESC, I assume it's for a quadcopter or other aircraft.

I think you'll get better precision if you use milliseconds rather than degrees.

DuaneDegn:
Sorry, I didn’t read your original post carefully enough. Whenever I see ESC, I assume it’s for a quadcopter or other aircraft.

I think you’ll get better precision if you use milliseconds rather than degrees.

I’ll try it out again tomorrow

Note that typical RC units only output control signals for 90 deg range of movement instead of 180 deg. Using degree commands, this would be from 45 deg to 135 deg for low to high (or possibly high to low). Commands outside these bounds might be considered faulty not be accepted by the ESC for safety reasons. This range in microseconds would probably be 1000us to 2000us.

edit, below is some simple servo test code you can use to send commands from the serial monitor for testing.

// zoomkat 10-22-11 serial servo test
// type servo position 0 to 180 in serial monitor
// or for writeMicroseconds, use a value like 1500
// for IDE 0022 and later
// Powering a servo from the arduino usually *DOES NOT WORK*.

String readString;
#include <Servo.h> 
Servo myservo;  // create servo object to control a servo 

void setup() {
  Serial.begin(9600);
  myservo.writeMicroseconds(1500); //set initial servo position if desired
  myservo.attach(7, 500, 2500);  //the pin for the servo control, and range if desired
  Serial.println("servo-test-22-dual-input"); // so I can keep track of what is loaded
}

void loop() {
  while (Serial.available()) {
    char c = Serial.read();  //gets one byte from serial buffer
    readString += c; //makes the string readString
    delay(2);  //slow looping to allow buffer to fill with next character
  }

  if (readString.length() >0) {
    Serial.println(readString);  //so you can see the captured string 
    int n = readString.toInt();  //convert readString into a number

    // auto select appropriate value, copied from someone elses code.
    if(n >= 500)
    {
      Serial.print("writing Microseconds: ");
      Serial.println(n);
      myservo.writeMicroseconds(n);
    }
    else
    {   
      Serial.print("writing Angle: ");
      Serial.println(n);
      myservo.write(n);
    }
    Serial.print("Last servo command position: ");    
    Serial.println(myservo.read());
    readString=""; //empty for next input
  } 
}