motor issues

hi all
im using a nema 17 motor and im facing a problem that i dont understand what is happening, im trying to achive de motor to have two buttons switch 1 to move counter clockwise other clockwise and then to convert that into degrees 0 to 360 degree output serial monitor

this the code im using

#define MotorDir  6
#define MotorStep 7
#define ButaoA A1
#define ButaoB A0

int msDelay = 5
int ButaoEstadoA = 0; 
int ButaoEstadoB = 0; 

int count = 0;

int n; 

void setup() {
  Serial.begin(9600); 
  pinMode(MotorDir, OUTPUT);
  pinMode(MotorStep, OUTPUT);
  pinMode(ButaoA, INPUT); 
  pinMode(ButaoB, INPUT);
}

void loop() {

  int degree = (count * 1.8) ; 
  

  ButaoEstadoA = digitalRead(ButaoA);
  ButaoEstadoB = digitalRead(ButaoB);

  Serial.print("    count=");
  Serial.print(count);
  Serial.print("    graus=");
  Serial.println(degree);

  if (ButaoEstadoA == HIGH)
  {
    digitalWrite(MotorDir, HIGH);

    for ( n = 0; n <= 1; n++) 
    {
      digitalWrite(MotorStep, HIGH);
      delay(msDelay);
      digitalWrite(MotorStep, LOW);
      delay(msDelay);// faz um delay

      if (count >= 200) {
        count = 0; 
        degree = 0;
      }
      count = count + n;
    }
  }
  
  else if (ButaoEstadoA == LOW) { 
    {
      digitalWrite(MotorStep, LOW);
    }



    if (ButaoEstadoB == HIGH)
    {
      digitalWrite(MotorDir, LOW);
      for (n = 0; n <= 1; n++)
      {
        digitalWrite(MotorStep, HIGH);
        delay(msDelay);// faz um delay
        digitalWrite(MotorStep, LOW);
        delay(msDelay);

        if (count >= -1) {

       //   how to do it?
        }
        count = count - n;
      }



    }
    else if (ButaoEstadoB == LOW) 
    {
      digitalWrite(MotorStep, LOW);
    }
  }
}

at this moment is counting down when goes below 0 degree counter clockwise i just cant figuer out how to convert that into degrees 360.359,358 and so on...

another problem im facing is the revolutions count it seems that the motor is moving 100 steps count to make a 360 degree, when it should be 200 steps, i have tryed a simpler code without buttons etc.. and makes 200 step to do the 360 degree..

Hi,

What model Arduino are you using?

What is the part number of the stepper motor?
Can you post a link to the datasheet?

Are you using a stepper controller module, if so what make and model is it?
Can you post a link to the datasheet?

What power supplies are you using?

Can you please post a copy of your circuit, in CAD or a picture of a hand drawn circuit in jpg, png?
NOT A FRITZY picture.

Thanks.. Tom. :slight_smile:

You don't need FOR if you just want a single step. In fact I think your FOR is causing 2 steps to happen (when n is 0 and when n is 1) but only incrementing the count by 1.

If you are using the FOR loop in another example to run through several steps then the line

count = count + n;

will almost certainly be wrong.

In all cases I think it should be

count = count + 1;

