Stepper with encoder.

I have been working on this for a few hours and I am quite lost. I have a stepper and encoder. I have used the encoder counts and pulse to create an error when the motor has missed steps. I would like the arduino to reset the stepper back to its original 0 when it has an error larger than a full step. the snippet below is my attempt. the entire code is below.

[/code]if (error<-25 || error> 25){
target.move(Zero);
target.setSpeed(4000); [/left]

#include <AccelStepper.h>
#include <Encoder.h>
Encoder myEnc(2, 3);

AccelStepper target(1, 6, 8); // pin 6 = pulse, pin 8 = direction
const int buttonRT = 11;
const int buttonBK = 10;
const int buttonLT = 9;
const int disableMotor = 7;
int Desired_position = 0;

void setup() {                                                                                                                                                                                                                                                                  
  target.setMaxSpeed(4000);
  target.setSpeed(500);
  target.setMinPulseWidth(50);
  //target.setAcceleration(10);
  pinMode(buttonRT, INPUT_PULLUP);
  pinMode(buttonBK, INPUT_PULLUP); 
  pinMode(buttonLT, INPUT_PULLUP);
  pinMode(disableMotor, OUTPUT);
  
  
  
  Serial.begin(9600); 
}

void loop(){ 
  
  // encoder and error collection section.
  int actualPosition = myEnc.read();
  int correctedActualPosition=(actualPosition)*.801;
  int error = (correctedActualPosition - target.currentPosition() );
  int Zero= error/8;

  

  // count and return to zero
  
   // position control
{
    while (digitalRead(buttonRT) == LOW) {//wired N.O.
      Desired_position = -500;
    }
    while (digitalRead(buttonBK) == HIGH) {//wired N.C.
      Desired_position = 0;
    }
    //wired N.C.
    while (digitalRead(buttonLT) == LOW) {//wired N.O.
      Desired_position = 500;
    }
    if (error<-25 || error> 25){     
      target.move(Zero);
      //target.setSpeed(4000);
    }
  }
  //print only while there are no pulses to the motor.
  if (target.distanceToGo()==0){
    //digitalWrite(disableMotor, HIGH);
    Serial.print(actualPosition);  
    Serial.print ("   ");
    Serial.print (Desired_position);
    Serial.print ("   ");
    Serial.print (target.currentPosition());
    Serial.print ("   ");
    Serial.println (error,DEC);
    Serial.print ("   ");
    //Serial.print (correctedActualPosition);
  }
  {
  // controls motor moves
  target.moveTo(Desired_position);
  target.setSpeed(4000);
  target.runSpeedToPosition();

  // read the input pins:
  int buttonState1 = digitalRead(buttonRT);
  int buttonState2 = digitalRead(buttonBK);
  int buttonState3 = digitalRead(buttonLT);


}
}

Check this part of code. Without any test condition how it can move inside the loop. you share me snap shot of serial monitor , Since i dont have encoder here to test it,

{
    while (digitalRead(buttonRT) == LOW) {//wired N.O.
      Desired_position = -500;
    }
    while (digitalRead(buttonBK) == HIGH) {//wired N.C.
      Desired_position = 0;
    }
    //wired N.C.
    while (digitalRead(buttonLT) == LOW) {//wired N.O.
      Desired_position = 500;
    }
    if (error<-25 || error> 25){     
      target.move(Zero);
      //target.setSpeed(4000);
    }
  }

You can't mix integers and floats in maths like this

int correctedActualPosition=(actualPosition)*.801;

All the variables must be floats - if you really need that precision. You could also approximate the fraction with integers - actualPosition * 10 / 8 (edited to correct stupid typo - I had a 2 where the 8 is now)

All these WHILEs

while (digitalRead(buttonRT) == LOW)

should probably be IFs

If you have lost the stepper position you will need a move sequence that can restore it. Normally this is done by moving until a limit switch is triggered.

In this case if you know the actual position from the encoder why not just use that to update the current position and carry on.

...R

Hi,
How many steps does stepper do for 360degrees?
How many pulses does the encoder output for 360degrees?

Tom...... :slight_smile:

AMPS-N, I may not have given what you needed, I am not sure what you want me to do

Here is a snap shot of the Serial monitor

buttonRT pushed once
-626 -500 -500 -1
-626 -500 -500 -1

buttonLT pushed once
626 500 500 1
626 500 500 1

buttonBK pushed once
0 0 0 0
0 0 0 0

buttonBK pushed once then rotated out of phase to show the error on the right.the error is the result of *.801 by encoder counts on the left.
-10 0 0 -8
-10 0 0 -8

Robin2,

All valid points I have not thought of fractions, but it does seem to work. The las serial reading shows the error correctly.

I changed the Whiles for IFs. Is this because the whiles are more expensive?

using limit switch, I am trying to keep as few of components as I can My plan is to use a Z channel of an encoder to rezero, but they are weeks out.

I actually was making an attempt to reset zero with this bit of code.

if (error<-25 || error> 25){     
      target.move(Zero);
      target.setSpeed(4000);

Zero is a corrected value of error to move to the original 0. That even sound complicated to me now that I have read it back. so much for k.i.s.s.

Tom, I have a standard 200 step motor micro-stepping at 1/8. My encoder is a 500 steps per rev.

Thanks everyone for the input, I am looking forward to hearing how to simplify my code and make it actually work. I have tried many things and have been close but no cigar.

You havent read my old comment carefully,As mentioned there is no entry condition???

You havent shared library used in your code.??

Replce your while loop with if conditions

Put snap shot of error output before ur test condition

 Serial.print("error:");Serial.println(error);
    if (error<-25 || error> 25){     
      target.move(Zero);
      //target.setSpeed(4000);
    }

I did include the entire sketch showing the libraries and I did fix the while statements like Robbin2 suggested. I included snap shots of the serial monitor of different scenarios to show you how the program was reacting. I am still not sure what the

As mentioned there is no entry condition???

is all about. I still am new to the arduino I guess I need to have my hand held from time to time. I am not sure what the print statement that you have added does for me either.

Can you paste your revised code.

entry condition means, you used improper bracket without condition statement. Seems even you new to C. For previous program it not even printing data because you used while loop.

Check condition
{
//Do this process

}

i have highlighted it my post where you made mistake.

you have used where loop gets early as before your test condition. use autoformat option from tool or press ctrl+T

Ok, I have my motor behaving as it should. If there is a deviation from where it suppose to be and where it is, it moves back to the encoder zero. Now I am trying to increment a score every time I have an error larger than twelve micro steps. unfortunately it is giving me more than one increment. I need some type of debounce for the increment. can anyone point me in the right direction.

#include <AccelStepper.h>
#include <Encoder.h>
Encoder myEnc(2, 3);

AccelStepper target(1, 6, 8); // pin 6 = pulse, pin 8 = direction
const int buttonRT = 11;
const int buttonBK = 10;
const int buttonLT = 9;
const int disableMotor = 7;
int Desired_position = 0;
int RightScore =0;
int LeftScore =0;

void setup() {                                                                                                                                                                                                                                                                  
  target.setMaxSpeed(4000);
  target.setSpeed(3000);
  target.setMinPulseWidth(50);
  //target.setAcceleration(10);
  pinMode(buttonRT, INPUT_PULLUP);
  pinMode(buttonBK, INPUT_PULLUP); 
  pinMode(buttonLT, INPUT_PULLUP);
  pinMode(disableMotor, OUTPUT);
  


  Serial.begin(9600); 
}

void loop(){ 

  // encoder and error collection section.
  int actualPosition = myEnc.read();
  int StepsToZero=(actualPosition)*8/10;
  int error = (StepsToZero - target.currentPosition());
  int Zero= error/8;
 
  // count and return to zero

  // position control

  if (digitalRead(buttonRT) == LOW) {//wired N.O.
    Desired_position = -400;
  }
  if (digitalRead(buttonBK) == HIGH) {//wired N.C.
    Desired_position = 0;
  }
  //wired N.C.
  if (digitalRead(buttonLT) == LOW) {//wired N.O.
    Desired_position = 400;
    
  }
  /*
   if ((error<-15) && (Desired_position = -400)){
      
  }
  */
  if (error<-15){    
    delay (1000);      
    target.setCurrentPosition(StepsToZero);
    Desired_position = 0;
    RightScore++;
    
  }
  /*
   if ((error>12) && (Desired_position = -400)){
     LeftScore++;
  }  
  */
  if (error>12){    
    delay (1000);      
    target.setCurrentPosition(StepsToZero);
    Desired_position = 0;
    LeftScore++;
  } 
  {
      // controls motor moves
      target.moveTo(Desired_position);
      target.setSpeed(3000);
      target.runSpeedToPosition();
    
  
  
  
  
    //print only while there are no pulses to the motor.
    if (target.distanceToGo()==0){
      
      Serial.print("LeftScore");
      Serial.print ("   ");
      Serial.print (LeftScore);
      Serial.print ("   ");
      Serial.print ("RightScore");
      Serial.print ("   ");
      Serial.println (RightScore);     
 
      /*
      //digitalWrite(disableMotor, HIGH);
      Serial.print(actualPosition);  
      Serial.print ("   ");
      Serial.print (Desired_position);
      Serial.print ("   ");
      Serial.print (target.currentPosition());
      Serial.print ("   ");
      Serial.print (error,DEC);
      Serial.print ("   ");
      Serial.print (StepsToZero);
      Serial.println ("   ");
      */
    }
    

  }}

Can you put datasheet of the Encoder.
Have you checked output W.r.t voltage you getting proper angle. If not calibrate using first order or second order software filtering program.

The encoder is working fine. I can stop the motor in a move or simply turn the motor to a position and it will always find zero. My issue is counting each time it is out of sequence. It is a 500ppr Quadrature encoder (actual 2000ppr) from us digital. but the hardware is working fine. It is my brain that is not. I am looking into adapting the debounce sketch to keep from incrementing more than one per event. Is there some simple way to implement this?

Please share serial output of below code!!! replace loop statement

void loop(){ 

  // encoder and error collection section.
  int actualPosition = myEnc.read();
 Serial.print("actualPosition:"); Serial.println(actualPosition);
  int StepsToZero=(actualPosition)*8/10;
   Serial.print("StepsToZero:"); Serial.println(StepsToZero);
  int error = (StepsToZero - target.currentPosition());
   Serial.print("error:"); Serial.println(error);
    int Zero= error/8;
 Serial.print("Zero:"); Serial.println(Zero);
  // count and return to zero

  // position control

  if (digitalRead(buttonRT) == LOW) {//wired N.O.
    Desired_position = -400;
  }
  if (digitalRead(buttonBK) == HIGH) {//wired N.C.
    Desired_position = 0;
  }
  //wired N.C.
  if (digitalRead(buttonLT) == LOW) {//wired N.O.
    Desired_position = 400;

  }
  /*
   if ((error<-15) && (Desired_position = -400)){
   
   }
   */
     Serial.print("error value before check condition:"); Serial.println(error);
  if (error<-15){    
    delay (1000);      
    target.setCurrentPosition(StepsToZero);
    Desired_position = 0;
    RightScore++;

  }
  /*
   if ((error>12) && (Desired_position = -400)){
   LeftScore++;
   }  
   */
  if (error>12){    
    delay (1000);      
    target.setCurrentPosition(StepsToZero);
    Desired_position = 0;
    LeftScore++;
  } 
  
  //No entry condition Here???
  {
    // controls motor moves
    target.moveTo(Desired_position);
    target.setSpeed(3000);
    target.runSpeedToPosition();
    //print only while there are no pulses to the motor.
    if (target.distanceToGo()==0){

      Serial.print("LeftScore");
      Serial.print ("   ");
      Serial.print (LeftScore);
      Serial.print ("   ");
      Serial.print ("RightScore");
      Serial.print ("   ");
      Serial.println (RightScore);     

    }


  }
}

In your code posted above what does this part will do??. dont post code blindly. just check what you sharing. use autoformat option. check braces, brackets,entry conditions are valid or not???

  //No entry condition Here???
  {
    // controls motor moves
    target.moveTo(Desired_position);
    target.setSpeed(3000);
    target.runSpeedToPosition();
    //print only while there are no pulses to the motor.
    if (target.distanceToGo()==0){

      Serial.print("LeftScore");
      Serial.print ("   ");
      Serial.print (LeftScore);
      Serial.print ("   ");
      Serial.print ("RightScore");
      Serial.print ("   ");
      Serial.println (RightScore);     

    }


  }

Replace loop statement with what?

LeftScore 4 RightScore 2
LeftScore 4 RightScore 2
LeftScore 4 RightScore 2

in the accelstepper library you need to call the stepper to run. It does not need an entry statement here. when I push the right botton and change desired position it needs a moveTo command.

I told to share screen shot like this Not like below.

Dont give oversmart asnwers. If you dont know things try to learn it. All people helping to solve your issue , if giving over smart answer like you know everything none will help here…

For your reference i attached screen shot of serial monitor.We dont have actual setup here. Depend on your valid answer only we can give suggestions. Since you have device connected it wont be Zero in your case.

Try this code in your device. Send me screen shot of serial monitor.

#include <AccelStepper.h>
#include <Encoder.h>
Encoder myEnc(2, 3);

AccelStepper target(1, 6, 8); // pin 6 = pulse, pin 8 = direction
const int buttonRT = 11;
const int buttonBK = 10;
const int buttonLT = 9;
const int disableMotor = 7;
int Desired_position = 0;
int RightScore =0;
int LeftScore =0;

void setup() {                                                                                                                                                                                                                                                                  
  target.setMaxSpeed(4000);
  target.setSpeed(3000);
  //  target.setMinPulseWidth(50);
  //target.setAcceleration(10);
  pinMode(buttonRT, INPUT_PULLUP);
  pinMode(buttonBK, INPUT_PULLUP); 
  pinMode(buttonLT, INPUT_PULLUP);
  pinMode(disableMotor, OUTPUT);
  Serial.begin(9600); 
}

void loop(){ 

  // encoder and error collection section.
  int actualPosition = myEnc.read();
 Serial.print("actualPosition:"); Serial.println(actualPosition);
  int StepsToZero=(actualPosition)*8/10;
   Serial.print("StepsToZero:"); Serial.println(StepsToZero);
  int error = (StepsToZero - target.currentPosition());
   Serial.print("error:"); Serial.println(error);
    int Zero= error/8;
 Serial.print("Zero:"); Serial.println(Zero);
  // count and return to zero

  // position control

  if (digitalRead(buttonRT) == LOW) {//wired N.O.
    Desired_position = -400;
  }
  if (digitalRead(buttonBK) == HIGH) {//wired N.C.
    Desired_position = 0;
  }
  //wired N.C.
  if (digitalRead(buttonLT) == LOW) {//wired N.O.
    Desired_position = 400;

  }
  /*
   if ((error<-15) && (Desired_position = -400)){
   
   }
   */
     Serial.print("error value before check condition:"); Serial.println(error);
  if (error<-15){    
    delay (1000);      
    target.setCurrentPosition(StepsToZero);
    Desired_position = 0;
    RightScore++;

  }
  /*
   if ((error>12) && (Desired_position = -400)){
   LeftScore++;
   }  
   */
  if (error>12){    
    delay (1000);      
    target.setCurrentPosition(StepsToZero);
    Desired_position = 0;
    LeftScore++;
  } 
  
 
    // controls motor moves
    target.moveTo(Desired_position);
    target.setSpeed(3000);
    target.runSpeedToPosition();
    //print only while there are no pulses to the motor.
    if (target.distanceToGo()==0){

      Serial.print("LeftScore");
      Serial.print ("   ");
      Serial.print (LeftScore);
      Serial.print ("   ");
      Serial.print ("RightScore");
      Serial.print ("   ");
      Serial.println (RightScore);     

   


  }
  Serial.println(".......................................");
  delay(1000);
}

AMPS, I do apologize if it Sounded to Smart. I was simply trying to clarify. I was not trying to rub anyone the wrong way. I am in no way trying to boast my knowledge,I am aware that I know very little of the C programming world. I appreciate all of the time you guys put in.

I was unsuccessful in attaching the screen shot on to this post, I am not sure how to get it from paint to here? if you would let me in on the secret, I will do so. In the mean time I will post your debug as I know how.

I have captured where it gives first gives the error where I grabbed the shaft and it lost one full step.

I no longer use Zero in the code I just forgot to take it out. The StepsToZero never referred to Zero anyway it was referring to the original programmed zero. (The reset position when you reset the arduino.)

Thanks again for taking a look.

actualPosition:0
StepsToZero:0
error:0
Zero:0
error value before check condition:0
LeftScore 0 RightScore 0
.......................................
actualPosition:41
StepsToZero:32
error:32
Zero:4
error value before check condition:32
.......................................
actualPosition:38
StepsToZero:30
error:-1
Zero:0
error value before check condition:-1
.......................................
actualPosition:37
StepsToZero:29
error:-1
Zero:0
error value before check condition:-1
.......................................

OK I also added the debug portion where the motor is approaching zero again and then it shows the score. I did this several times and it scored only one like I would like it to do. but with all of this printing it has slowed the program and motor to a slow crawl.

.......................................
actualPosition:-9
StepsToZero:-7
error:-2
Zero:0
error value before check condition:-2
.......................................
actualPosition:-7
StepsToZero:-5
error:-1
Zero:0
error value before check condition:-1
.......................................
actualPosition:-6
StepsToZero:-4
error:-1
Zero:0
error value before check condition:-1
.......................................
actualPosition:-4
StepsToZero:-3
error:-1
Zero:0
error value before check condition:-1
.......................................
actualPosition:-3
StepsToZero:-2
error:-1
Zero:0
error value before check condition:-1
LeftScore 0 RightScore 1

OK I finally broke down and learned how to use millis this was the fix for the extra counts. I used millis to de-bounce the error if you will.

AMP-N thanks for the help I just saw the attachments and other options below? Now I feel silly.

#include <AccelStepper.h>
#include <Encoder.h>
Encoder myEnc(2, 3);

AccelStepper target(1, 6, 8); // pin 6 = pulse, pin 8 = direction
const int buttonRT = 11;
const int buttonBK = 10;
const int buttonLT = 9;
const int disableMotor = 7;
int Desired_position = 0;
int RightScore =0;
int LeftScore =0;
unsigned long interval=1000;  
unsigned long previousMillis=0; 

void setup() {                                                                                                                                                                                                                                                                  
  target.setMaxSpeed(4000);
  target.setSpeed(3000);
  target.setMinPulseWidth(50);
  //target.setAcceleration(10);
  pinMode(buttonRT, INPUT_PULLUP);
  pinMode(buttonBK, INPUT_PULLUP); 
  pinMode(buttonLT, INPUT_PULLUP);
  pinMode(disableMotor, OUTPUT);



  Serial.begin(9600); 
}

void loop(){ 

  // encoder and error collection section.
  int actualPosition = myEnc.read();
  int StepsToZero=(actualPosition)*8/10;
  int error = (StepsToZero - target.currentPosition());
  int Zero= error/8;

  // count and return to zero

  // position control

  if (digitalRead(buttonRT) == LOW) {//wired N.O.
    Desired_position = -400;
  }
  if (digitalRead(buttonBK) == HIGH) {//wired N.C.
    Desired_position = 0;
  }
  //wired N.C.
  if (digitalRead(buttonLT) == LOW) {//wired N.O.
    Desired_position = 400;

  }
  // controls motor moves
    target.moveTo(Desired_position);
    target.setSpeed(3000);
    target.runSpeedToPosition();

  [glow=red,2,300]if (error<-15){         
    target.setCurrentPosition(StepsToZero);
    Desired_position = 0;
    target.moveTo(Desired_position);
    target.setSpeed(3000);
    target.runSpeedToPosition();
   if ((unsigned long)(millis() - previousMillis) >= interval) {
    previousMillis = millis(); 
    RightScore++;[/glow]
   }
  }
  
  
  if (error>15){
  target.setCurrentPosition(StepsToZero);
    Desired_position = 0;
    target.moveTo(Desired_position);
    target.setSpeed(3000);
    target.runSpeedToPosition();
    if ((unsigned long)(millis() - previousMillis) >= interval) {
    previousMillis = millis();
    LeftScore ++;
   }
    
  } 
  
    

    //if (target.distanceToGo()!=0){
     // digitalWrite(disableMotor, HIGH);
    //}


    //print only while there are no pulses to the motor.
    if (target.distanceToGo()==0){
      
      Serial.print("LeftScore");
      Serial.print ("   ");
      Serial.print (LeftScore);
      Serial.print ("   ");
      Serial.print ("RightScore");
      Serial.print ("   ");
      Serial.println (RightScore);     
    }
      /*
      //digitalWrite(disableMotor, HIGH);
       Serial.print(actualPosition);  
       Serial.print ("   ");
       Serial.print (Desired_position);
       Serial.print ("   ");
       Serial.print (target.currentPosition());
       Serial.print ("   ");
       Serial.print (error,DEC);
       Serial.print ("   ");
       Serial.print (StepsToZero);
       Serial.println ("   ");
       */
    


  
}

You choose print screen option from keypad. Then open paint paste (ctrl+v) . Save it as JPG format. Attach here.

Some question here

  1. what is use of variable Zero here???

What you checking here.

 if (target.distanceToGo()==0){

      Serial.print("LeftScore");
      Serial.print ("   ");
      Serial.print (LeftScore);
      Serial.print ("   ");
      Serial.print ("RightScore");
      Serial.print ("   ");
      Serial.println (RightScore);     


  }
  1. Need final Serial monitor output.
#include <AccelStepper.h>
#include <Encoder.h>
Encoder myEnc(2, 3);

AccelStepper target(1, 6, 8); // pin 6 = pulse, pin 8 = direction
const int buttonRT = 11;
const int buttonBK = 10;
const int buttonLT = 9;
const int disableMotor = 7;
int Desired_position = 0;
int RightScore =0;
int LeftScore =0;

void setup() {                                                                                                                                                                                                                                                                  
  target.setMaxSpeed(4000);
  target.setSpeed(3000);
  //  target.setMinPulseWidth(50);
  //target.setAcceleration(10);
  pinMode(buttonRT, INPUT);
  pinMode(buttonBK, INPUT); 
  pinMode(buttonLT, INPUT);
  pinMode(disableMotor, OUTPUT);
  Serial.begin(9600); 
}

void loop(){ 

  // encoder and error collection section.
  int actualPosition = myEnc.read();
 Serial.print("actualPosition:"); Serial.println(actualPosition);
  int StepsToZero=(actualPosition)*8/10;
   Serial.print("StepsToZero:"); Serial.println(StepsToZero);
  int error = (StepsToZero - target.currentPosition());
   Serial.print("error:"); Serial.println(error);
    int Zero= error/8;
 Serial.print("Zero:"); Serial.println(Zero);
  // count and return to zero

  // position control

  if (digitalRead(buttonRT) == LOW) {//wired N.O.
    Desired_position = -400;
  }
  if (digitalRead(buttonBK) == HIGH) {//wired N.C.
    Desired_position = 0;
  }
  //wired N.C.
  if (digitalRead(buttonLT) == LOW) {//wired N.O.
    Desired_position = 400;

  }
      Serial.print("error value before check condition:"); Serial.println(error);
  if (error<-15){    
    delay (1000);      
    target.setCurrentPosition(StepsToZero);
    Desired_position = 0;
    RightScore++;
Serial.println("Right score moved");
  }else  
  if (error>12){    
    delay (1000);      
    target.setCurrentPosition(StepsToZero);
    Desired_position = 0;
    LeftScore++;
    Serial.println("Left score moved");
  } 
  
 Serial.print("Desired Postion:");  Serial.println(Desired_position);
    // controls motor moves
    target.moveTo(Desired_position);
    target.setSpeed(3000);
    target.runSpeedToPosition();
    //print only while there are no pulses to the motor.
    if (target.distanceToGo()==0){

      Serial.print("LeftScore");
      Serial.print ("   ");
      Serial.print (LeftScore);
      Serial.print ("   ");
      Serial.print ("RightScore");
      Serial.print ("   ");
      Serial.println (RightScore);     


  }
  Serial.println(".......................................");
  delay(1000);
}