Go Down

Topic: AccelStepper and Encoder Library in single sketch = PROBLEM? (Read 4240 times) previous topic - next topic

aadityadengle

Dear All,
In my project I need to drive a stepper motor with Arduino. It is a heavy motor so I am using driver to do actual phase control where as my Mega sends Pulse and Direction to motor driver.
I also need to have a Linear Quadrature Encoder as feedback to Arduino to eliminate any backlash / lag in my drive mechanism(though having Ball Screws and Timing Belt!!), also It is important to have crosscheck on the axis movement.

Now I started with AccelStepper Library and Encoder Library as following code

Code: [Select]


#include <AccelStepper.h>
#include <Encoder.h>
#include <TimerOne.h>
#include <TimerThree.h>
//...
bool xRun;
bool strmCnt;
float count;
String inpData;
AccelStepper xDrv(1, 32, 33);
Encoder xEnc(18, 19);

//=============================================================================================================================================================
void setup() {
  Serial.begin(9600);
  Serial2.begin(9600);

  xDrv.setMaxSpeed(1500);
  xDrv.setAcceleration(2500);

  Timer1.initialize(1000);
  Timer1.attachInterrupt(Timer1_tick);
  Timer3.initialize(1000);
  Timer3.attachInterrupt(Timer3_tick);
}
//=============================================================================================================================================================
void loop() {
  if (strmCnt == true) {
    Serial2.print (count);
  }
}

//=============================================================================================================================================================


void Timer1_tick() {
  if (xRun == true) {
    xDrv.run();
  }
}
//=============================================================================================================================================================
void Timer3_tick() {
  count = xEnc.read();
}
//=============================================================================================================================================================

void serialEvent() {
  if (Serial.available()) {
    char buff = (Serial.read());
    if (buff == '!') {
      resolveInp();
    } else {
      inpData += buff;
    }
  }

}
//...
void resolveInp() {
  if (inpData.startsWith("MT")) {      // Move To Command; Input in MM.
    String buf = inpData.substring(2);
    char Fbuf[32];
    buf.toCharArray(Fbuf, sizeof(Fbuf));
    float trgPos = atof(Fbuf);
    trgPos = MM2Pulse(trgPos);
    xRun = true;
    xDrv.moveTo(trgPos);

    inpData = "";
    return;//    break;
  }

  if (inpData == "STOPMOVE") { //Stop Move Command
    xDrv.stop();
    xDrv.runToPosition();
    inpData = "";
    xRun = false;
    return;
  }
  if (inpData == "STREAMCOUNT") { //Stop Move Command
    strmCnt = true;
    inpData = "";
    return;
  }

  if (inpData == "STOPCOUNT") { //Stop Move Command
    strmCnt = false;
    inpData = "";
    return;
  }
  if (inpData == "PAUSEMOVE") { //PAUSE Move Command
    xRun = false;
    inpData = "";
    return;
  }

  if (inpData == "RESMOVE") { //Resumes Move Command
    xRun = true;
    inpData = "";
    return;
  }
}
//=============================================================================================================================================================

long MM2Pulse(long mVal) {
  return mVal * 40;  // Given Value X Pulse Per Rotation / Turns per MM [aka Pitch of Screw]
}
//...
long Pulse2MM(long pVal) {
  return pVal * 0.025; // Given Value X Turns per MM [aka Pitch of Screw] / Pulse Per Rotation
}



When I try to run this code I have a bad stepper movement. It is so sluggish ( < 1 pulse / sec) some times that i can hardly notice the movement. Also the Pulse output is not constant for every Arduino reset cycle. Encoder counts are steady in any case.

Where as when I remove either library the things goes very smooth. I think both libraries are not compatible with each other or they are just overloading the Mega.

Please suggest your solution.


Robin2

i suspect seriaEvent is using up clock cycles that could be avoided. I personally avoid that function and just use if Serial.available() whenever it suits me.

Also I don't understand why you are using the Timer library to manage things. That probably uses up more CPU cycles. Can't you just leave it to loop() to activate things. AccelStepper does not need timed inputs - it figures that out itself so you are probably just duplicating work.

Maybe you can use a simple interrupt routine to read the encoder pulses - so you don't need that library at all.

...R
Two or three hours spent thinking and reading documentation solves most programming problems.

aadityadengle

@Robin,
Agree with your suggestion
Quote
Also I don't understand why you are using the Timer library to manage things.
Tried to do the things in loop() but ended resulting the same.

Quote
Maybe you can use a simple interrupt routine to read the encoder pulses - so you don't need that library at all.
I have my own lib to do the things in ISR kindly have a look. but same is not working here!!!

aadityadengle

i suspect seriaEvent is using up clock cycles that could be avoided. I personally avoid that function and just use if Serial.available() whenever it suits me.
There is no problem with serialEvent(). It works perfectly.
My problem is with the AccelStepper and Encoder Lib. I think Interrupts on Encoder Pins making AccelStepper move slow.

Robin2

I have my own lib to do the things in ISR kindly have a look. but same is not working here!!!
Why not?

I'm not a great enthusiast for Arduino libraries but if you wrote that one yourself you should be the expert.

Your extensive ReadMe is typical of the reason I don't like libraries  :)

...R
Two or three hours spent thinking and reading documentation solves most programming problems.

aadityadengle

 :smiley-sad-blue:  tried lots of things but sadly no result matches my expectations.
