Run stepper motor and ultrasonic sensor simultaneoulsy.

I am using a stepper motor of 30 steps per revolution. I am also using an ultrasonic sensor for mapping the environment. I could only collect 30 values from the sensor in a revolution. This is because after each step I am reading the sensor value.

Is there any way I could run the stepper motor in the background and continuously collect sensor values?
Just like you can run a DC motor by analogWrite function and forget about it and do anything while it is running, is the same thing possible with a stepper motor?

Will I have to use a servo motor to run them simultaneously?

The answer is almost certainly yes - but without seeing your program and details of the stepper motor driver you are using I cannot be specific.

...R

It is a Bipolar stepper motor. I am using L293D driver to run it. This is my code:

After each step, it displays the sensor value. I want them to happen simultaneously so that I could read values when it is performing the steps and not after each step.

#include <Stepper.h>

// the number of steps on your motor
#define STEPS 30

// create an instance of the stepper class, specifying
// the number of steps of the motor and the pins it's
// attached to
Stepper stepper(STEPS, 8, 9, 10, 11);

// Variables for ultrasonic sensor
// defines pins numbers
const int trigPin = 5;
const int echoPin = 6;

// defines variables
long duration;
float distance;

void setup() {
  // set the speed of the motor to 30 RPMs
  stepper.setSpeed(30);
  
  //setup for the sensor
  pinMode(trigPin, OUTPUT); // Sets the trigPin as an Output
  pinMode(echoPin, INPUT); // Sets the echoPin as an Input
  
  Serial.begin(9600); // Starts the serial communication
}

void readSensor() {
    //reads the value of ultrasonic sensor and prints it
    
    // Clears the trigPin
    digitalWrite(trigPin, LOW);
    delayMicroseconds(2);
    // Sets the trigPin on HIGH state for 10 micro seconds
    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;
    // Prints the distance on the Serial Monitor
    Serial.print("Distance: ");
    Serial.println(distance);
}

void loop() {
  
  //clockwise rotation
  for(int i = 0; i < 30; i++)
  {
    // move one step
    stepper.step(1);
    readSensor();
  }
  //anticlockwise rotation
  for(int i = 0; i < 30; i++)
  {
    // move one step in reverse
    stepper.step(-1);
    readSensor();
  }
  
}

Your code seems to move 1 step and read the sensor, then 1 step and 1 read.

There might be neater ways to program it but an Arduino cannot do two things at once - it can just do them one after the other very quickly so that they appear simultaneous.

In what way is your program insufficient? I guess I don't understand what you want that is different.

Maybe have a look at the demo Several Things at a Time

...R

stepper.step() blocks the program until the stepper moves a step. So while it is taking the step I cannot do anything. But I want to take sensor reading even while it is taking a step and not only after steps.

Is there any way to do it?

keestu:
stepper.step() blocks the program until the stepper moves a step.

Executing a single step probably only takes a few microseconds - is that too long to wait? The slowness is mainly due to the use of the L298 because it imposes unnecessary computations on the Arduino.

And if you use a specialized stepper driver such as a Pololu A4988 or DRV8825 it would only take a single digitalWrite() - or if time is really important it could be done with a single instruction taking 0.0625 µsecs using port manipulation.

You need to tell us more about your project so we can understand the significance of what you are saying.

...R
Stepper Motor Basics
Simple Stepper Code

Thank you! I think I will proceed the way it works now as it is fast, and making it simultaneous won't have much effect.

Just for the knowledge, I wanted to know if there was any way to do that. I will look for these drivers if still needed. Thank you again :slight_smile:

This kind of thing might help but would need tuning.
It only shows how getting more sensor reads per step might be done.
Possible problem is if sensor read might make stepper step so late it runs badly.

Not compiled or tested.

char  stepperStepDirection; // default 0, can be -1, 0, or 1
byte  stepperIndex;
byte  stepperSteps = 30;

unsigned long stepperStepStartMicros;  // using micros() because millis() does skip values
unsigned long stepperStepTimeMicros = 5000;  // if accurate time is important, use micros()!

unsigned long sensorStartMicros;
unsigned long sensorTimeMicros = 500;

.................

void loop() 
{
  if ( micros() -  stepperStepStartMicros >= stepperStepTimeMicros )  // run stepper on time
  {
    if ( stepperStepDirection )  // non-zero is true, allows for the possibility to stop the stepper in later version
    {
      stepper.step( stepperStepDirection );
      if ( stepperIndex == stepperSteps )
      {
        stepperIndex = 0;
        stepperStepDirection *= -1;  // reverses stepper motion
      }
    }
    stepperStepStartMicros += stepperStepTimeMicros; // till next time
  }

  if ( micros() -  sensorStartMicros >= sensorTimeMicros ) //   // run sensor on its own time, not stepper's
  {
    readSensor();
    sensorStartMicros += sensorTimeMicros; // do it again later
  }
}

Robin2:
The slowness is mainly due to the use of the L298 because it imposes unnecessary computations on the Arduino.

Can those computations be pre-calculated and tabled?
In that case it would take 3 cycles per byte to fetch and maybe 100-200 (at 16 per usec) more if interpolation is needed, but that assumes using 16 bit integers at most -- no floats or longs.

GoForSmoke:
Can those computations be pre-calculated and tabled?

I guess. IIRC there are four (or is it 8 ) permutations of power for the 2 pairs of wires for the stepper coils. So that would enable them to stored as 4 bits in each of 4 (or 8 ) bytes in a small array. Then the code just needs to loop around the array and use PORTx to output the data if the pins used to control the motor are carefully chosen so they are all on one PORT.

It may well be that the stepper library does this sort of thing behind the scenes - although it does not impose limitations on the pins that can be used.

With a specialized stepper driver it is only necessary to produce a HIGH followed by a LOW on the step pin.

...R

Robin2:
I guess. IIRC there are four (or is it 8 ) permutations of power for the 2 pairs of wires for the stepper coils. So that would enable them to stored as 4 bits in each of 4 (or 8 ) bytes in a small array. Then the code just needs to loop around the array and use PORTx to output the data if the pins used to control the motor are carefully chosen so they are all on one PORT.

It may well be that the stepper library does this sort of thing behind the scenes - although it does not impose limitations on the pins that can be used.

With a specialized stepper driver it is only necessary to produce a HIGH followed by a LOW on the step pin.

...R

With buttons debounced in hardware I need less code too but common practice is to support the cheaper hardware at the expense of software. The L298 code does not have to be slow or big or limiting but I getcha, the more integrated units can run on PWM.

GoForSmoke:
but I getcha, the more integrated units can run on PWM.

Just to avoid any confusion, a stepper motor drivers are not controlled by PWM. The pulse width is normally constant at about 10µsecs and the speed of the motor is controlled by the interval between pulses.

...R

2 Uno pins have 980/sec PWM, 1/256th of that is 4us but the 1ms pulse seems too short for getting the stepper started.
Oh well, too bad.

How big (degrees or radians) is a stepper step?
How wide (degrees or radians) is the ultrasound beam?

AWOL:
How big (degrees or radians) is a stepper step?
How wide (degrees or radians) is the ultrasound beam?

If the thing doing the scan and/or things being scanned could be moving you'd want continuous scanning but otherwise you've pointed out a possible flaw to the scheme.