Control ESC and Brushless Motor with Ultrasonic Sensor

I am trying to control the speed of a Brushless DC Motor based on the distance measured from an Ultrasonic Sensor. The ultrasonic sensor is reading distance without any issues, and the motor did spin using a potentiometer. The idea is to have the motor speed up and slow down automatically, but motor is not spinning or responding to this code. Any help is appreciated, thanks!

#include <Servo.h>
//initialization
Servo ESC_1 
int Trig_Pin = 7;
int Echo_Pin = 11;

void setup() {
//set up pins
  pinMode(Trig_Pin, OUTPUT);
  pinMode(Echo_Pin, INPUT);
  ESC_1.attach(9);
  Serial.begin (9600);
}
void loop() {
  if(GetDistance() >= 5 && GetDistance() <= 20){
// if distance is between 5 and 20, keep speed constant
    Set_Speed(0);
    delay(1000);
  }
  if(GetDistance() < 5){
// if distance is less than 5, slow down
    Speed_Down();
  }
  if(GetDistance() > 20){
// if distance is greater than 20, speed up
    Speed_Up();
  }
// else keep speed constant 
  Set_Speed(0);
  delay(1000);

//print the distance
  Serial.print(GetDistance());
  Serial.print("cm ");
  Serial.println();
  delay(250);
}

float GetDistance(){
// read sensor
  float Duration, Sensor_Distance;
  digitalWrite(Trig_Pin, LOW);
  delayMicroseconds(5);
  digitalWrite(Trig_Pin, HIGH);
  delayMicroseconds(10);
  digitalWrite(Trig_Pin, LOW);
  pinMode(Echo_Pin, INPUT);
  Duration = pulseIn(Echo_Pin, HIGH);
  Sensor_Distance = (Duration/2) / 29.1;
  return Sensor_Distance;
}
void Set_Speed(int Speed){
  int Angle = map(Speed, 0, 100, 0, 180); //scale the speed to use with the motor
  ESC_1.write(Angle); //send signal to ESC
}

void Speed_Up(){
//increase speed
  for(int S; S <= 70; S+=5){
    Set_Speed(S); //send new speed value (increasing)
    delay(1000);
  }
}

void Speed_Down(){
//slow down
  for(int S = 70; S > 0; S -= 5){
    Set_Speed(S); //send new speed value (decreasing)
    delay(1000);
  }
}

First post and you used code tags! Karma++

You mentioned that you have 2 sketches - one that reads the sensor and one that uses a pot to adjust the motor speed. Can you post those sketches?

I will find it easier to help you if I see what worked before tackling what is not working now.

I do want to make 2 notes about your current code.

  1. Only read the sensor once at the top of the loop. Something like this snippet:
void loop() {
  float DistanceReading;
  DistanceReading = GetDistance();
  if (DistanceReading >= 5 && DistanceReading <= 20) {
    // if distance is between 5 and 20, keep speed constant
    Set_Speed(0);
    delay(1000);
  }
  if (DistanceReading < 5) {
    // if distance is less than 5, slow down
    Speed_Down();
  }

Edit: I guess I should provide some reasoning for this. Only reading the sensor value at the top of the loop provides at least 2 advantages. First, it is quicker to read it once per loop. Second, it is safer. With your previous code, you could get a different value each time you read the sensor. So in a single loop, your tests might match on multiple different values. Best to read the value, then use that single reading for all the tests in the loop.

  1. Delays make your program unresponsive. You are likely spending lots of time in your speed_up and speed_down routines.

Oh, hey, your speed_up does not initialize S in the loop. I wonder what that does to execution?

From what I can see SetSpeed(0) does not keep the speed constant. It sets Angle to 0 or minimum. So either the code or the comments are wrong. To keep the speed constant you just need not write anything new to the ESC.

And since you change speed in blocking for loops you basically only ever run at two speeds write(0) and write(70). You ramp up and down but you can never stop at any intermediate speed. Is that what you intend?

Steve

Thank you for your help! Here what I had with the Pot and sensor. The speed of the motor was changing based on the pot.

#include <Servo.h>

Servo ESC1
int Trig_Pin = 7;
int Echo_Pin = 11;

void setup(){
   pinMode(Trig_Pin, OUTPUT);
   pinMode(Echo_Pin, INPUT);
   ESC1.attach(9);
}
void loop(){
  float Duration, Sensor_Distance;
  digitalWrite(Trig_Pin, LOW);
  delayMicroseconds(5);
  digitalWrite(Trig_Pin, HIGH);
  delayMicroseconds(10);
  digitalWrite(Trig_Pin, LOW);
  pinMode(Echo_Pin, INPUT);
  Duration = pulseIn(Echo_Pin, HIGH);
  Sensor_Distance = (Duration/2) / 29.1;
  int Val;
  int Angle;
  Val = analogRead(A5); //Pot was connected to pin A5
  Angle = map(Val, 0, 100, 0, 180);
  ESC1.write(Angle);
  Serial.println(Angle);
  Serial.println(Sensor_Distance);
  delay(500);
}

So in that last program why don't you just feed Sensor_ Distance (from the sensor) into the map() command instead of Val (from the pot). You'll need to adjust the map() to suit the range of values from Sensor_Distance.

Won't that do what you want, change speed with distance?

Steve