Step motor position control

Hello everyone,

I would like some advice on controlling my step motor.
I have a NEMA17 1.8°/step controlled with a4988 driver and an arduino board UNO R4; I have integrated microstepping to make it move better because I need more precision.
I want it to make only 5 turns in one direction and then stop at a very precise position A.

With this code, my motor often makes maybe 2 revolutions and then stops at position B, and then starts again from that point to make 5 revolutions, how come?

// definizione dei PIN
const int dirPin = 5;
const int stepPin = 6;
const int motMS1Pin = 9;
const int motMS2Pin = 10;
const int motMS3Pin = 11;
const int stepForRevolution = 200*16;

// list of microstep config pin outputs in binary notation B[MS1][MS2][MS3]

byte microSteps[5] = {
  B000,  // full step
  B100,  // 1/2  step
  B010,  // 1/4  step
  B110,  // 1/8  step
  B111,  // 1/16 step
};

void setup() {
  // configure initial motor settings
  digitalWrite(stepPin, LOW);
  digitalWrite(dirPin, HIGH);

  pinMode(stepPin,OUTPUT); 
  pinMode(dirPin,OUTPUT);
  pinMode(motMS1Pin, OUTPUT);
  pinMode(motMS2Pin, OUTPUT);
  pinMode(motMS3Pin, OUTPUT);

  digitalWrite(motMS1Pin, bitRead(microSteps[4], 2));
  digitalWrite(motMS2Pin, bitRead(microSteps[4], 1));
  digitalWrite(motMS3Pin, bitRead(microSteps[4], 0));
}


int motSpeed = 62; // TODO: desired speed in rpm 62 is for 6500bph

void loop() {
  //Motore in direzione oraria
  digitalWrite(dirPin,LOW);
  
  // 45 giri del motore, cioè 5 della Filler
  for(int x = 0; x < 45*stepForRevolution; x++) {
    digitalWrite(stepPin,HIGH); 
    delayMicroseconds(motSpeed); 
    digitalWrite(stepPin,LOW); 
    delayMicroseconds(motSpeed); 
  }
  delay(10000); // pausa di un secondo
  }``

You get overflow in the for loop multiplication with 45. 45 * 200* 16 = 144000. Max value of an int is 32767.

1 Like

if I use 45, the motor does 5 rounds. what type of function can i use?

Railroader explained the problem.
Use long instead of int.

1 Like

Is that correct for Uno R4?

Be aware, that microstepping doesn't increase precision. It let the motor move more smoothly with less noise, but the microstep positions are much less accurate than fullstep positions. In fact, the motor may not move at all if you only make a few microsteps (Depending on the load of the motor).

The UNO R4 is a 32bit processor, so int is 32bit wide and will not overflow at 32767. ( As @PaulRB already pointed out )

If that affects the capacity on an int, I've learned something new.
How will the compiler know that? Just checked the setup in the IDE and it shows "Arduino UNO" but not any R4.
If my memory works even in the large IBM360 an int was 16 bits.

The compiler obviously must know for which microprocessor it is compiling. How will it create machine code otherwise? And so it must also know the word length of the MCU. An int is the native wordlength of the MCU, but at least 16 bits.

yes, the motor can get that fast without acceleration

How is that told in the IDE set up?

You have to select the board/MCU in the Tools menue before compiling. Don't you do that? Or are you only using UNO R3? That are IDE basics ... :thinking:
But we are getting off topic ...

Which one do You select?
Yes, off topic.

Of course the board that is connected and on which the sketch is to run. I have many different ones. Maybe you should open a new topic if there are more questions about this.

Done!

To make sure the variable doesn't overflow, you can declare it as int32_t or print its size :

  Serial.print("sizeof(int) = ");
  Serial.println(sizeof(int));

B000 is a valid binary representation although I prefer 0b000
Here is a Wokwi simulation of your setup, it works except I didn't verify (understand) why it makes 808 steps per loop :grinning:
EDIT : it now works, see post #17

It does not really work :wink: . Your simulation uses an Arduino Nano, which is a 8-bit device. So int is 16 bit wide. That means this expression:
45 * stepPerRevolution
leads to an overflow. You must use
45UL * stepPerRevolution
on a Nano to avoid this.

3 Likes

You're right, even compiler math (or is it not ? what about #define instead of const ... ?) can overflow !

I modified the program accordingly and it works, thanks.

If you declare it like this

const unsigned long stepForRevolution = 200*16;

The compiler will take care of it for you

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