Combining Motor Steper with Ultrasonic Sensor. Help me with the code please

I would greatly apreciate some help in coding.

I am using Ultrasonic Sensor (HC-SR04), a stepper motor, and two limit switch in the end of the motor track.

my plan is to control the stepper motor using the ultrasonic sensor.
if the distance is more than 20 cm, it should moves to the left (DIR HIGH).
if the distance is less than 20 cm, it should moves to the right (DIR LOW).

and if the motor moves way too far (it touchs the limit switch), it should stops the movement.

i've been working on this program for a long time, but for some reason the code that i made doesn't work. My stepper motor doesn't move at all, i don't know why.

could you guys kindly check my program and help me with this issues?


// Define stepper motor and ultrasonic sensor connections:
#define echoPin 6   // attach pin D6 Arduino to pin Echo of HC-SR04
#define trigPin 7   // attach pin D7 Arduino to pin Trig of HC-SR04
#define dirPin 10    // attach pin D2 Arduino to pin DIR+
#define stepPin 11   // attach pin D3 Arduino to pin STEP+


long duration;      // variable for the duration of sound wave travel
int distance;       // variable for the distance measurement

unsigned long curMillis;
unsigned long prevStepMillis = 0;
unsigned long millisBetweenSteps = 25; // milliseconds

int limitswitch1  = 0;  
int limitswitch2  = 0;  

const int button8 = 8;    // right limit switch (pin8)
const int button9 = 9;    // left limit switch  (pin9)

void setup() {
  // Declare pins as output:
  pinMode(stepPin, OUTPUT);
  pinMode(dirPin, OUTPUT);
   Serial.begin(9600);     
  pinMode(button8, INPUT_PULLUP);   // right limit switch as input
  pinMode(button9, INPUT_PULLUP);   // left limit switch as input
  pinMode(trigPin, OUTPUT); // Sets the trigPin as an OUTPUT
  pinMode(echoPin, INPUT);
  limitswitch1  = digitalRead(button8);   // limit swith kanan pada PIN 8
  limitswitch2  = digitalRead(button9);   // limit swith kiri pada PIN 9
}

void loop() {
    digitalWrite(trigPin, LOW);
    delayMicroseconds(2);
    curMillis = millis();
    reading();
    action();
    
}
 

void reading() {
  digitalWrite(trigPin, LOW);
  delayMicroseconds(2);
  // Sets the trigPin HIGH (ACTIVE) for 10 microseconds
  digitalWrite(trigPin, HIGH);
  delayMicroseconds(10);
  digitalWrite(trigPin, LOW);
  // Reads the echoPin, returns the sound wave travel time in microseconds
  duration = pulseIn(echoPin, HIGH);
  // Calculating the distance
  distance = duration * 0.034 / 2; // Speed of sound wave divided by 2 (go and back)
  // Displays the distance on the Serial Monitor
  Serial.print("Distance: ");
  Serial.print(distance);
  Serial.println(" cm");
}
void action(){
if(distance > 20 && limitswitch1 == 1 && limitswitch2 == 1) {
  digitalWrite(dirPin, HIGH);
  startmotor();}

if(distance < 20 && limitswitch1 == 1 && limitswitch2 == 1) {
  digitalWrite(dirPin, LOW);
  startmotor();}
  
 if (digitalRead (button8) == 0)     // if right limit switch is LOW (on)
           {
           digitalWrite (stepPin, LOW);
           }
     if (digitalRead (button9) == 0)     // if left limit switch is LOW (on)
           {
             digitalWrite (stepPin, LOW);
           }

    
}
void startmotor(){
if (curMillis - prevStepMillis >= millisBetweenSteps) {
        prevStepMillis = curMillis;
        digitalWrite(stepPin, HIGH);
        digitalWrite(stepPin, LOW);
        
  }
}

Two microseconds is way too short a time for a thing to happen, especially step a stepping motor.

1 Like

Hi, thanks for replying!

the two microseconds delay shouldn't affect the stepper since i step my stepper motor in startmotor(), or does it? i really don't understand

@adhityaj, your topic has been moved to a more suitable location on the forum. Installation and Troubleshooting is not for problems with (nor for advise on) your project :wink: See About the Installation & Troubleshooting category.

That function is indeed problem. As it stands it will never start the motor because it looks only once at the millis counter, and if it has not advanced enough it will simply return. It needs to wait until the time has expired and then give a pulse. Your use of millis here is wrong it might as well be a simple delay.

The loop function resets the value of the current millis variable every time so your motors never get stepped.

1 Like

Hi, im actually new at this forum. Thank you so much!

I use millis because i've tried using delayMicroseconds-- it worked but the sensor needs to wait until the delay ends, so I decided to use millis.

But, to be honest, i actually don't really understand how the millis works.

Sir, i really need your help.

Hi,
Has the suggested reason in post#6 fix your problem.

If not;
Have you developed your code in stages?
Have you written code that JUST tests the ultrasonic and displays the result in the IDE monitor?
Have you written code that JUST makes your stepper move back and forth.
Have you written code that JUST reads your limit switch and displays the result in the IDE monitor?

