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?
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.
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.
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.
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.
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.
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.