Encoder library with Accelstepper malfunction

JihoonLee

Member
Hi All,
I made the in-out action as a stepper motor using the Encoder library and Accelstepper.
I'm a newbie in coding, so the code is just using Exsample, and it's very simple.

The encoder works fine, but the motor gets malfunctioning when saving and recall in-out positions.

It seems to lose its position after returning to the loop statement.
Another concern is that the Easybutton library uses the function name "read", which is same with the Encoder library.

Could you help me or some advice for good coding?

  • Coding Environment: Arduino IDE
  • Encoder used: 200cpl rotary encoder.
  • Board: SAMD21mini (to be moved to Teensy 3.2 or LC)
  • Motor: Nema17 Bipolar 1.7 degree


Code:
#include <Encoder.h>
#include <EasyButton.h>
#include <AccelStepper.h>

#define BTN1 5
#define BTN2 6

Encoder Enc(12, 13);
AccelStepper stepper1(1, 10, 11);
EasyButton button1(BTN1);
EasyButton button2(BTN2);

long XInPoint = 0;
long XOutPoint = 0;

short scale = 4;

void setup() {

  button1.begin();
  button2.begin();

  button1.onPressed(onButton1Pressed);
  button2.onPressed(onButton2Pressed);

  button1.onPressedFor(1000, onPressed1ForDuration);
  button2.onPressedFor(1000, onPressed2ForDuration);

  stepper1.setMaxSpeed(3000);
  stepper1.setAcceleration(6000);
}

long oP  = -999;

void loop() {

  button1.read();
  button2.read();

  ///////////////////////////////////////////////////////////////////// Encoder

  long nP = Enc.read();
  if (nP != oP) {
    oP = nP;
    stepper1.moveTo(nP * scale);
  }
  stepper1.run();
}

////////////////////////////////////////////////////////////// Button1.(Pressed)

void onButton1Pressed()
{
  stepper1.moveTo(XInPoint);
  stepper1.runToPosition();
}

////////////////////////////////////////////////////////////// Button2.(Pressed)

void onButton2Pressed()
{
  stepper1.moveTo(XOutPoint);
  stepper1.runToPosition();
}

///////////////////////////////////////////////////////////// Button1.(Duration)

void onPressed1ForDuration()
{

long xi = Enc.read();
  XInPoint = xi;
}

//////////////////////////////////////////////////////////// Button2.(Duration)

void onPressed2ForDuration()
{

 long xo = Enc.read();
  XOutPoint = xo;
}
 
The encoder and the stepper are unlikely to have the same number of steps per revolution, yet you are using encoder values in the stepper positions...
 
Thanks for the comment.
For the 'In and Out Button' action of the motor, I also tried the currentPosition value of the Accelstepper, but the result was not good.

How can I return the accumulate moved steps of Accelstepper to Encoder library side?

*In this case, the buttons work, but if I use the encoder input again after completing the In and Out(Button) actions, it immediately moves to another point.

Code:
#include <Encoder.h>
#include <EasyButton.h>
#include <AccelStepper.h>

#define BTN1 5
#define BTN2 6

Encoder Enc(12, 13);
AccelStepper stepper1(1, 10, 11);
EasyButton button1(BTN1);
EasyButton button2(BTN2);

long XInPoint = 0;
long XOutPoint = 0;

short scale = 4;

void setup() {

  button1.begin();
  button2.begin();

  button1.onPressed(onButton1Pressed);
  button2.onPressed(onButton2Pressed);

  button1.onPressedFor(1000, onPressed1ForDuration);
  button2.onPressedFor(1000, onPressed2ForDuration);

  stepper1.setMaxSpeed(3000);
  stepper1.setAcceleration(6000);
}

long oP  = -999;

void loop() {

  button1.read();
  button2.read();

  ///////////////////////////////////////////////////////////////////// Encoder

  long nP = Enc.read();
  if (nP != oP) {
    oP = nP;
    stepper1.moveTo(nP * scale);
  }
  stepper1.run();
}

////////////////////////////////////////////////////////////// Button1.(Pressed)

void onButton1Pressed()
{
  stepper1.moveTo(XInPoint);
  stepper1.runToPosition();
}

////////////////////////////////////////////////////////////// Button2.(Pressed)

void onButton2Pressed()
{
  stepper1.moveTo(XOutPoint);
  stepper1.runToPosition();
}

///////////////////////////////////////////////////////////// Button1.(Duration)

void onPressed1ForDuration()
{
XInPoint = stepper1.currentPosition(); 
}

//////////////////////////////////////////////////////////// Button2.(Duration)

void onPressed2ForDuration()
{
XOutPoint = stepper1.currentPosition();
}
 
Last edited:
Again, decide which coordinates you are using and stick to them - if you are using the stepper steps, you'll have to convert encoder values to stepper steps before using them, or vice versa.

Why are you calling runToPostion() BTW - you already call run() in loop so the steppers will do the right thing in the background quite happily.
(Or is button.read() blocking???)
 
>>>How can I return the accumulate moved steps of Accelstepper to Encoder library side?

You could make use of one or both of these functions that are in the encoder library. As you can see, they reset the absolute position of the encoder.



Code:
	inline int32_t readAndReset() {
		if (interrupts_in_use < 2) {
			noInterrupts();
			update(&encoder);
		} else {
			noInterrupts();
		}
		int32_t ret = encoder.position;
		encoder.position = 0;
		interrupts();
		return ret;
	}
	inline void write(int32_t p) {
		noInterrupts();
		encoder.position = p;
		interrupts();
	}
 
You're right. The motor was looping in the background of the code.
And, when the steps returns to the loop, the encoder cannot update the steps scale.

Actually I needed acceleration of the motor, so I added Run(); in both the encoder and the Accelstepper side.
I finally corrected the malfunction by removing the 'steps scale' and adding simple 'delay();' instead of Accelstepper stop ();

The code is a bit unstable now, but it works nonetheless.

Thank you for your advice!
 
I added the 'write();' class to the code in encoder side from the encoder library, and after that the motor steps(from Accelstepper) is found its place. My code is still unstable, but it's working now anyway. One thing I regret I can't find the way for use Steps Scale.
I'm going to study your code to make it possible.

Thank you for your advice and code suggestions.
 
Back
Top