Converting steps to degrees will require using float variable and multiplying the number of steps be 1.8. Something like (I'm not sure of the float syntax as I have never had to use them in my Arduino programs)

float degrees;
degrees =  count * 1.8;

...R

my shchematic is hereTom

 if (ButaoEstadoA == HIGH)
  {
    digitalWrite(MotorDir, LOW);
   digitalWrite(MotorStep, HIGH);
    delay(msDelay);// faz um delay
    digitalWrite(MotorStep, LOW);
    delay(msDelay);

    if (count == 200) {
      count = 0; 
      degree = 0;
    }
    count = count+ 1;
  }
 else  {
    {
      digitalWrite(MotorStep, LOW);
    }
    if (ButaoEstadoB == HIGH)
    {
      digitalWrite(MotorDir, HIGH);

      digitalWrite(MotorStep, HIGH);
      delay(msDelay);// faz um delay
      digitalWrite(MotorStep, LOW);
      delay(msDelay);

      if (count == 0) {
        count = 200;
        degree = 360;
    }
     count = count - 1;
    }
    else if (ButaoEstadoB == LOW) 
    {
      digitalWrite(MotorStep, LOW);
    }

Thanks robin, i have removed the( for) has you sugested and it seems that is working, but is decrementing 2 in2 360,358,356 etc... and also incrementing 2 by 2

Ok it seems is cause of the delay if i slow down count correct if is to fast counts 2 by 2..
another issue i find is every time arduino is power up motor will move for a position, for what i understand motor is moving until finds trigger correct?
is there anyway to fix this?

You need to post your latest code.

I forgot to attach these links to my earlier reply

...R
Stepper Motor Basics
Simple Stepper Code

void setup() 
{
  Serial.begin(9600); problemas)
  pinMode(MotorDir, OUTPUT);
  pinMode(MotorStep, OUTPUT);
  pinMode(ButaoA, INPUT);
  pinMode(ButaoB, INPUT);
 pinMode(enable, OUTPUT);

}

void loop() {

  float degree = (count * 1.8) ; 

  digitalWrite(enable,HIGH);

  ButaoEstadoA = digitalRead(ButaoA);
  ButaoEstadoB = digitalRead(ButaoB);

  Serial.print("    count=");
  Serial.print(count);
  Serial.print("    graus=");
  Serial.println(degree);

  

  if (ButaoEstadoA == HIGH)
  {
    digitalWrite(enable,LOW);

    digitalWrite(MotorDir, LOW);
    digitalWrite(MotorStep, HIGH);
    delay(msDelay);// faz um delay
    digitalWrite(MotorStep, LOW);
    delay(msDelay);

    if (count == 200) {
      count = 0; 
      degree = 0;
    }
    count = count+ 1;
  }

 else  
   
 {
      digitalWrite(MotorStep, LOW); 
    }
 

    if (ButaoEstadoB == HIGH)

    {
      digitalWrite(enable,LOW);

      digitalWrite(MotorDir, HIGH);
      digitalWrite(MotorStep, HIGH);
      delay(msDelay);// faz um delay
      digitalWrite(MotorStep, LOW);
      delay(msDelay);// faz um delay

      if (count == 0) {
        count = 200;
        degree = 360;
    }
     count = count - 1;
    }
    else if (ButaoEstadoB == LOW) 
    {
      digitalWrite(MotorStep, LOW);
  }
}

That is not a complete program - the definitions of the variables are missing.

I suspect your strange counting has to do with the interaction between how long you press the button and how fast the motor moves. How do you want it to work?

It may help to stop spurious steps if you use digitalWrite() to set the appropriate values in setup().

...R

Hi,
Thanks, your circuit diagram.


Tom.... :slight_smile:

Hi,

another issue i find is every time arduino is power up motor will move for a position,

Connect the ENABLE pin up to an output.
In setup()
the very first line

pinMode(EnablePin, OUTPUT);
digitalWrite(EnablePin,HIGH);

This will disable the stepper driver.
Then the very last line of setup()

digitalWrite(EnablePin,LOW);

This will then enable the driver
Tom... :slight_smile:

thanks Robin and Tom for all the suport
not sure if im using the enable correctly or if there is anything i could improve the code
all seems to work, the bigest issue i find at this moment is that somethimes when i press the butons or when i power arduino, the steps seems to give a jump is like the motor is finding the trigger and then works ok, no idea if this is normal for the stepers or if is something in code missing or wrong, the main idea was to have a system that would measure degrees as precisely has possible for then i try to implement that in a telescope.

Very great job Robin on the posts on the Stepper Motor Basics ,Simple Stepper Code :slight_smile:

here is the full code Robin

#define MotorDir  6
#define MotorStep 7
#define ButaoA A1
#define ButaoB A0
#define  enable 8

int msDelay = 10;
int ButaoEstadoA = 0; 
int ButaoEstadoB = 0;
int count = 0;


void setup() 
{
  Serial.begin(9600); 
  pinMode(MotorDir, OUTPUT);
  pinMode(MotorStep, OUTPUT);
  pinMode(ButaoA, INPUT);
  pinMode(ButaoB, INPUT);
 pinMode(enable, OUTPUT);
 digitalWrite(enable,HIGH);

}

void loop() {

  float degree = (count * 1.8) ; 


  ButaoEstadoA = digitalRead(ButaoA);
  ButaoEstadoB = digitalRead(ButaoB);

  Serial.print("    count=");
  Serial.print(count);
  Serial.print("    graus=");
  Serial.println(degree);

  

  if (ButaoEstadoA == HIGH)
  {
    digitalWrite(enable,LOW);

    digitalWrite(MotorDir, LOW);
    digitalWrite(MotorStep, HIGH);
    delay(msDelay);// faz um delay
    digitalWrite(MotorStep, LOW);
    delay(msDelay);

    if (count == 200) {
      count = 0; 
      degree = 0;
    }
    count = count+ 1;
  }

 else  
   
 {
      digitalWrite(MotorStep, LOW); 
    }
 

    if (ButaoEstadoB == HIGH)

    {
      digitalWrite(enable,LOW);

      digitalWrite(MotorDir, HIGH);
      digitalWrite(MotorStep, HIGH);
      delay(msDelay);// faz um delay
      digitalWrite(MotorStep, LOW);
      delay(msDelay);// faz um delay

      if (count == 0) {
        count = 200;
        degree = 360;
    }
     count = count - 1;
    }
    else if (ButaoEstadoB == LOW) 
    {
      digitalWrite(MotorStep, LOW);
  }
}

meph328:
the main idea was to have a system that would measure degrees as precisely has possible for then i try to implement that in a telescope.

The normal procedure with stepper motors is to initialize things by moving the motor to a position where it triggers a limit switch that the Arduino uses to identify the ZERO position.

I can't figure from your description whether your motor twitches by a single step (which would not be unusual) or whether it moves several unwanted steps.

...R

Robin i have added a button to the code that will change betwen micro steps mode 1 full step, 2 half step and 3 sixteenth step, witch is working fine, however im facing a problem that couldnt find solution yet, is that the counter would need to be updated to the selection i will chose, what i mean is imagening that im in full step and will count 200 steps to do 360 degree and lets imagen im in 178 count and i change for half step mode it will remain at 178 counts and it would need to be 178*2 i have tryed but it would keep incrementing by 2 then by 2 and so on, i would need to just convert 1 time to updade the mode im in to the correct degress
here is my code

#define MotorDir  6
#define MotorStep 7
#define ButaoA 9
#define ButaoB 10
#define ButaoC 5
#define  enable 8
#define MS1 11
#define MS2 12
#define MS3 13

int msDelay = 10; 
int ButaoEstadoA = 0; 
int ButaoEstadoB = 0; 


int count = 0;
int MicroPassos;
int Micro;

int ButaoEstadoC;
int pressC = 1;
int val = 1;


void setup() {
  Serial.begin(9600);
  pinMode(MotorDir, OUTPUT);
  pinMode(MotorStep, OUTPUT);
  pinMode(ButaoA, INPUT_PULLUP);
  pinMode(ButaoB, INPUT_PULLUP);
  pinMode(ButaoC, INPUT_PULLUP);
  pinMode(enable, OUTPUT);
  pinMode(MS1, OUTPUT);
  pinMode(MS2, OUTPUT);
  pinMode(MS3, OUTPUT);
  digitalWrite(enable, HIGH);
  ButaoEstadoC = digitalRead(ButaoC);
}

void loop() {
  float degree = (count * 1.8) / Micro ; 
  
  ButaoEstadoA = digitalRead(ButaoA);
  ButaoEstadoB = digitalRead(ButaoB);
  
  val = digitalRead(ButaoC);

  if (val != ButaoEstadoC) 
  {
    if (val == LOW) {
      pressC++;
      if (pressC > 3) {
        pressC = 1;
      }
    }
  }
  if (pressC == 1) {
    MicroPassos = 200;
    Micro = 1;
    digitalWrite(MS1, LOW);
    digitalWrite(MS2, LOW);
    digitalWrite(MS3, LOW);
    
  }
  if (pressC == 2) {
    MicroPassos = 400;
    Micro = 2;
    digitalWrite(MS1, HIGH);
    digitalWrite(MS2, LOW);
    digitalWrite(MS3, LOW);
  }
 if (pressC == 3) {
    MicroPassos = 3200;
    Micro = 16;
    digitalWrite(MS1, HIGH);
    digitalWrite(MS2, HIGH);
    digitalWrite(MS3, HIGH);
  }
  ButaoEstadoC = val;
 
  Serial.print("    count=");
  Serial.print(count);
  Serial.print("    graus=");
  Serial.println(degree);
  Serial.print("    buttons press=");
  Serial.print(pressC);


  if (ButaoEstadoA == LOW)
  { digitalWrite(enable, LOW);
    digitalWrite(MotorDir, LOW);
    digitalWrite(MotorStep, HIGH);
    delay(msDelay);
    digitalWrite(MotorStep, LOW);
    delay(msDelay);/

    if (count == MicroPassos) {
      count = 0; 
      degree = 0;
    }
    count = count + 1;
  }
  else 
  {
    digitalWrite(MotorStep, LOW);
    digitalWrite(enable, HIGH);
  }
 
  if (ButaoEstadoB == LOW)
  { digitalWrite(enable, LOW);
    digitalWrite(MotorDir, HIGH);/

    digitalWrite(MotorStep, HIGH);
    delay(msDelay);// faz um delay
    digitalWrite(MotorStep, LOW);
    delay(msDelay);

    if (count == 0) {
      count = MicroPassos;
      degree = 360;
    }
    count = count - 1;
  }
  else if (ButaoEstadoB == LOW) 
  {
    digitalWrite(MotorStep, LOW);
}

I think you are now running into the common problem of having all your code in the loop() function rather than having separate functions for the different activities.

For example if you have a function called changeMicrosteps() you could easily include in that the necessary code to adjust the step count - or have the changeMicrosteps() function call another function to changeStepCountBase()

Have a look at Planning and Implementing a Program

You could add code to your existing program to change the count base when you change the microstep basis but it is just going to wind up as a bird's nest that is very difficult to maintain.

...R

hi Robin i have start implementing functions has you advised, can u check my code see if im on the right track..
im new into programing so bare with me hehe
im still figuering out where i would implement the changes on the counts for the microseps i would select
this is the code where i have start implementing the functions

#define MotorDir  6
#define MotorStep 7
#define ButaoA 9
#define ButaoB 10
#define ButaoC 5
#define Enable 8
#define MS1 11
#define MS2 12
#define MS3 13

int msDelay = 1003; 
int ButaoEstadoA = 0; 
int ButaoEstadoB = 0; 

int count = 0;
int MicroPassos;
int Micro;
const float angulo=1.8;
int ButaoEstadoC;
int pressC = 1;
int val = 1;


void setup() 
{
  Serial.begin(9600); 
  pinMode(MotorDir, OUTPUT);
  pinMode(MotorStep, OUTPUT);
  pinMode(ButaoA, INPUT_PULLUP);
  pinMode(ButaoB, INPUT_PULLUP);
  pinMode(ButaoC, INPUT_PULLUP);
  pinMode(Enable, OUTPUT);
  pinMode(MS1, OUTPUT);
  pinMode(MS2, OUTPUT);
  pinMode(MS3, OUTPUT);
  digitalWrite(Enable, HIGH);
}

void loop() 
{
  float degree = (count * angulo) / Micro ; //formula para converter passos(count) em graus
  
  checkButtons();

  changeMicrosteps();

  CheckMicrosteps();
 
  Serial.print("    count=");
  Serial.print(count);
  Serial.print("    graus=");
  Serial.println(degree);
  Serial.print("    buttons press=");
  Serial.print(pressB);


  if (ButaoEstadoA == LOW)// compara se o estado do butao A for HIGH(1) faz o que esta na estrutura
  { 
    MotorClockWsise();

    if (count == MicroPassos) {// define que se a contagem for igual 200
      count = 0; // a contagem vai ter o valor de 0
      degree = 0;// graus vao ser 0
    }
    count = count + 1;
  }
  else   // caso nao esteja o butao em HIGH entao faz o que esta na estrutura else
  {
    MotorStop();
  }
  // codigo do botao que faz motor rodar no sentido oposto do relogio

  if (ButaoEstadoB == LOW)// compara se o estado do butao B for HIGH(1) faz o que esta na estrutura
  { 
    MotorClock();

    if (count == 0) {
      count = MicroPassos;
      degree = 360;
    }
    count = count - 1;
  }
  else if (ButaoEstadoB == LOW) // caso nao esteja o butao em HIGH entao faz o que esta na estrutura else
  {
    MotorStop();
  }

}


void changeMicrosteps() {

 if (pressC == 1) {
    MicroPassos = 200;
    Micro = 1;
    digitalWrite(MS1, LOW);
    digitalWrite(MS2, LOW);
    digitalWrite(MS3, LOW);
    
  }
  if (pressC == 2) {
    MicroPassos = 400;
    Micro = 2;
    digitalWrite(MS1, HIGH);
    digitalWrite(MS2, LOW);
    digitalWrite(MS3, LOW);
  }
 if (pressC == 3) {
    MicroPassos = 3200;
    Micro = 16;
    digitalWrite(MS1, HIGH);
    digitalWrite(MS2, HIGH);
    digitalWrite(MS3, HIGH);
  }
}


void MotorClockWsise()
{
    digitalWrite(Enable, LOW);
    digitalWrite(MotorDir, LOW);// em HIGH a direcao vai no sentido do relogio
    digitalWrite(MotorStep, HIGH);// manada sinal HIGH para ligar o passo do motor
    delayMicroseconds(msDelay);// faz um delay
    digitalWrite(MotorStep, LOW);// manada sinal LOW para desligar o passo do motor
    delayMicroseconds(msDelay);// faz um delay
  }

void MotorClock()
{
    digitalWrite(Enable, LOW);
    digitalWrite(MotorDir, HIGH);//em LOW a direcao vai no sentido contra relogio
    digitalWrite(MotorStep, HIGH);// manada sinal HIGH para ligar o passo do motor
    delayMicroseconds(msDelay);// faz um delay
    digitalWrite(MotorStep, LOW);// manada sinal LOW para desligar o passo do motor
    delayMicroseconds(msDelay);// faz um delay
  }

 void MotorStop(){

    digitalWrite(MotorStep, LOW); // Desliga motor
    digitalWrite(Enable, HIGH);
  }

  void checkButtons()
  {
  ButaoEstadoA = digitalRead(ButaoA);//verifica o estado do butao A
  ButaoEstadoB = digitalRead(ButaoB);//verifica o estado do butao A

  val = digitalRead(ButaoC);
  }

  void CheckMicrosteps()
  {
   if (val != ButaoEstadoC) // compara se o estado do butao A for HIGH(1) faz o que esta na estrutura
  {
    if (val == LOW) {
      pressC++;
      if (pressC > 3) {
        pressC = 1;
      }
    }
  }
 
  ButaoEstadoC = val;
  }

meph328:
im still figuering out where i would implement the changes on the counts for the microseps i would select

Your code structure is going in the right direction.

It may be worth considering how you want to keep track of steps. It may be easier always to count microsteps and to increment them by (say) 4 for a single step (assuming max of 4x microstepping). Then you could change the value to be added for every step in the function changeMicrosteps()

Whatever you do you should avoid using floating point arithmetic if at all possible - it is very slow and can be imprecise.

...R

I recommend trying out the AccelStepper library and making things easy for yourself...

i will look into it, but still would love to come up with a solution to change the counts based on the microseps choise :slight_smile:

meph328:
i will look into it, but still would love to come up with a solution to change the counts based on the microseps choise :slight_smile:

That is not difficult. What have you tried? What happened?

...R

Sorry Robin i was only able to answer today to reply due to work life

here is the code i have at moment

#define MotorDir  6
#define MotorStep 7
#define ButaoA 9
#define ButaoB 10
#define ButaoC 5
#define Enable 8
#define MS1 11
#define MS2 12
#define MS3 13

int msDelay = 1;
int ButaoEstadoA = 0;
int ButaoEstadoB = 0;

int count = 0;
int MicroPassos;
int Micro;
const float angulo = 1.8;
int ButaoEstadoC;
int pressC = 1;
int val = 1;
float degree; 
int State = 0;

void setup()
{
  Serial.begin(9600);
  pinMode(MotorDir, OUTPUT);
  pinMode(MotorStep, OUTPUT);
  pinMode(ButaoA, INPUT_PULLUP);
  pinMode(ButaoB, INPUT_PULLUP);
  pinMode(ButaoC, INPUT_PULLUP);
  pinMode(Enable, OUTPUT);
  pinMode(MS1, OUTPUT);
  pinMode(MS2, OUTPUT);
  pinMode(MS3, OUTPUT);
  digitalWrite(Enable, HIGH);
}

void loop()

{
  degree = (count * angulo) / Micro ;

  MicroButtons();

  changeMicrosteps();

  MotorButtons();

  CheckMicrosteps();

  SerialPrint();

}

void MicroButtons()
{
  ButaoEstadoA = digitalRead(ButaoA);
  ButaoEstadoB = digitalRead(ButaoB);
  val = digitalRead(ButaoC);
}

void changeMicrosteps() {

  if (pressC == 1)
  {
    FullStep();
  }
  if (pressC == 2)
  {
    HalfStep();
  }
  if (pressC == 3)
  {
    SixteenthStep();
  }
}

void MotorButtons() {

  if (ButaoEstadoA == LOW)
  {
    MotorClockWsise();

    if (count == MicroPassos) {
      count = 0; 
      degree = 0;
    }
    count = count + 1;
  
  }
  
 

 if (ButaoEstadoB == LOW)
  {
    MotorClock();

    if (count == 0) {
      count = MicroPassos;
      degree = 360;
    }
    count = count - 1;
  }
   else if (ButaoEstadoA||ButaoEstadoB == LOW) 
   
  {
    MotorStop();
  }
   }

void MotorClockWsise()
{
  digitalWrite(Enable, LOW);
  digitalWrite(MotorDir, LOW);
  digitalWrite(MotorStep, HIGH);
  delayMicroseconds(msDelay);
  digitalWrite(MotorStep, LOW);
  delayMicroseconds(msDelay);
}

void MotorClock()
{
  digitalWrite(Enable, LOW);
  digitalWrite(MotorDir, HIGH);
  digitalWrite(MotorStep, HIGH);
  delayMicroseconds(msDelay);
  digitalWrite(MotorStep, LOW);
  delayMicroseconds(msDelay);
}

void MotorStop() {

  digitalWrite(MotorStep, LOW); 
  digitalWrite(Enable, HIGH);
}


void CheckMicrosteps()
{
  if (val != ButaoEstadoC) 
  {
    if (val == LOW) {
      pressC++;
      if (pressC > 3) {
        pressC = 1;
      }
    }
  }
  ButaoEstadoC = val;
}


void SerialPrint()
{
  Serial.print("    count=");
  Serial.print(count);
  Serial.print("    graus=");
  Serial.println(degree);
  Serial.print("    buttons press=");
  Serial.print(pressC);
}

void FullStep()
{
  MicroPassos = 200;
  Micro = 1;
  digitalWrite(MS1, LOW);
  digitalWrite(MS2, LOW);
  digitalWrite(MS3, LOW);
}
void HalfStep()
{
  MicroPassos = 400;
  Micro = 2;
  digitalWrite(MS1, HIGH);
  digitalWrite(MS2, LOW);
  digitalWrite(MS3, LOW);
}
void SixteenthStep()
{
  MicroPassos = 3200;
  Micro = 16;
  digitalWrite(MS1, HIGH);
  digitalWrite(MS2, HIGH);
  digitalWrite(MS3, HIGH);
}

i have a question that isnt making sense to me on this part of the code: else if (ButaoEstadoA||ButaoEstadoB == LOW)
Shouldnt that be set has HIGH sense im using arduino internal pullups and they reversed state, and the motor would be off if im not pressing the button?
only works if is set on LOW,could you clarify me why is acting that way

void MotorButtons() {

  if (ButaoEstadoA == LOW)
  {
    MotorClockWsise();

    if (count == MicroPassos) {
      count = 0; 
      degree = 0;
    }
    count = count + 1;
  
  }
  
 

 if (ButaoEstadoB == LOW)
  {
    MotorClock();

    if (count == 0) {
      count = MicroPassos;
      degree = 360;
    }
    count = count - 1;
  }
   else if (ButaoEstadoA||ButaoEstadoB == LOW) 
   
  {
    MotorStop();
  }
   }

about the part of what i was trying to achived when i change the microsteps mode to change the count based on the microsteps i chose, i have tryed this, but doesnt work it will keep doubling and doubling, how could i make it to only double one time and then keep counting 1 by 1?

if (pressC == 2)
  {
    HalfStep();
count=count*2;
  }
  if (pressC == 3)
  {
    SixteenthStep();
count=count*16;
  }

but isnt working sense it will keep doubling the count over and over, no idea how can i make