Any kind of ISR will make AccelStepper to move abnormally!!!!!
switching over dedicated Arduino Nano for AccelStepper as of now. In future I am thinking to move on ARM based boards like DUE (Arduino), Cortex M4 Tiger (Bhasha Technologies)

Robin2

What features of AccelStepper do you need? It is very simple to write code to make a stepper move when you have a proper stepper motor driver board.

Using two Arduinos will add a lot of complexity.

Perhaps your ISR has too much code in it?

...R
Two or three hours spent thinking and reading documentation solves most programming problems.

aadityadengle

The basic functionality..... is what I needed. In fact I am getting it but at very very slow rate.
As per the AccelStepper document I am initializing the stepper to be used with external driver. that means AccelStepper will only generate the Pulse and Direction on the selected Pins.
It is generating the same as it has to be BUT.... not at the same frequency it has to.
Consider If  in my sketch I have set the .maxSpeed at 3500 pulses / sec. and .setAcceleration  at 3000 pulses / sec2, then Without referring to the Encoder Library i.e. ingnoring any signals / interrupts from the encoder gives me the best and timely output of the pulses. Whereas having Encoder Library added to the sketch and having it initialized for the Interrupts (#define ENCODER_USE_INTERRUPTS); the AccelStepper is producing the pulses but almost at the rate of 1 or 2 pulse per second.
I tried to change the parameters in AccelStepper like Acceleration and MaxSpeed but it only turns in to disappointment.

One other thing also has to be considered (and have already done that), If I define Encoder Library not to use interrupts (i.e. #define ENCODER_DO_NOT_USE_INTERRUPTS) every thing flows well except I am missing lots and lots of pulses on the encoder ( almost 100 mm physical travel for encoder is getting reflected only 6 mm?). The encoder is at finest resolution and I am counting it at X4.

I also made changes in the Encoder Config. (which was not possible in Encoder Lib. so I followed your suggestion and done the thing in sketch itself without using library.) I write down smallest possible ISR and defined only one interrupt (Encoder Lib uses 2 interrupt for the best possible results) yet it has improved the results only by 1 or 2 pulses per second. i.e. now I am getting 2 to 4 pulses per second.

I am agree with you that ANY ISR is too long for the AccelStepper to keep with the pulse generation. I am just wondering how the developer has missed a stone?

Or......

It simply has to be concerned with the Mega's speed......

And yes..... I am already using 2 Mega in my project and controlling (more specific managing) them through PC. but with the Nano I have plan to use it as an module of the stepper controlling Mega.
Last night done some coding and primary tests, resulting good output as expected. Only the change in my plan was rather using Nano for the encoder.... I have used it dedicated for the AccelStepper. (reason: just to avoid interrupts on RX/TX while streaming encoder counts).

My intention is to use minimum possible hardware (like one board pc) to minimize overall complexity of the system. More hardware = harder to debug the problem = harder to maintain the system = more possibilities of the error generation. So looking towards the ARM based boards. I have just got one from Basha Technologies. Will have some hands on that and let you know the results....

Aaditya...

aadityadengle

It is very simple to write code to make a stepper move when you have a proper stepper motor driver board.
In fact I am using a Dedicated Industrial grade Driver Unit. which accepts Pulse and Direction signals and has its own power supply for internal logic and stepper output.

Robin2

The basic functionality..... is what I needed.
That does not convey a lot of information. Maybe I was not clear enough with my question. What I'm really wondering is whether you need the acceleration capability.

If all you want is to make a stepper move then these two lines of code will create a single step

Code: [Select]
digitalWrite(stepPin, HIGH);
digitalWrite(stepPin, LOW);


Just repeat them as and when required.

You could do some crude acceleration by doing (say) the first and last quarter revolution at speed A and the rest of the steps at speed B. And I'm sure that will give you ideas for less-crude acceleration.

If you don't need the AccelStepper library maybe you can use the Encoder library without problems.

I think you should work on the assumption that all Arduino libraries have been written without any thought for integration with other stuff.

...R
Two or three hours spent thinking and reading documentation solves most programming problems.

aadityadengle

That does not convey a lot of information. Maybe I was not clear enough with my question.
I have considered the Acceleration as the basic need of any stepper motor operation. So did mentioned basic functionality.

Quote
If all you want is to make a stepper move then these two lines of code will create a single step
I know its all need to generate a square wave to drive stepper but, when one try to do any Industrial project, I  think he must have some logic / some standardization in the movement.

Quote
I think you should work on the assumption that all Arduino libraries have been written without any thought for integration with other stuff.
Yesss.... very true. If I am using them in one place then I have to think about there integration.
I tried to do this with AccelStepper and Encoder Library which was unfortunately not successful enough.
 

Robin2

I know its all need to generate a square wave to drive stepper but, when one try to do any Industrial project, I  think he must have some logic / some standardization in the movement.
I don't understand what is in your mind.

Every step is caused by a square wave. The only variable is the time between steps. AccelStepper will vary that from a long time to a short time during the acceleration period. You could easily write your own code to do the same thing and it would probably get you out of the problem that you are now in.

The real advantage of AcelStepper is for people who are NOT using a proper stepper motor driver because it manages all the complex stuff about the order in which the stepper coils need to be energized.

Have you done tests to determine if you really need to use acceleration?

...R
Two or three hours spent thinking and reading documentation solves most programming problems.

Go Up