Go Down

Topic: Again stepper problems  (Read 327 times) previous topic - next topic

snewpers

Hi, I am still trying to get some stuff working and I thought I had it figured out. I divided parts of my project into smaller projects and combined them that way.

I am still using accelstepper btw.

When I click a button, a stepper moves right, another button, stepper moves left.
This works fine.


Code: [Select]
void runStepperR() {                                            //  ove stepper by joystick clockwise until endstop.

  stepper1.setMaxSpeed(5000);                             //  motor speed stepper 1
  stepper1.moveTo(150000);                                      //  Keep moving until endstop.
  stepper1.setSpeed(5000);
  stepper1.runSpeedToPosition();                                //  Yup, run Forest
}


void runStepperL() {                                            //  Move stepper by joystick counter clockwise until endstop.

  stepper1.setMaxSpeed(5000);                             //  motor speed stepper 1
  stepper1.moveTo(-150000);                                     //  Keep moving until endstop.
  stepper1.setSpeed(5000);
  stepper1.runSpeedToPosition();                                //  Yup, run Forest
}




I save the number of steps made so that I can toggle between 0 (my endpoint) and the value that was generated using above code. For instance, 10000 steps.

When I click a button (not hold) I want to move the stepper as fast as I did before from 0 to 10000 and when I click again go from 10000 to 0.

In void loop() I have the following code:

Code: [Select]
if (StartbuttonState == LOW && flagRUN == 0 && setupActive == 0) { // van start naar einde
    flagRUN = 1;
    }

  if (flagRUN == 1 && flagDIR == 0) { // we zijn op startpunt, nu naar eindpunt!
    runMemoryToEnd();
    }

  if (flagRUN == 1 && flagDIR == 1) { // we zijn op eindpunt, nu naar startpunt!
    runMemoryToStart();
     }



This sets a flag (flagRUN) to be active and the flagDIR is the direction. If the button is clicked and both flags are 0, runMemoryToStart() is run. if the DIR = 1 than runMemoryToEnd() is run etc.

The code for that is:

Code: [Select]
void runMemoryToStart() {                                //  move stepper with acceleration to startpoint, so from 1000 > 0
  stepper1.setMaxSpeed(7000);                           //  motor speed stepper 1
  stepper1.setAcceleration(5000);
  stepper1.moveTo(-stepper1Pos);                          //  Keep moving until endstop.
  stepper1.run();

  if (stepper1.distanceToGo() == 0) {                           //  are we at desired location?
    stepper1.setCurrentPosition(-stepper1Pos);                             //  reset speed
    //  change direction
    flagRUN = 0;                                                //  stop running
    flagDIR = 0;
  }
}


void runMemoryToEnd() {                                         //  move stepper with acceleration to endpoint, so from 0 > 1000
  stepper1.setMaxSpeed(7000);                           //  motor speed stepper 1
  stepper1.setAcceleration(5000);
  stepper1.moveTo(stepper1Pos);                               //  Keep moving until endstop.
  stepper1.run();
  if (stepper1.distanceToGo() == 0) {                           //  are we at desired location?
    stepper1.setCurrentPosition(stepper1Pos); //reset                     //  reset speed
    flagRUN = 0;                                                //  stop running
    flagDIR = 1;                                                //  change direction
  }
}


I had some serial prints running to verify that steps were counted etc and they do. The things that I can't get working is the speed. It seems like the stepper runs at a lower speed. Slower than the original speed.
Could it be the 'if' statement in the last code that slows things down?

Is there another way to use 1 click of a button to get the steppers moving for x steps? I need to have a flag of some kind to signal the end of the steps and the direction, don't I?

DKWatson

Let's assume flagRUN = 1 and flagDIR = 0.
Your test in the loop will call runMemoryToEnd.
You set stepper1 parameters and then stepper.run, testing for stepper1.distanceToGo == 0. If that condition evers comes to exist, flagRUN = 0, flagDIR = 1. Then what?
Live as if you were to die tomorrow. Learn as if you were to live forever. - Mahatma Gandhi

Robin2

You should NOT have the call to stepper.run() inside any function or conditional block. It should be in loop() - probably the last line in loop().

If the program does not do what you want when stepper.run() is in loop() and called all the time (and very frequently) then there is something wrong elsewhere in your code.

Post the complete program that represents your best attempt,

If you have already got advice about this project in another Thread please provide a link to it so we don't waste time repeating ourselves.

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

snewpers

It waits until the next press where flagRun becomes 1 again and the flagIR is also 1, executing runMemoryToStart();

If the distance is 0 again, it sets both flags back to 0 and waits for another press. This way it will bounce only when StartbuttonState == LOW (pressed) and completes a full run without holding a button.

The stepper keeps running until stepper1.distanceToGo == 0. So the stepper1Pos holds the number of steps, positive or negative, but either way distance to go will count (down) until it reaches zero and than the flags are changed.

snewpers

@Robin

I actually did move the stepper.run() to the last line of the loop() and it made no difference in speed. Nothing I tried so far gets the same speed as 'void runStepperR()'.

I was reading the accelstepper docs again and it says:

The desired acceleration in steps per second per second. Must be > 0.0. This is an expensive call since it requires a square root to be calculated. Dont call more ofthen than needed

and

speed   The desired maximum speed in steps per second. Must be > 0. Caution: Speeds that exceed the maximum speed supported by the processor may Result in non-linear accelerations and decelerations.


