What is the Most Efficient Code?

706 views
Skip to first unread message

John Wall

unread,
Aug 22, 2015, 11:06:01 AM8/22/15
to accelstepper
As with most here, I am a novice at programming.  I have been working with Arduino for several months now and more recently, the Accel library with various degrees of success. 

I am building a flight simulator cockpit for an A10C.  I have numerous analogue gauges that are either real A10C gauges retro fitted with stepper motors or fabrications that I manufactured myself.  I have been experimenting with the Easy Driver board, a handful of  Arduino Pro Minis as well as various stepper motors ranging from a NEMA 8 to the small Switec25 motors.  The Accel library has been my preferred choice due to its excellent ability to run multiple stepper motors simultaneously.

This is the situation.  What I have is a flight simulator running on Win7 64 that exports data from each of its simulated gauges. This data stream is directed to an Arduino board via SPI.  The data is  parsed and the exact position of the pointer for a specific gauge is provided.  This position is defined in a range of 0 to 65,535.  It is updated 25 times per second.   This range of data is remapped to the number of steps for whatever stepper motor is being used to move the gauge pointer and whether micro stepping is needed to smooth the movement out.  I use an Easy Driver board for its microstepping.

I would very much appreciate some assistance in writing, what would hopefully be, an extremely efficient sketch using the Accel Library.  Mostly because of the large amount of data involved and the numerous stepper motors I have to deal with.  (see pics below for example).  To that end I have made some basic assumptions that I hope can be confirmed on this forum.

Firstly, because this is a situation where all we are doing is mimicking precisely what the simulators gauges are doing, I do not need to be concerned with acceleration or deceleration.  There is no momentum to overcome as the pointer that's being moved weighs virtually nothing.  Furthermore, any perceived accell/decel seen in the simulator would be reflected in the changing data.  

Second is speed.  I assume that I should set the speed as fast as possible just short of where steps are lost .  Because speed varies so much in the sim I would again assume speed changes are reflected in the changes within data stream.  As long as the motor can move as fast as the fastest motion seen in the sim then all would be good. 

Essentially, all I would do is set speed to max "(stepper.setMaxSpeed(???)", do not include any acceleration whatsoever and start the sketch by zeroing the motor in the "void setup()". 

If all of the above is correct then what remains is how to handle a single variable that holds the position of the gauge pointer which is update 25 times per second but only if there is a change it its position.  

Based on the background info I have provided, I would very much appreciate your assistance with writing a sketch using the most efficient Accel commands that would allow several stepper motors to run  several gauges from the same Arduino board all at the same time. 

Here is an example of what I am trying to accomplish.  Unfortunately my expertise is CNC and mechanical with only a small (but growing) knowledge in programming.

  

If anyone is interested in cockpit building, this is my photo site with everything that I have built to date.  http://s221.photobucket.com/user/MRAR15/library/A10%20Cockpit%20Panels?sort=3&page=1

Thank you for reading this and hopefully helping me resolve this bit of programming.

John 


gregor

unread,
Aug 22, 2015, 7:20:16 PM8/22/15
to accelstepper
Hi, 

assumptions 1 and 2 seem to be correct to me. 

However, you need to define acceleration with setAcceleration() because the default value is 1 step / second^2, this will be way too low for your application. You should set the acceleration to a very high value, for example 1000000 steps / second^2 to achieve constant speed through almost instant acceleration to maximum speed.

Holding the Gauge position is easy. You could, for instance, create a class Gauge that contains all the functions and variables needed, among those the previously set gauge position. Processing the updated Gauge position would then be possible like this:
void Gauge::updateGaugePosition(unsigned int new_value)
{
   
//do nothing when gauge position has not changed.
   
if (new_value == old_value)
     
return;

   
//gaugePosToSteps() converts the gauge position to stepper motor steps.
   stepper
.moveTo(gaugePosToSteps(new_value));
   old_value
= new_value;
}
where old_value is a private variable of the class Gauge.
Alternatively, you could just store the gauge positions to global variables. 


I like your project. Please keep us updated!

Mike McCauley

unread,
Aug 22, 2015, 10:37:32 PM8/22/15
to accels...@googlegroups.com
On Saturday, August 22, 2015 04:20:16 PM gregor wrote:
> Hi,
>
> assumptions 1 and 2 seem to be correct to me.

Agree.

>
> However, you need to define acceleration with setAcceleration() because the
> default value is 1 step / second^2, this will be way too low for your
> application. You should set the acceleration to a very high value, for
> example 1000000 steps / second^2 to achieve constant speed through almost
> instant acceleration to maximum speed.

Yes, thats one way.

You can also use the moveTo(), setSpeed(), runSpeedToPosition() idiom and not
be concerned with accelerations at all

Heres an example that reads input positions from Serial and uses that data to
set the stepper positions:


#include <AccelStepper.h>

// Alas its not possible to build an array of these with
// different pins for each :-(
AccelStepper stepper1(AccelStepper::FULL4WIRE, 2, 3, 4, 5);
AccelStepper stepper2(AccelStepper::FULL4WIRE, 8, 9, 10, 11);