Have you checked all your I/O indepedently to prove your circuit?

Can you please post a circuit diagram, not a Fritzy image?

Have you looked at NewPing library to communicate with your ultrasonic?
https://playground.arduino.cc/Code/NewPing/
Have a read and look at the examples.

Thanks.. Tom... :grinning: :+1: :coffee: :australia:

1 Like

Hi Tom, thanks for replying.

i've tried it separately,
ultrasonic and the result is fine.
limit switch works as it should be.
stepper motor can move back and forth when it use delayMicrosecond.

the problem is-- if im using the delayMicrosecond to step my stepper, it will interrupt my ultrasonic sensor (the sensor waits until the delay ends).

so then im using millis, and i think i didn't use it properly.

i really need help for using millis to combine ultrasonic and stepper motor

Hi,
Have you looked at NewPing?

What stepper controllers are you using?

Thanks.. Tom... :grinning: :+1: :coffee: :australia:

@adhityaj you ticked solution on reply #6, that means you consider the problem is solved. If that is not the case untick that box and carry on asking questions.

okay, unticked. I still confused how to use millis to step my motorstepper

So post the code again where you have included the advise you have already been given.

The problem would seem to be that both the stepping and the distance sensor needs to be written as a state machine in order for it to multitask successfully.
You are using pulseIn which is blocking code.

I think this is what you are trying to do:

// Define stepper motor and ultrasonic sensor connections:
const byte EchoPin = 6;   // attach pin D6 Arduino to pin Echo of HC-SR04
const byte TriggerPin = 7;   // attach pin D7 Arduino to pin Trig of HC-SR04

// Speed of sound:
// 343 meters per second 
// == 0.002915452 seconds per meter
// == 2915.452 microseconds per meter
const float MicrosecondsPerCM = 29.15452;
const float MicrosecondsPerRoundTripCM = MicrosecondsPerCM * 2;  // ~58.3

const int RightLimitPin = 8;    // right limit switch (pin8)
const int LeftLimitPin = 9;    // left limit switch  (pin9)

const byte DirectionPin = 10;    // attach pin D2 Arduino to pin DIR+
const byte StepPin = 11;   // attach pin D3 Arduino to pin STEP+

unsigned long PreviousStepMillis = 0;
unsigned long MillisBetweenSteps = 25; // milliseconds

void setup()
{
  Serial.begin(115200);
  delay(200);

  // Declare pins as output:
  pinMode(StepPin, OUTPUT);
  pinMode(DirectionPin, OUTPUT);

  pinMode(RightLimitPin, INPUT_PULLUP);   // right limit switch as input
  pinMode(LeftLimitPin, INPUT_PULLUP);   // left limit switch as input

  pinMode(TriggerPin, OUTPUT); // Sets the TriggerPin as an OUTPUT
  pinMode(EchoPin, INPUT);

}

void loop()
{
  unsigned long currentMillis = millis();

  boolean hitRightLimit  = digitalRead(RightLimitPin) == LOW;
  boolean hitLeftLimit  = digitalRead(LeftLimitPin) == LOW;

  // Do nothing if either limit switch is pressed
  if (hitRightLimit || hitLeftLimit)
    return;

  digitalWrite(TriggerPin, LOW);
  delayMicroseconds(2);
  // Sets the TriggerPin HIGH (ACTIVE) for 10 microseconds
  digitalWrite(TriggerPin, HIGH);
  delayMicroseconds(10);
  digitalWrite(TriggerPin, LOW);
  // Reads the EchoPin, returns the sound wave travel time in microseconds
  unsigned long duration = pulseIn(EchoPin, HIGH, 30000ul);
  // Calculating the distance
  int distanceCM = duration / MicrosecondsPerRoundTripCM;


  // Displays the distance on the Serial Monitor
  Serial.print("Distance: ");
  Serial.print(distanceCM);
  Serial.println(" cm");

  // Set the direction pin to move toward 20cm.
  digitalWrite(DirectionPin, (distanceCM > 20) ? HIGH : LOW);

  // Step periodically
  if (currentMillis - PreviousStepMillis >= MillisBetweenSteps)
  {
    PreviousStepMillis = currentMillis;
    digitalWrite (StepPin, LOW);
    digitalWrite (StepPin, HIGH);
  }
}

From Direct Message:

This would be the place to ask questions.

Hello Sir!

Ive tried your code and it works as I want. Thank you so much for it.

but the problem is, I dont understand how to adjust the speed of the motor.

Change the number of milliseconds between steps:

The initial value of 25 gives about 40 steps per second (1000 / 25).

I see....
So, the maximum speed that i can get is (1000/1), isn't it?

Is that value the right way round?

That is the maximum speed you can generate pulses for your motor. If the motor will move that fast is another matter. That depends on a lot of factors, like the stall torque and the load on the motor as well as how it is powered.

With a stepping motor the faster you pulse it the lower the torque is. The torque is a maximum when it is not moving. You can pulse it so fast that there comes a point where the actual torque is below the stall torque and then it will not move any more.

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