Could it be that the acceleration combined with the high (?) speed of 5000 steps/second (on 8x microstepping) is asking too much from the arduino?

I will attach it, it's too big otherwise.

snewpers

I believe acceleration is steps per second per second so 12000 is out of the ball park and across the river, start with a more conservative value (500?) and work your way up. Also seems like the max steps per second for a 16 MHz processor is around 4000, sounds like your motor is missing lots of steps and falling behind.   
Could it be that the microstepping indeed is the problem when combined with acceleration? The first code (that just moves to the left or right) is way faster (with same speed settings) but also needs no computing as far as speed/steps goes. It only needs to step.

Robin2

#6
Sep 19, 2018, 10:22 am Last Edit: Sep 19, 2018, 10:24 am by Robin2
Normally the acceleration is set once in setup() so its calculation should not affect the rest of the program.

The AccelStepper library is not able to do high step rates. If you need high step rates just write your own code and don't use the library.

Writing your own simple acceleration system is not difficult. Have a look at the code in this link.


If you want more advice please post the latest version of your complete program.

...R

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

snewpers

#7
Sep 19, 2018, 10:44 am Last Edit: Sep 19, 2018, 10:58 am by snewpers
Hi Robin the zip file is the complete sketch and the latest version. All of it. Did I forget anything?

The link you provided made a lot of sense. I thought I needed the accelstepper.h to get an acceleration working. Actually, that code of yours, to me, is readable and I understand what is going on.

I now have to figure out if I can get that to work in my sketch :)

Thanks.

ETA:
Does this also work with two steppers running at the same time at different speeds?

Robin2

Sorry, but I'm just too lazy to go through all those .ino files and try to make sense of them. There is over 20k of code.

Can't you just create a short single program that illustrates the problem?

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

darrob

@snewpers:
What driver are you using for your stepper motors? (easydriver? .. etc)

Cheers...

snewpers

#10
Sep 19, 2018, 03:00 pm Last Edit: Sep 19, 2018, 03:04 pm by snewpers
@Robin

I'll make one. I like to split things up in tabs to make it a bit more readable for me :) I guess that's not done by everyone then?

@Darrob
Easydriver and/or A4988. (The Easydriver is factory set to 8x microstepping.)

darrob

#11
Sep 19, 2018, 07:14 pm Last Edit: Sep 19, 2018, 11:14 pm by darrob
Okay

As Robin2 stated, Accelstepper does not do well at high step rates.
I have also had fluctuation issues with it, and have given up on trying to use it for my project.

My project uses only one stepper and I'm using a TMC260 driver.

I have taken the library and modified it so that it can be used with something like EasyDriver.
I'm attaching the library, plus a small ino.

The library does not do any acceleration. You can set the stepper speed (in RPM) and tell the stepper to move a number of steps one way or another way (clockwise/anticlockwise)
You can set the microstepping mode (1 to 256) but it defaults to 8
If your driver board is hard set to 8, then the function is not useful. If, however, you can change the stepping mode, issuing a call to setMicrosteps() will keep speed calculations correct.

This was a very quick edit, so there are a number of things I've not properly implemented or tested yet.
For example. The driver keeps track of the current position as the number of steps away from the home position. Home position gets set when the driver is initialised. If you change microstepping mode, you will need to re-calculate / reset the current position with a call to setCurrentPosition()

I don't have an easydriver myself, so I can't physically test that the stepper will work, but quick theoretical debugging seems to work.

Now, the reason for including the test INO:

The ino will show you how to declare, initialise and use the stepper in a non-blocking manner.

There is also a function called calculate_accel()
This shows a simple method of accelerating up to a required speed, moving at that speed then decelerating to a stop.
It uses a simple constant acceleration ramp, and the acceleration value can be changed either by a define or a variable.

This combination is good for speeds of up to 4000 steps per second. If you're using a standard stepper motor that has 200 steps per revolution and 8 microsteps, this works out to about 2.5RPS or 150RPM

This article will show how to install the library.

If you decide to try it, let me know if you have any questions about the accelerating part or anything.
Read through StepDirStepper.h for details on the functions etc

You might want to modify parts of the driver to suit your own needs.

Give it a try and see how it goes

Robin2

#12
Sep 19, 2018, 07:35 pm Last Edit: Sep 19, 2018, 07:42 pm by Robin2
I'll make one. I like to split things up in tabs to make it a bit more readable for me :) I guess that's not done by everyone then?
Splitting up a long program is very sensible.

Looking for advice with a long program (whether in one piece or several) is much less so :)


I always try to design my different parts so they can be tested separately.

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

snewpers

#13
Sep 19, 2018, 09:26 pm Last Edit: Sep 19, 2018, 09:58 pm by snewpers
@darrob, thanks I will look into that for sure, seems promising!

@Robin, noted. In my case it seems that after putting different (working) parts together it introduces a whole lot of new problems :D

I tried your stepper code and that works just fine. Am I correct that 1,000,000 µs equals 1 step per second? The speed would have to be calculated then by the interval between steps, is that correct?

So a speed of 2000 steps per second would have a short interval of 500 µs? (1,000,000 / 2000)



Thanks again!

Robin2

Am I correct that 1,000,000 µs equals 1 step per second? The speed would have to be calculated then by the interval between steps, is that correct?
Yes.

For high step rates it may also be useful to use the digitalWriteFast library. But be aware that it is so much faster that you would need to allow an explicit amount of time (about 10µsecs) for the step pulse.

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

Go Up