void setup() {
Serial.begin(9600);
stepper1.setMaxSpeed(100);
stepper2.setMaxSpeed(100);

}

uint8_t buffer[2];
uint8_t buf_index = 0;

void loop() {
// If inpuit data is available, read it and interpret
// it as new positions
if (Serial.available())
{
buffer[buf_index++] = Serial.read();
if (buf_index >= 2)
{
buf_index = 0;
stepper1.moveTo(buffer[0]);
stepper1.setSpeed(50); // Cause moveTo changes the speed
stepper2.moveTo(buffer[1]);
stepper2.setSpeed(50); // Cause moveTo changes the speed
}

}

// Poll the steppers for possible movement
stepper1.runSpeedToPosition();
stepper2.runSpeedToPosition();
--
Mike McCauley VK4AMM mi...@airspayce.com
Airspayce Pty Ltd 9 Bulbul Place Currumbin Waters QLD 4223 Australia
http://www.airspayce.com
Phone +61 7 5598-7474

Mike McCauley

unread,
Aug 22, 2015, 10:43:38 PM8/22/15
to accels...@googlegroups.com
BTW, nice mechanical work John!

John Wall

unread,
Aug 23, 2015, 4:49:20 AM8/23/15
to accelstepper
Thank you both.

@ Gregor... The data I eventually receive has already been compared to the previous

John Wall

unread,
Aug 23, 2015, 9:48:57 AM8/23/15
to accelstepper


On Sunday, 23 August 2015 04:49:20 UTC-4, John Wall wrote:

 
Sorry about that.  Must have hit the wrong button.  As I was saying...
 

@ Gregor... The data I receive has already been compared to the last piece of data so only data that has changed is sent to the Arduino board.   That data goes into a global variable and then it is remapped as follows:  "targetPos = map(value,0,65535,0,945); with 0 to 945 being the available steps for that specific motor.  


So the only line I need in the void loop() function is "stepper.moveTo (targetPos);" and that will allow the motor to move in almost perfect sync and keep up with the simulator gauge??

  @Mike... I am probably going to replace the Arduino with ChipKit as one panel will have12 stepper motors in it... the Engine Instrument Monitoring (EMI) panel.  Thats why there is a need to be as efficient as possible with the code and of course unblocking would be an imperative.  There are several other sets of gauges that will only have at most 4 steppers in it so I will use Arduino for them.

As to the code you had posted:

// Alas its not possible to build an array of these with 
// different pins for each :-( ................................................................... Is this relevant to my situation?  Can you explain the significance of this statement please.

AccelStepper stepper1(AccelStepper::FULL4WIRE, 2, 3, 4, 5); .......... I will be using the Easy Driver for almost everything because of its microstepping capability.  Does that impact anything other                                                                                                                   than changing the statement to  "  AccelStepper stepper(1, 8, 9,); " 

AccelStepper stepper2(AccelStepper::FULL4WIRE, 8, 9, 10, 11);        

void setup() { 
  Serial.begin(9600); 
  stepper1.setMaxSpeed(100); 
  stepper2.setMaxSpeed(100); 
  

uint8_t buffer[2]; 
uint8_t buf_index = 0; 

void loop() { 
  // If inpuit data is available, read it and interpret 
  // it as new positions 
  if (Serial.available()) 
  { 
    buffer[buf_index++] = Serial.read(); 
    if (buf_index >= 2) 
    { 
      buf_index = 0; 
      stepper1.moveTo(buffer[0]); ..................I don't really know anything about buffers other than I had read that sometimes it makes things run better.  Will this be important for my application? 
      stepper1.setSpeed(50); // Cause moveTo changes the speed 
      stepper2.moveTo(buffer[1]); 
      stepper2.setSpeed(50); // Cause moveTo changes the speed 
    } 
    
  } 
  
  // Poll the steppers for possible movement 
  stepper1.runSpeedToPosition(); 
  stepper2.runSpeedToPosition();  

Thank you both for taking the time to look at my project and for your comments.  This project has been underway for the last 18 months now.   The cockpit gauges, as you could imagine, are such a large part of the simulator.  They will either make or break this project.  Your comments are most welcome.

Yes indeed, I will continue to post my progress with an emphasis on those items relevant to this forum. 

If you could respond to my questions in red above, I will then put together a sketch or two and do some more testing.

Thank you gentlemen.

Regards
John Wall  

Mike McCauley

unread,
Aug 23, 2015, 4:15:53 PM8/23/15
to accels...@googlegroups.com
None of the items you highlighted are critical to your needs.

Brian Schmalz

unread,
Aug 24, 2015, 9:14:12 AM8/24/15
to accels...@googlegroups.com
John,

Going with a chipKIT board is a great idea. One thing to consider is Digilent's new WiFire chipKIT board. You don't need the WiFi or SD card on it of course, but it runs a 200Mhz processor, and I don't think you'd have to worry too much about loading the CPU down with too many steppers.

*Brian


--
You received this message because you are subscribed to the Google Groups "accelstepper" group.
To unsubscribe from this group and stop receiving emails from it, send an email to accelstepper...@googlegroups.com.
For more options, visit https://groups.google.com/d/optout.

John Wall

unread,
Aug 24, 2015, 11:27:13 AM8/24/15
to accelstepper
Are you serious Brian...200Mhz!!!!!!!!!  I think you just made my day, maybe the whole year.  So what your suggesting is a $79.00 board with 41 IO pins which is basically 20 stepper motors using basically Arduino code, all running simultaneously in my cockpit. 

But is that a reasonable expectation ...20 steppers motors running of a 200Mhz processor.  This all pretty new to me so I'm not sure what the limitations might be but it sounds extremely promising so far. 

John

Brian Schmalz

unread,
Aug 24, 2015, 11:51:00 AM8/24/15
to accels...@googlegroups.com
John,

Yup. That's exactly what I'm suggesting.

I have not tried loading the WiFire down with lots of AccelStepper objects running at high speed to see where it bogs down. That would be a great test though (that you will probably be the first person in the world to attempt!).

I can tell you this though - on a "normal" chipKit board (running at 80MHz) I can easily get 10 AccelStepper objects running up to 4K steps/second or even higher. So I think that you should have no problem doing 20 steppers on the WiFire since you don't need really high step rates.

*****

As a related question - (mainly for Mike): Is there a good way for AccelStepper to know that it's taxing the CPU too much and steps are being generated incorrectly? I don't believe there is, and it would be a really neat think to think about adding. I'm not quite sure how it would work in practice, but it seems that you could grab the global time each time you step, and then the next time you actually take a step, look for how much time has elapsed. Normally you'll be able to step when you need to, since you're being called often enough. But if things are getting loaded down, you will be called and you'll check the time and you'll realize that your ideal time to take this next step has already passed. You'll take the step anyway, but then a flag could be set saying "This stepper motor object is not getting enough CPU time", and that flag could be read by the mainline Arduino code. This would allow us to design a pretty simple test for "how many stepper motors, running at what speeds, is this board able to handle".

*Brian

gregor

unread,
Aug 24, 2015, 3:25:00 PM8/24/15
to accelstepper
I think your main bottleneck will be the SPI communication, you may not be able to take advantage of the 200MHz cpu. 

John Wall

unread,
Aug 24, 2015, 5:08:11 PM8/24/15
to accelstepper


On Monday, August 24, 2015 at 3:25:00 PM UTC-4, gregor wrote:
I think your main bottleneck will be the SPI communication, you may not be able to take advantage of the 200MHz cpu. 

The baud rate we use to send/receive the data is 250,000 however, that doesn't mean much to me.   Now I could always run 2 of the UNO32 ChipKit boards at 80Mhz and using 10 stepper motors for each board. That is close to what I will ultimately need for the cockpit.  To be precise, I need to control 28 stepper motors.  

Do you still think that there may be a bottle neck at 250,000.

Another question just came to mind...Is it reasonable to have a function  called Stepper.zero that would set zero for you based on that command.  I noticed another library had that function. 

Mike McCauley

unread,
Aug 24, 2015, 5:23:49 PM8/24/15
to accels...@googlegroups.com, Brian Schmalz
Hi,

On Monday, August 24, 2015 10:50:58 AM Brian Schmalz wrote:
> John,
>
> Yup. That's exactly what I'm suggesting.

Brian prob has more experience with this than me, but I wonder of 20 steppers
might be too much? Prob need to test it comprehensively first. Certainly it
depends on the max sped configured. At any rate, even if the max speed of all
steppers moving at the same time cant be maintained, it should degrade
gracefully by going 'as fast as it can'.

>
> I have not tried loading the WiFire down with lots of AccelStepper objects
> running at high speed to see where it bogs down. That would be a great test
> though (that you will probably be the first person in the world to
> attempt!).
>
> I can tell you this though - on a "normal" chipKit board (running at 80MHz)
> I can easily get 10 AccelStepper objects running up to 4K steps/second or
> even higher. So I think that you should have no problem doing 20 steppers
> on the WiFire since you don't need really high step rates.

I think I agree with this.

>
> *****
>
> As a related question - (mainly for Mike): Is there a good way for
> AccelStepper to know that it's taxing the CPU too much and steps are being
> generated incorrectly? I don't believe there is, and it would be a really
> neat think to think about adding. I'm not quite sure how it would work in
> practice, but it seems that you could grab the global time each time you
> step, and then the next time you actually take a step, look for how much
> time has elapsed. Normally you'll be able to step when you need to, since
> you're being called often enough. But if things are getting loaded down,
> you will be called and you'll check the time and you'll realize that your
> ideal time to take this next step has already passed. You'll take the step
> anyway, but then a flag could be set saying "This stepper motor object is
> not getting enough CPU time", and that flag could be read by the mainline
> Arduino code. This would allow us to design a pretty simple test for "how
> many stepper motors, running at what speeds, is this board able to handle".

Interesting idea. Of course it then introduces the old conundrum in that it
would require yet more cycles to determine if there is a speed problem,
thereby compounding it :-(

BTW, the most expensive (slow) operation in the stepper code is the square
root required for the _first_ step of a move.

Cheers.

gregor christandl

unread,
Aug 24, 2015, 5:38:22 PM8/24/15
to accels...@googlegroups.com

Hi,
With "bottleneck" i meant it will be the slowest part of the code, but not necessarily so slow that it becomes a problem. I am just wondering if it pays off to have a powerful CPU to accelerate some rather lightweight functions (assuming you use runSpeedToPosition()) when the time it takes to receive a complete SPI message is the same for a 200MHz cpu and a 16MHz cpu (that most arduinos use).

AccelStepper has a function setCurrentPosition(), is this what you are looking for? Or do you need a function that moves your steppers to their respective home positions? The latter you will have to implement yourself.


--

Mike McCauley

unread,
Aug 24, 2015, 9:56:38 PM8/24/15
to accels...@googlegroups.com, Brian Schmalz
On Tuesday, August 25, 2015 07:23:44 AM Mike McCauley wrote:
> Hi,
>

>
> BTW, the most expensive (slow) operation in the stepper code is the square
> root required for the _first_ step of a move.


Actually when I double check the code thats not true.
The expensive square root occurs when you call setAcceleration().

Cheers.

poriya kiani

unread,
Aug 25, 2015, 4:27:59 AM8/25/15
to accelstepper

 hey every body sorry to interrupt i was searching the web about a code for making pulses for easy driver that i saw this very useful topic.
 since English is not my first language please apologies me for grammatical mistakes. 
 i have confused about sth that i hope you guys could help me about it. excuse me if my questions are very simple.
 i have a project that i have to control 4 stepper motor in to ways one way is to control them with one joystick and the other way is to control them with serial connection with computer i am using 4 tb660 driver that has almost same principle as easydriver and an arduino mega board.
 my main problem is that i dont know how to provide the clock that driver needs.

since i have 4 stepper motors that might work at the same time i can't use this code right here because of delay times:

digitalWrite(9, HIGH);
  delayMicroseconds(100);          
  digitalWrite(9, LOW); 
  delayMicroseconds(100);

so i searched the web and  confront accelstepper library.

 as far as i know we can drive a bipolar stepper by using easy driver and in order to do that it is just enough to provide step input and direction input on driver
 now i'm confused about these commands " AccelStepper stepper1(AccelStepper::FULL4WIRE, 2, 3, 4, 5); " &  "  AccelStepper stepper(1, 8, 9,); "
it seems to me that these commands are for when we want to drive stepper motor with the controller chip directly , am i write? and if we can use these codes to provide step input and direction input please tell me how to do it and which pin is what. i think you guys mentioned that it is ok to use "  AccelStepper stepper(1, 8, 9,); " but i didn't get it why it is ok to do. that isn't this code for driving steppet directly? would you please clear that for me.

it is so important to me that all 4 stepper motors can rotate simultaneously if it is needed. do you think the ardoino mega is capable of doing that? the speed or acceleration is not so important to me and i can trade off these parameters for the important mean which is rotating in the exact time.

thanks for your replies i would really appreciate it.

Mike McCauley

unread,
Aug 25, 2015, 4:43:22 AM8/25/15
to accels...@googlegroups.com
Hello,
Yes.
AccelStepper stepper1(AccelStepper::FULL4WIRE, 2, 3, 4, 5)
means its a 4 wire full stepper connected to pin 2, 3, 4, 5

AccelStepper stepper(1, 8, 9,);
means use a driver (eg easy driver) connected to pins 8 (for step) and 9 for
(direction)


> and if we can use
> these codes to provide step input and direction input please tell me how to
> do it and which pin is what. i think you guys mentioned that it is ok to
> use " AccelStepper stepper(1, 8, 9,); " but i didn't get it why it is ok
> to do. that isn't this code for driving steppet directly? would you please
> clear that for me.

Its not the best way to do it but 1 means DRIVER.

It is better to say it like:
AccelStepper stepper(AccelStepper::DRIVER, 8, 9,);

>
> it is so important to me that all 4 stepper motors can rotate
> simultaneously if it is needed. do you think the ardoino mega is capable of
> doing that?

Yes.

> the speed or acceleration is not so important to me and i can
> trade off these parameters for the important mean which is rotating in the
> exact time.
>
> thanks for your replies i would really appreciate it.

You should also carefully read the documentation.

poriya kiani

unread,
Aug 25, 2015, 7:02:14 AM8/25/15
to accelstepper
>AccelStepper stepper(1, 8, 9,); 
>means use a driver (eg easy driver) connected to pins 8 (for step) and 9 for 
>(direction) 
thanks a lot mike for your reply that was a really big help i tried to figured it out from the documentation but i couldn't


but still i have a little bit problem with using  " AccelStepper stepper(1, 8, 9,) ":

as far as i know for using this command i have to set a position then set speed and acceleration and finally use stepper.run() i did it successfully as follow and it worked:

AccelStepper stepper(1, 9, 8);
int pos = 100;
  stepper.setMaxSpeed(300);
  stepper.setAcceleration(300);
  stepper.run();

(i just omitted unnecessary lines:)
 my question is: can i use the direction pin directly like this?

AccelStepper stepper(1, 9, 8);
  digitalWrite(8, HIGH);

and can i access and change direction Enumerator my self if yes how can i do that?
i am asking that because i want to control the steeper by using a joy stick that the movement of joystick control the direction and speed of motor.
if you know any better way to do this please clear it out for me.


for begining this code came to mind:

#define X_pin A0  // Pin A0 connected to joystick x axis
  stepper.setMaxSpeed(300);
  stepper.setAcceleration(300);

while (analogRead(X_pin) >= 0) {

  digitalWrite(8, HIGH);
  stepper.run();
}

but as i guessed it didn't work i tried to change it a little bit like adding positive and negative position and etc ,  but it didn't work

for understanding better what i'm about to do imagine this example:

i want to write a code that as long as the x axis of joystick have a certain value the stepper rotate in a certain direction and speed for example if the x axis goes a bit up the stepper rotate clockwise and it rotates as long as the x axis is still up. and if x axis goes down the stepper rotate counter-clockwise as long as the x axis is down.

what is your suggestion what do you think i should do?
and do you think if i can do it for one stepper can i do it for four stepper without any collision or conflict?


gregor

unread,
Aug 25, 2015, 7:30:51 AM8/25/15
to accelstepper
i am asking that because i want to control the steeper by using a joy stick that the movement of joystick control the direction and speed of motor.
if you know any better way to do this please clear it out for me.

for this use case it is probably better to use setSpeed() and runSpeed().
for the example below i assume you have a joystick connected to pin A0 on your Arduino.
when using setSpeed(), a positive speed will make the stepper turn clockwise, a negative speed will make it turn counter-clockwise.

#define MAXSPEED 100  //the maximum speed of your stepper (both directions)

uint16_t joystick_value
;
int speed;

void loop()
{
  joystick_value = analogRead(A0);

  int speed = map(joystick_value, 0, 1024, -MAXSPEED, MAXSPEED );    //map joystick input to -MAXSPEED to +MAXSPEED range

  stepper.setSpeed(speed);

  stepper.runSpeed();
}  




John Wall

unread,
Aug 25, 2015, 11:53:21 AM8/25/15
to accelstepper, brian....@gmail.com
I've been doing so testing on my engine instrument panel based on the previous discussions we've had and a problem has occurred that I cannot seem to resolve. 

The test starts with a Pro Mini, an Easy Driver board and a VID29 stepper motor (used in automobile dashboard gauges).  It has 615 full steps from stop to stop.  I setup the ED to run at full steps and used a 5v PSU fro the motors
  
void setup() {
  stepper.setMaxSpeed(2000.0);
  stepper.setAcceleration(2000.0);
  stepper.setSpeed(400);
  stepper.runToNewPosition(-615);  //backwards sweep to find hard stop
  stepper.setCurrentPosition(0); //establishes the zero position
}

void loop() { 
 stepper.moveTo(600); //move to almost full range of motion
 stepper.moveT0(0);//return to zero
 stepper.run():
}

At 5v motor supply voltage it works beautifully.  If I use 12V it runs way to fast.
So then I duplicate everything to create a second stepper motor (stepper2...) with another ED board with the same code and config...same everything.
This is where the problem starts.

One motor runs well, the other is stop and start, erratic. I run it at 12v this time...same issue so I go back to 5v.  Each time I adjust current, No impact.
I comment out the second motor and run it again but with one only motor (its fine) and then run it with the other motor (its fine as well) to rule out bad motor.
I swap out ED boards in case bad board.  Same as above, both work fine individually.

So the problem begins when I use 2 ED boards and 2 motors with a single Pro Mini  (Pins 8,9 and 10,11).

I am wondering if the Pro Mini is the cause but it runs at 16Mhz?  Any ideas as to what may be causing this. 

gregor

unread,
Aug 25, 2015, 12:03:39 PM8/25/15
to accelstepper, brian....@gmail.com
Hi, 
can you post code with both steppers that has this problem? The Arduino will most likely not be the problem.

this code:
void loop() { 
 stepper.moveTo(600); //move to almost full range of motion
 stepper.moveT0(0);//return to zero
 stepper.run():
}
will not move the stepper at all. 

John Wall

unread,
Aug 25, 2015, 1:48:33 PM8/25/15
to accelstepper, brian....@gmail.com
Hi Gregor

This is what I used for 2 stepper motors:

#include <AccelStepper.h>

AccelStepper stepper (1, 8, 9);//driver, step, direction
AccelStepper stepper1 (1, 10, 11);//driver, step, direction

void setup() {
  stepper.setMaxSpeed(2000.0);
  stepper.setAcceleration(2000.0);
  stepper.setSpeed(400);
  stepper.runToNewPosition(-630); //backwards sweep to find hard stop
  stepper.setCurrentPosition(0);//establishes the zero position

  stepper1.setMaxSpeed(2000.0);
  stepper1.setAcceleration(2000.0);
  stepper1.setSpeed(400);
  stepper1.runToNewPosition(-630); //backwards sweep to find hard stop
  stepper1.setCurrentPosition(0);//establishes the zero position

}

void loop() {
 stepper1.moveTo(630);
 stepper.moveTo(630);
 stepper1.run();
 stepper.run();
}

This is a cut/n/paste right from the IDE.

Thanks
John

gregor

unread,
Aug 25, 2015, 1:53:15 PM8/25/15
to accelstepper, brian....@gmail.com
you should not use setSpeed() when using run(). setSpeed() is only for officially supported for usage with runSpeed().
Also, set the target position only once, do not set it in every program loop.

#include <AccelStepper.h>


AccelStepper stepper (1, 8, 9);//driver, step, direction
AccelStepper stepper1 (1, 10, 11);//driver, step, direction


void setup() {
  stepper
.setMaxSpeed(2000.0);
  stepper
.setAcceleration(2000.0);

  stepper
.runToNewPosition(-630); //backwards sweep to find hard stop
  stepper
.setCurrentPosition(0);//establishes the zero position


  stepper1
.setMaxSpeed(2000.0);
  stepper1
.setAcceleration(2000.0);

  stepper1
.runToNewPosition(-630); //backwards sweep to find hard stop
  stepper1
.setCurrentPosition(0);//establishes the zero position


 
//set target once
  stepper1
.moveTo(630);
  stepper
.moveTo(630);
}


void loop() {
 stepper1
.run();
 stepper
.run();
}

poriya kiani

unread,
Aug 25, 2015, 4:00:21 PM8/25/15
to accelstepper
thanks a lot for your reply gregor i really appreciate it
 
i tried to use this code like you said:


#include <AccelStepper.h>
#define X_pin A0
#define MAXSPEED 300  //the maximum speed of your stepper (both directions)


AccelStepper stepper(1, 9, 8);
uint16_t X_pinval
;
int speed;


void setup() {
 
// put your setup code here, to run once:




}
void loop()
{
  X_pinval
= analogRead(A0);


 
int speed = map(X_pinval, 0, 1023, -MAXSPEED, MAXSPEED );    //map joystick input to -MAXSPEED to +MAXSPEED range


  stepper
.setSpeed(speed);


  stepper
.runSpeed();
}  

but it didn't work the stepper seemed to try to move but it just had some random steps i tried to change the code a bit but nothing changed then i thought that maybe there is something wrong with the joy stick so i searched and found this code to test it:

// Arduino pin numbers


//#define X_pin  A0 // analog pin connected to X output
//#define Y_pin  A1 // analog pin connected to Y output
 
const int SW_pin = 2; // digital pin connected to switch output
 
const int X_pin = A0;         // joystick X axis  
 
const int Y_pin = A1;         // joystick Y axis


 
//int X_Pin = A1;
 
 
//int Y_Pin = A0;


 
void setup() {
  pinMode
(SW_pin, INPUT);
 
//digitalWrite(SW_pin, HIGH);
 
//pinMode(X_pin, INPUT);
 
//pinMode(Y_pin, INPUT);


 
//pinMode(SW_pin, INPUT_PULLUP);
 
Serial.begin(115200);
}
 
void loop() {
 
Serial.print("Switch:  ");
 
Serial.print(digitalRead(SW_pin));
 
Serial.print("\n");
 
Serial.print("X-axis: ");
 
Serial.print(analogRead(X_pin));
 
Serial.print("\n");
 
Serial.print("Y-axis: ");
 
Serial.println(analogRead(Y_pin));
 
Serial.print("\n\n");
  delay
(1000);
}

and i connected the joystick like this:



the results were a bit worrying when i opened the serial monitor the results were complitly random as follow:

Switch:  1
X
-axis: 316
Y
-axis: 614




Switch:  1
X
-axis: 833
Y
-axis: 565




Switch:  0
X
-axis: 725
Y
-axis: 214




Switch:  1
X
-axis: 426
Y
-axis: 140




Switch:  0
X
-axis: 16
Y
-axis: 849




Switch:  0
X
-axis: 525
Y
-axis: 203




Switch:  1
X
-axis: 462
Y
-axis: 631

this problem happened while the joystick was at its rest position and as result the values for both axis should be something about 512 but it is random at first i thought  that the code is wrong so changed it a bit but nothing good happened and sometimes when i was pushing the button at axis rest points (512) the values of both axis were going to 1023. finally i switched joystick power supply to an adapter but the problem didn't solve

i think maybe the joystick is damaged and there is nothig wrong with the code or connection
what is your your idea about this guys?

 

Mike McCauley

unread,
Aug 25, 2015, 5:32:58 PM8/25/15
to accels...@googlegroups.com
Hello John,

There are a few problems with the code you sent:

1. You are using setSpeed with run(). SetSpeed is only for use in constant
speed environments. Looks like you want to use accelerated steppers (viz
setting the accel with setAcceleration().

2. You are setting 2 new target positions every time through the loop and not
giving it a chance to move. moveTo does not actually implement the move, it
only sets a new target position.


To test a single stepper you prob want (untested):


void setup() {
stepper.setMaxSpeed(200.0);
stepper.setAcceleration(2000.0);
stepper.runToNewPosition(-615); //backwards sweep to find hard stop
stepper.setCurrentPosition(0); //establishes the zero position
}

void loop() {
stepper.moveTo(600); //move to almost full range of motion
stepper.runToPosition(); // Blocks until move completed
stepper.moveTo(0);//return to zero
stepper.runToPosition(); // Blocks until move completed
}


A more common idiom and the one you will want in your finished code is
(pseudocode)


void loop() {
if (get a new new position command)
{
stepper.moveTo(whatever);
}
stepper.run();
}

It is vitally important to understand that you need to call run() *as often as
possible* in the loop() but only set new target positions very occasionally
(when a new command arrives)

In the case of multiple steppers you would want:

void loop() {
if (get a new new command)
{
if (its for stepper 1)
stepper1.moveTo(whatever);
if (its for stepper 2)
stepper2.moveTo(whatever);
}
stepper1.run();
stepper1.run();
}

Cheers.
> *individually.*
> > mi...@airspayce.com
> >
> > > > >>> Airspayce Pty Ltd 9 Bulbul Place Currumbin Waters QLD 4223
> >
> > Australia
> >
> > > > >>> http://www.airspayce.com
> > > > >>> Phone +61 7 5598-7474
> >
> > send
> >
> > > > >>> an email to accelstepper...@googlegroups.com.
> > > > >>> For more options, visit https://groups.google.com/d/optout.
> > > > >
> > > > > You received this message because you are subscribed to the Google
> > > > > Groups
> > > > > "accelstepper" group.
> > > > > To unsubscribe from this group and stop receiving emails from it,
> >
> > send
> >
> > > > > an
> > > > > email to accelstepper...@googlegroups.com <javascript:>.

John Wall

unread,
Aug 25, 2015, 8:46:54 PM8/25/15
to accelstepper
Mike and Gregor

Well Gregor the code revisions you gave me and Mike the reduction in speed both worked to the point that the motors now move smoothly.  The first motor zeroed in and then the second zeroed in.  Then they both moved to the position (620) I had asked for and they both started at exactly the same time and they both reached the destination at exactly the same time.  Success!!

Now Mike, you stated that "you need to call run() *as often as possible* in the loop()" .   I'm not sure what that actually means because you generally call run once, as the last statement and there are no other opportunities where you can call for run.  Am I missing something here.  I have read that statement several times over the past few weeks.  It just doesn't register as to what I should do other that include it in the loop.  Are you suggesting it read like this???

void loop() { 

 stepper.run();
 stepper.run();
 stepper.run();
 stepper.run();
 stepper.run();  etc.


Could you elaborate on this please.  It's been on my mind for some time and I just don't get it.  I'm sure it will be one of those "DOH!" moments when it finally hits me.

Other than that, I will try your code later tomorrow but I wanted to ask, so I create a variable and any time the data is different from the last piece of data,  it is placed in that variable. In other words I replace your "whatever" with my variable name and the motors start running with the sim, so to speak. 

if (get a new new command) 
        { 
                if (its for stepper 1) 
                        stepper1.moveTo(whatever); 
                if (its for stepper 2) 
                        stepper2.moveTo(whatever); 
        } 
        stepper1.run(); 
        stepper1.run(); 



I will give that a try with real time data from the sim on the weekend and see how it runs.  I think I am getting to understand some of this.  It all amounts to understanding HOW the commands work.  I misinterpreted several of them thinking they did something entirely different. 

Thanks guys.  I very much want to get these gauges running with the simulator.   I would like to write a tutorial for gauge building on my home forum...http://forums.eagle.ru/forumdisplay.php?f=101

There are a lot of people who have basic enough skills to make a gauge but getting it to run with the simulator (read:code) is beyond a lot of peoples abilities.  I would like to change that, if I can, and make it easier for them if at all possible.

Regards
John 






On Tuesday, August 25, 2015 at 5:32:58 PM UTC-4, mikem wrote:
Hello John,

There are a few problems with the code you sent:

1. You are using setSpeed with run(). SetSpeed is only for use in constant
speed environments. Looks like you want to use accelerated steppers (viz
setting the accel with setAcceleration().

2. You are setting 2 new target positions every time through the loop and not
giving it a chance to move. moveTo does not actually implement the move, it
only sets a new target position.


To test a single stepper you prob want (untested):


void setup() {
  stepper.setMaxSpeed(200.0);
  stepper.setAcceleration(2000.0);
  stepper.runToNewPosition(-615);  //backwards sweep to find hard stop
  stepper.setCurrentPosition(0); //establishes the zero position
}

void loop() {
 stepper.run

Mike McCauley

unread,
Aug 25, 2015, 8:57:21 PM8/25/15
to accels...@googlegroups.com
Hi John,

On Tuesday, August 25, 2015 05:46:53 PM John Wall wrote:
> Mike and Gregor
>
> Well Gregor the code revisions you gave me and Mike the reduction in speed
> both worked to the point that the motors now move smoothly. The first
> motor zeroed in and then the second zeroed in. Then they both moved to the
> position (620) I had asked for and they both started at exactly the same
> time and they both reached the destination at exactly the same time.
> Success!!
>
> Now Mike, you stated that "you need to call run() *as often as possible* in
> the loop()" . I'm not sure what that actually means because you generally
> call run once, as the last statement and there are no other opportunities
> where you can call for run. Am I missing something here. I have read that
> statement several times over the past few weeks. It just doesn't register
> as to what I should do other that include it in the loop. Are you
> suggesting it read like this???
>
> void loop() {
>
> stepper.run();
> stepper.run();
> stepper.run();
> stepper.run();
> stepper.run(); etc.
> }

No.

>
> Could you elaborate on this please. It's been on my mind for some time and
> I just don't get it. I'm sure it will be one of those "DOH!" moments when
> it finally hits me.

loop() is automatically called over and over again.
stepper.run() steps the motor one step if a step has become due (or overdue).

What I mean is that you must call stepper.run() within the loop() and make
sure nothing else blocks operations for so long that steps will be missed:

This is good:

loop()
{
if (some infrequent event occurs)
deal with it quickly;
stepper.run();
}

This is bad:

loop()
{
do something that takes a long time;
stepper.run()
}


The meanings of 'quickly' and 'long time' depend entirely on your maximum
*required* stepping rate.

The end result must be that stepper.run() gets called as often as possible,
with everything else taking second priority.
If your code design cant attain this ideal then AccelStepper is not for you.


Cheers.

John Wall

unread,
Aug 26, 2015, 8:46:26 AM8/26/15
to accelstepper
Thanks Mike for the clarification.  That is what I thought since I couldn't see any other way to call it.  I just need to ensure no blocking function prevents that from happening.   I'll go through the list of commands and separate the blocking functions on a little cheat sheet so I avoid them.  I need to keep the code as clean and sleek as possible with so much data being acted upon so quickly.

I'll be back in  a few days with the result of our discussions and with any luck all will be running as it should.

Thanks again
John Wall

James Conway

unread,
Aug 26, 2015, 10:09:43 AM8/26/15
to accels...@googlegroups.com
I have successfully set up a simple stepper-motor solution with the AccelStepper library and an Arduino that maintains a platform at a constant height (using 2 light sensors) so that film holders can be reliably discarded by a robotic arm. The topic here is interesting, especially as it pushes the limits of a low-end microcontroller for how many motors it can control and with what fidelity. As a one-time assembly language programmer, it seems to me that the poll-in-a-loop is prone to delays outside the stepper motor servicing code, and why not put the time-sensitive stuff into an interrupt handler to guarantee service calls at the frequency needed? Obviously the interrupt handler has to be often enough but not too often, and light enough that it doesn’t impact on itself (ie run too long so that the next interrupt is skipped), but it leaves the higher-level non-sensitive code free to do as it wants, which takes a lot of effort off the programmer. I did in fact implement this for my simple job - and I know its not entirely safe because the library is not written with that use in mind, but in fact it works fine.

What would it take to make an interrupt-handled version of AccelStepper run reliably? I appreciate there are subtleties here, such as the target position, the speed or the acceleration being changed while an interrupt to call run happens, and so some guarding of internal variables might be necessary, but would there be much beyond that? I think this would make use of the library easier, as long as the interrupt routine is limited to simple operations like myStepper.run().
 
Of course, I may be wrong about that!

James Conway


-- 

You received this message because you are subscribed to the Google Groups "accelstepper" group.
To unsubscribe from this group and stop receiving emails from it, send an email to accelstepper...@googlegroups.com.

For more options, visit https://groups.google.com/d/optout.



----------------------------------------------------------------------
James Conway, PhD.,
Associate Professor, Department of Structural Biology
Director, Molecular Biophysics and Structural Biology Graduate Program
University of Pittsburgh School of Medicine
Biomedical Science Tower 3, Room 2047
3501 5th Ave
Pittsburgh, PA 15260
U.S.A.
Phone: +1-412-383-9847
Fax:   +1-412-648-8998
Email: jxc...@pitt.edu
Web:   http://www.structbio.pitt.edu/main/people/faculty/71-conway  
----------------------------------------------------------------------

gregor

unread,
Aug 26, 2015, 1:12:38 PM8/26/15
to accelstepper
i just ran a little test (Arduino Mega 2560):
#include <AccelStepper.h>

#define NUM_STEPPERS 20

AccelStepper *steppers[NUM_STEPPERS];

void setup()
{  
  Serial.begin(9600);
  Serial.println("begin");
  
  for (int i = 0; i < NUM_STEPPERS; i++)
  {
    steppers[i] = new AccelStepper(AccelStepper::DRIVER, 2*i + 3, 2*i+ 1 + 3);

    steppers[i]->setMaxSpeed(200.0);
    steppers[i]->setSpeed(100.0);
  }
}

void loop()
{
  unsigned long start_time = millis();
  unsigned long stop_time;
  uint16_t counter;

  do
  {
    counter++;

    for (int i = 0; i < NUM_STEPPERS; i++)
    {
      steppers[i]->runSpeed();
    }    
  }
  while (counter != 0);

  stop_time = millis();

  Serial.print("time needed: ");
  Serial.print(stop_time - start_time);
  Serial.println("ms");
}

begin
time needed: 14474ms
time needed: 14475ms
time needed: 14475ms
time needed: 14475ms
time needed: 14475ms
time needed: 14475ms
time needed: 14475ms
time needed: 14475ms

14475 / 65536 = 0.2208709716796875 ms needed in average for stepping 20 steppers using runSpeed() (~0.011 ms per stepper).
Reply all
Reply to author
Forward
0 new messages