Controlling linear actuators without position indicator

Hello kind helper!

I’m not that experienced in using a while loop and I think this is the part where my code fails.

I am trying to control two linear actuators with a three pin ultrasonic sensor. The actuators (without position indicator) are connected to a motor controller. What I am trying to accomplish, is when an object comes within a 5 cm range of the sensor, the motors will activate for 100 milliseconds, stop and hold their position until the sensor detects that the object is >= 5 cm’s. When this happens the motors should go back to their original position.

What I am struggling with now is that the motors aren’t returning to their original position after the sensor detects an object that is >= 5 cm’s. I think this problem is caused by the way I update the ultrasonic sensor input in the while loop.

I hope you can help me!

int enA = 5;
int enB = 3;
const int in1 = 8;
const int in2 = 7;
const int in3 = 4;
const int in4 = 2;
const int pingPin = 12;

long previousMillis = 0;    
long interval = 1000; 
long time;
long startTime = 0;

//change ultrasonic sensor signal to distance
long microsecondsToCentimeters(long microseconds) {

  return microseconds / 29 / 2;
}  


void setup() {
  // initialize serial communication:
  Serial.begin(9600);
  pinMode(in1, OUTPUT);
  pinMode(in2, OUTPUT);
  pinMode(enA, OUTPUT);
  pinMode(enB, OUTPUT);
  pinMode(in3, OUTPUT);
  pinMode(in4, OUTPUT); 
}
 
}
void loop() {
  // Variabele cm
  long duration, cm;
  time = millis();

  // Activate
  pinMode(pingPin, OUTPUT);
  digitalWrite(pingPin, LOW);
  delayMicroseconds(2);
  digitalWrite(pingPin, HIGH);
  delayMicroseconds(5);
  digitalWrite(pingPin, LOW);

  // Signal read
  pinMode(pingPin, INPUT);
  duration = pulseIn(pingPin, HIGH);

  // to cm
  cm = microsecondsToCentimeters(duration);
  Serial.print(cm);
  Serial.print("cm");
  Serial.println();
 


  delay(100);
  //send pulse
 
  if (cm < 5) {
   digitalWrite(in1, HIGH);
    digitalWrite(in2, LOW);
    digitalWrite(in3, LOW);
    digitalWrite(in4, HIGH);
    analogWrite(enA, 255);
    analogWrite(enB, 255);
    delay(100);
    
    //keep position
    while (cm < 5){
     digitalWrite(in1, LOW);
    digitalWrite(in2, LOW);
    digitalWrite(in3, LOW);
    digitalWrite(in4, LOW);
    analogWrite(enA, 255);
    analogWrite(enB, 255);   
    cm = microsecondsToCentimeters(duration);
    }
    
  }
  
  //Back to original position
    if (cm > 5){
      digitalWrite(in1, LOW);
    digitalWrite(in2, HIGH);
    digitalWrite(in3, HIGH);
    digitalWrite(in4, LOW);
    analogWrite(enA, 255);
    analogWrite(enB, 255);
    }
    }
    while (cm < 5){
     digitalWrite(in1, LOW);
    digitalWrite(in2, LOW);
    digitalWrite(in3, LOW);
    digitalWrite(in4, LOW);
    analogWrite(enA, 255);
    analogWrite(enB, 255);   
    cm = microsecondsToCentimeters(duration);
    }

Nothing changes the value of duration while this loop is running, so if this loop ever starts, it will never end.

It is NOT necessary to keep writing the same values to the pins. Do that ONCE before the while loop starts.

I’m sure it will be blindingly obvious what you SHOULD be doing in the while loop.

PaulS:

    while (cm < 5){

digitalWrite(in1, LOW);
    digitalWrite(in2, LOW);
    digitalWrite(in3, LOW);
    digitalWrite(in4, LOW);
    analogWrite(enA, 255);
    analogWrite(enB, 255); 
    cm = microsecondsToCentimeters(duration);
    }



Nothing changes the value of duration while this loop is running, so if this loop ever starts, it will never end.

It is NOT necessary to keep writing the same values to the pins. Do that ONCE before the while loop starts.

I'm sure it will be blindingly obvious what you SHOULD be doing in the while loop.

This is exactly what I am struggling with. I am sure there is a really logical and simple explanation for this but I simply don’t know how to update the duration variable in the while loop.

the brackets in the code are definitely not set correctly. so you can read the code bad. can you post your entire (relevant) code and the serial output? And please comment the variables in the code (for example, what is enA or in1).

I think you have to first think about what you want to do exactly where in the code. I would definitely avoid a delay. It would be better, e.g. timebased execution and split the code.
e.g. that you measure the distance 5x per second and only start or stop the motors when the 5cm is over or under.

Fixed it. Used the Newping library and now everything works

This is exactly what I am struggling with. I am sure there is a really logical and simple explanation for this but I simply don't know how to update the duration variable in the while loop.

If you put the code to measure the distance into a function, that you call from loop(), you could call that same function from inside your while loop.