Avoid stepper motor being slowly by digitalRead

Hey guys,

I'm quite new to embedded programming and currently facing the following problem. I'm using an Arduino UNO to control a stepper motor (linear actuator) and up to ten different sensors (buttons, switches, capacity sensor...). For driving the stepper motor, I use the common driver shield A4988. The way this works for moving the stepper motor is the following:

  • setting sleep Pin to LOW
  • setting dir Pin to either zero or one
  • the speed of the actuator is determined by the pulse length of the signal at the step Pin. So setting it to HIGH, then waiting some microsenconds and setting it back to LOW makes the stepper motor move! In code:
digitalWrite(sleepPinZ, LOW);
digitalWrite(dirPinZ, dirZ);
digitalWrite(stepPinZ, HIGH);
delayMicroseconds(500);
digitalWrite(stepPinZ, LOW);
delayMicroseconds(500);

So in each computation loop, one "step" is made. This all worked fine up to the point where I've added a lot of different sensor, which require to call digital/analogRead during every loop and before the stepper motor makes the next step. Code:

void loop() {

   // serial stuff user can stop motor ////////////////////////////////////Not important
   ....
  //////////////////////////////////////////////////////////////////////////////////////////////
  
  int stat1 = digitalRead(5);
  int stat2 = digitalRead(6);
  int stat3 = digitalRead(7);
  int stat4 = digitalRead(8);
  int stat5 = digitalRead(9);
  int stat6 = ananlogRead(A0);
  //and so on...
  // if stat1 then...
  // if stat2 then...

   
   if(dirZ>-1 && !stop){
      digitalWrite(sleepPinZ, LOW);
      digitalWrite(dirPinZ, dirZ);
      digitalWrite(stepPinZ, HIGH);
      delayMicroseconds(500);
      digitalWrite(stepPinZ, LOW);
      delayMicroseconds(500);
   }else{
    digitalWrite(sleepPinZ, HIGH);
   }
}

What happens is that the stepper motor does not move smoothly anymore. It is quite slow and the reason for that is pretty clear to me: Getting the status of each sensor by using digital or analog read requires some time and therefore the time between each step of the motor becomes bigger => motor moves slower. However, I definitely need to check every sensor after each step of the motor, as some of the determine the stop point of motor.

Do you have some idea how this can be solved? Of course on a multicore system I simply would use threads. On the other hand, I know the interrupt function an arduino has, however, I couldn't bring it in line with the current situation.

Sorry for not providing a minimal working example - I think it would be too much code that might confuse the reader, therefore I just displayed the important parts :slight_smile:

Reading a digital pin is fast - in the order of a 4..6 microseconds. Reading the analog pin is much slower and in Arduino UNO it is about 10ksps, ie. 100 microseconds. You did not say how many analog pins you read. Instead of delayMicroseconds (500); you can read the pins and use micros () to keep track of when 500 microseconds have passed for the next step. This method requires perhaps a completely different programming logic. The other option I can think of is to speed up the ADC of the microcontroller but then the ADC works with lower accuracy.

The second example in Robin2's simple stepper code tutorial shows how to write non-blocking code for a stepper.

There is a way to read the analog pins asynchronously. Do you need to read all of them before each step?

1 Like

The A4988 stepper driver steps on the positive edge of the step signal. The step signal only needs to be high for a couple of microseconds, at most. The speed is set by the duration of the low part of the signal.

Thanks for answering! However, i think the problem has nothing todo with the stepper running blocking. The Problem lays in the fact that reading analog sensors takes too long and therefore there is "big" time between two steps of motor

Thanks. I May try to avoid using analoge pins and try to retunr back to digital ones

I have 2 analog capacitive sensor to determine the start and endpoint of the stepper motor:/ the other sensors must only be read in one of the end positions

If you write it as non-blocking, you could be reading the inputs while the step delay is happening. That would speed things up. And reduce the high time for the step pulse. It only needs to be high for 1us, not 500. You nearly double the speed if the pulses could happen that fast.

Non-blocking timing tutorials:
Blink without delay().
Beginner's guide to millis().
Several things at a time.

To get high speeds on a stepper you must use acceleration like is offered by the AccelStepper or MobaTools stepper libraries.

Once you home a stepper you should be able to keep exact track of where it is by counting the steps.

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