Steppers are moving slower when using additional code

2,500 views
Skip to first unread message

BlueGene003

unread,
Apr 13, 2013, 12:15:15 PM4/13/13
to accels...@googlegroups.com
Hi,

My project consists of 2 stepper motors(with Pololu drivers), a 16x2-LCD-Display and a Joystick as control.

Without the analogRead and the switch/case, the steppers move normally(fast). As soon as I use the analogRead and the switch/case, the steppers go really, really slow.

Which part of the code is blocking the steppers? Is there any solution to get to steppers moving properly?

-------------------------------------

void setup()
{
    pinMode (button0, INPUT);
    pinMode (joyX, INPUT);
    pinMode (joyY, INPUT);
  lcd.begin(16, 2);              // start the library
  AccelStepperX.setMaxSpeed(2000);
  AccelStepperX.setAcceleration(1000);
  AccelStepperX.moveTo(-8000);
}

void loop()
{
    AccelStepperX.run();
    
  //-------------Einlesen der Eingaben-----------------
  joyX_value = analogRead(joyX);
  joyY_value = analogRead(joyY);
  button0_value = analogRead(button0);

  switch(progStep){

    //------Auswahl Modus-------
  case 0:
    AuswahlModus();
    break;
    //------Auswahl Motion-------
  case 1:
    AuswahlMotion();
    break;
    //------Auswahl Programmablauf-------
  case 2:
    switch (modus){
    case 0:
      video();
      break;

    case 1:
      timelapse();
      break;

    case 2:
      pano();
      break;
    }
    break;

  } // switch (progStep)
} // void loop()

Sandy Noble

unread,
Apr 13, 2013, 12:50:53 PM4/13/13
to accels...@googlegroups.com
Hello, I bet it'll be the analogRead()s that are slowing it down, but you could test it by doing

  joyX_value = 0;
  joyY_value = 0;
  button0_value = 0;

and see if that speeds everything up again.

To get around it, you could reduce number of times you poll for joy/button.

// only poll for values once every 100 loops
i++;
if (i > 100)
{
  joyX_value = analogRead(joyX);
  joyY_value = analogRead(joyY);
  button0_value = analogRead(button0);  
  i = 0; // reset counter
}


Or poll every 500 milliseconds:

if (lastInputCheckTime > (millis() + 500))
{
  joyX_value = analogRead(joyX);
  joyY_value = analogRead(joyY);
  button0_value = analogRead(button0);  
  lastInputCheckTime = millis();
}

A smarter way to do it might be to set up an "interrupt on value change", but arduino only has two interrupts normally, so that might not be trivial.

sandy noble



--
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/groups/opt_out.
 
 



--
Sandy Noble

BlueGene003

unread,
Apr 13, 2013, 1:30:27 PM4/13/13
to accels...@googlegroups.com
I have allready tested without the analogRead, but the Switch/Case is the bigger problem. As soon as I use it, the steppers are moving really slow.

Here is complete code:

[code]
#include <LiquidCrystal.h>
#include <AH_Pololu.h>
#include <AccelStepper.h>

LiquidCrystal lcd(29, 27, 22, 24, 26, 28);

//-------------Defintion for AH_Pololu-----------------
AH_Pololu stepperY(200,30,31,51,50,49,48); // Kippen
AH_Pololu stepperX(200,34,35,45,44,43,42); // Drehen

//-------------Defintion for AccelStepper-----------------
AccelStepper AccelStepperY(1, 31, 30); // Kippen
AccelStepper AccelStepperX(1, 35, 34); // Drehen

//-------------Defintion Analoge Eingänge-----------------
const int button0 =  A0; 
const int joyX =  A1; // Nullwert = 525
const int joyY =  A2; // Nullwert = 537

//-------------Werte Analoge Eingänge-----------------
int button0_value = 0;
int joyX_value = 0;
int joyY_value = 0;

int progStep = 0; // 0 = Auswahl Modus -- 1 = Auswahl Motion -- 2 = Programmablauf
int modus       = 0; // 0=VIDEO   --  1=TIMELAPSE  --  2=PANO
int motionModus = 0; // 0=SLIDER  --  1=PANOHEAD   --  2=BOTH

int caseVIDEO = 0;
int caseTIMELAPSE = 0;
int casePANO = 0;

int hzX;
int schrittX =0;

int hzY;
int schrittY =0;
void setup()
{
    pinMode (button0, INPUT);
    pinMode (joyX, INPUT);
    pinMode (joyY, INPUT);
  //Serial.begin(115200);
} // void loop()[/code]

[code]
//---------------------------------------------------------------
//-----------------------Auswahl Modus---------------------------
//---------------------------------------------------------------

void AuswahlModus(){
  //-------Auswahl Modus - Anzeige---------
  lcd.setCursor(1,0);
  lcd.print("VIDEO"); 
  lcd.setCursor(1,1);
  lcd.print("TIMELAPSE"); 
  lcd.setCursor(12,0);
  lcd.print("PANO");   
  //------Auswahl Modus - Control-Display-----------
  if (modus==0){
    lcd.setCursor(0,0);
    lcd.print(">"); 
  }
  else if(modus==1){
    lcd.setCursor(0,1);
    lcd.print(">"); 
  }
  else{
    lcd.setCursor(11,0);
    lcd.print(">"); 
  }

  //-------Auswahl Modus - Control-Funktion---------------------------------
  if(joyX_value>1000){
    delay(400);

    if(modus==0){
      modus=1;
    }
    else if(modus==1){
      modus=2;
    }
    else{
      modus=0;
    }
    lcd.clear();
  }
  if(button0_value>1000){
    delay(400);
    progStep+=1;
    lcd.clear();
  }
}
//---------------------------------------------------------------
//----------------------Auswahl Motion---------------------------
//---------------------------------------------------------------

void AuswahlMotion(){

  //-------Auswahl Motion - Anzeige---------------------------
  lcd.setCursor(1,0);
  lcd.print("PAN/TILT"); 
  lcd.setCursor(1,1);
  lcd.print("SLIDER"); 
  lcd.setCursor(12,0);
  lcd.print("BOTH");   
  //------Auswahl Motion - Control-Display--------------------------------
  if (motionModus==0){
    lcd.setCursor(0,0);
    lcd.print(">"); 
  }
  else if(motionModus==1){
    lcd.setCursor(0,1);
    lcd.print(">"); 
  }
  else{
    lcd.setCursor(11,0);
    lcd.print(">"); 
  }

  //------Auswahl Motion - Control-Funktion--------------
  if(joyX_value==1023){
    delay(400);

    if(motionModus==0){
      motionModus=1;
    }
    else if(motionModus==1){
      motionModus=2;
    }
    else{
      motionModus=0;
    }
    lcd.clear();
  }

  if(button0_value>1000){
    delay(400);
    progStep+=1;
    lcd.clear();
  }
}
[/code]

[code]
//---------------------------------------------------------------
//---------------------------VIDEO-------------------------------
//---------------------------------------------------------------
void video(){
  
  //-----------Caseweiterschaltung durch Button----------
  if(button0_value>1000){
    delay(400);
    caseVIDEO+=1;
    lcd.clear();
  }
  
  int HzX =4000;

  switch (caseVIDEO){

  case 0:
    lcd.setCursor(6,0);
    lcd.print("MOVE"); 
    lcd.setCursor(0,1);
    lcd.print("TO STARTPOSITION");
    
stepperX.setSpeedHz(1000); 
stepperX.move(-10); 
delay(100);
   // stepperX.setSpeedHz(HzX);
   // stepperX.move(16);



 /*      //-----------X----------------------
   if (joyX_value >550 && joyX_value<700)
   {
   schrittX-=8;
   hzX =300;
   }
   if (joyX_value >700 && joyX_value <1020)
   {
   schrittX-=8;
   hzX =1000;
   }
   if (joyX_value >1020)
   {
   schrittX-=8;
   hzX =5000;
   }
   
   if (joyX_value <520 && joyX_value>300)
   {
   schrittX+=8;
   hzX =300;
   }
   if (joyX_value <300 && joyX_value >20)
   {
   schrittX+=8;
   hzX =1000;
   }
   if (joyX_value <20)
   {
   schrittX+=8;
   hzX =5000;
   }
  //-----------------Y----------------------
  if (joyY_value >540 && joyY_value<700)
  {
    schrittY+=8;
    hzY =300;
  }
  if (joyY_value >700 && joyY_value <1020)
  {
    schrittY+=8;
    hzY =1000;
  }
  if (joyY_value >=1020)
  {
    schrittY+=8;
    hzY =5000;
  }

  if (joyY_value <510 && joyY_value>300)
  {
    schrittY-=8;
    hzY =300;
  }
  if (joyY_value <300 && joyY_value >5)
  {
    schrittY-=8;
    hzY =1000;
  }
  if (joyY_value <=5)
  {
    schrittY-=8;
    hzY =5000;
  }
  
  stepperX.setSpeedHz(hzX);   
  stepperX.move(schrittX);
   
  stepperY.setSpeedHz(hzY);
  stepperY.move(schrittY);*/
    break;

  case 1:
    break;

  case 2:
    break;

  case 3:
    break;

  case 4:
    break;
  }
}


//---------------------------------------------------------------
//-------------------------TIMELAPSE-----------------------------
//---------------------------------------------------------------
void timelapse(){
  lcd.setCursor(0,1);
  lcd.print("TIMELAPSE"); 

}

//---------------------------------------------------------------
//----------------------------PANO-------------------------------
//---------------------------------------------------------------
void pano(){
  lcd.setCursor(0,1);
  lcd.print("PANO"); 

}
[/code]

Sandy Noble

unread,
Apr 13, 2013, 5:26:07 PM4/13/13
to accels...@googlegroups.com
Hi well that would have been helpful to know beforehand - your switch/case is innocuous in itself, so it has to be some of the stuff that it calls.

On startup, if progStep stays at 0 (so button0 never gets pressed), then AuswahlModus() is the only sub-routine that gets called.  Now that has some delays in it, but as far as I can see they are only triggered when there's some input (joystick or button is pressed).  Otherwise the only things that could be delaying are the writes to the LCD.

When I've stuff that writes to LCDs I was surprised by how slow they were, so it could just be that.  Why not add some timers in the suspect sections to see where the delay is?  There are all kinds of LCDs though, so maybe mine were just slow.

I don't know if there's a way around the slowness of writing to LCDs, except doing it less frequently.

sn

BlueGene003

unread,
Apr 14, 2013, 9:48:58 AM4/14/13
to accels...@googlegroups.com
You are right, the LiquidCrytal-library is causing the slow speed. I´ve looked into the library an found several delayMicroseconds in it. 

Are there other LCD libraries without blocking/delay?

Sandy Noble

unread,
Apr 14, 2013, 10:49:25 AM4/14/13
to accels...@googlegroups.com
I imagine the delays are there for a reason - but you might find that they are not necessary on all devices.  I don't know much about driving LCDs.  Try taking them out and see what happens?

sn

Jon Magill

unread,
Apr 14, 2013, 2:32:40 PM4/14/13
to accels...@googlegroups.com
I had similar issues when I first started trying to use the accelstepper library with other user interface stuff at the same time.

My first hint was that my steppers maxed out at the same speed I had my serial communications set to (9600 in my first experiments). I was also polling a pot, sort of like your joystick, and with help from a post by Brian Schmalz I did exactly what Sandy suggests, set up a timer, or a mills() with an if() to check at less frequent intervals (think seconds here).

Most things like a joystick or LCD need very infrequent polling or updating, on the order of seconds rather than milli- or micro-seconds. I have also switched over to using the I2C LCD backpack from Adafruit (and their library for it) for my 20x4 so that my LCD is getting updates via serial. That has helped balance speeds.

Finally, all that said, for my multi-stepper setups I have done my basic prototyping (get stuff working) on the Arduino Uno and then moved things over to the Digilent Uno32 (80 MHz) for actual running. Most but not all libraries work on the Uno32/µ32 (supposed status here: http://www.chipkit.org/wiki/index.php?title=Library_Status), so that has been one of the limiting factors for some of my projects.

The Arduino Due at 84 MHz might be an option too, but I think it has some library issues with what works and doesn't work at the moment too. I haven't tried one of those yet. Likewise Brian's Fubarino SD looks like a good, tiny size option for these same types of setups (http://fubarino.org). My issues with trying different boards have all been trying to sort out which libraries you need and what works (at the moment) with which board.

Good luck,

--Jon

BlueGene003

unread,
Apr 14, 2013, 3:44:06 PM4/14/13
to accels...@googlegroups.com
How do I need to define lastInputCheckTime? Could you please post the complete code?

I have already tried the Digilent u32, but there were some issues with the accelstepper. As soon as I use the acceleration, my steppers won´t move.

Sandy Noble

unread,
Apr 14, 2013, 4:09:35 PM4/14/13
to accels...@googlegroups.com
Declare lastInputCheckTime (or whatever you want to call it) as a long global variable, like 

long lastInputCheckTime = millis();


sn

Jon Magill

unread,
Apr 14, 2013, 4:17:36 PM4/14/13
to accels...@googlegroups.com
Did you try some "plain vanilla" code for acceleration, like Brian's four motor test code? Start with something like that, then when you confirm that works, add the rest of your complexity...



/* Four Motor Demo
Super simple four motor demo code by Brian Schmalz
*/


#include <AccelStepper.h>

// Define some steppers and the pins they will use
AccelStepper stepper1(1, 26, 27); 
AccelStepper stepper2(1, 28, 29);
AccelStepper stepper3(1, 30, 31);
AccelStepper stepper4(1, 32, 33);

void setup()
{  
    stepper1.setMaxSpeed(11000.0);
    stepper1.setAcceleration(10000.0);
    stepper1.moveTo(12000);
    
    stepper2.setMaxSpeed(8000.0);
    stepper2.setAcceleration(10000.0);
    stepper2.moveTo(35203);
    
    stepper3.setMaxSpeed(20000.0);
    stepper3.setAcceleration(10000.0);
    stepper3.moveTo(26010); 

    stepper4.setMaxSpeed(6000.0);
    stepper4.setAcceleration(10000.0);
    stepper4.moveTo(29010); 
}

void loop()
{
    // Change direction at the limits
    if (stepper1.distanceToGo() == 0)
   stepper1.moveTo(-stepper1.currentPosition());
    if (stepper2.distanceToGo() == 0)
   stepper2.moveTo(-stepper2.currentPosition());
    if (stepper3.distanceToGo() == 0)
   stepper3.moveTo(-stepper3.currentPosition());
    if (stepper4.distanceToGo() == 0)
   stepper4.moveTo(-stepper4.currentPosition());
    stepper1.run();
    stepper2.run();
    stepper3.run();
    stepper4.run();
}

Mike McCauley

unread,
Apr 14, 2013, 4:25:05 PM4/14/13
to accels...@googlegroups.com, BlueGene003
My experience with 2 line LCDs is that they are very slow:

Operation Time (ms)
clear 3.1
cursorTo(1,0) 3.1
printIn(16 chars) 34.1
cursorTo(2,0) 87.1
update 2 lines
of 16 chars each 157.5
--
Mike McCauley mi...@open.com.au
Open System Consultants Pty. Ltd
9 Bulbul Place Currumbin Waters QLD 4223 Australia http://www.open.com.au
Phone +61 7 5598-7474 Fax +61 7 5598-7070

Radiator: the most portable, flexible and configurable RADIUS server
anywhere. SQL, proxy, DBM, files, LDAP, NIS+, password, NT, Emerald,
Platypus, Freeside, TACACS+, PAM, external, Active Directory, EAP, TLS,
TTLS, PEAP, TNC, WiMAX, RSA, Vasco, Yubikey, MOTP, HOTP, TOTP,
DIAMETER etc. Full source on Unix, Windows, MacOSX, Solaris, VMS, NetWare etc.

Jon Magill

unread,
Apr 14, 2013, 4:35:32 PM4/14/13
to accels...@googlegroups.com, BlueGene003
Agreed. I have re-written most of my code so that interactions with the LCD are primarily for setup and entering parameters, etc. Then once I go into "run" mode, I am not updating the LCD. In one of my projects, just an occasional update in a sort of "DRO" mode, where I update 4 digits in the middle of the screen every once in a while.

For most stuff, I have learned that when the motors are running it's best if that is the only thing happening until they're done. That approach makes things much more predictable performance-wise.

My applications are all very forgiving though, as I am not doing anything at the speed limits of the steppers or the library.

--Jon

BlueGene003

unread,
Apr 15, 2013, 1:11:58 PM4/15/13
to accels...@googlegroups.com
Without LCD and read analog, everything works fine.

I will try to use the last solution, avoding to update the LCD while the steppers are running. 

Originally, my plan was to display the current position of both steppers on the LCD. The control is for a pan/tilt-head for video recording, so every interrupt of the steppers would be visible on the video.

Jon Magill

unread,
Apr 15, 2013, 1:59:33 PM4/15/13
to accels...@googlegroups.com
I don't have any great code examples to share, but you can see Brian's technique I was describing for the pot checking, and a lot of detail on a photo skate dolly, which probably overlaps with what you're trying to do here: http://www.schweinert.com/blog/files/tag-control.html

Look for the link to download the sketch that Brian wrote for the skate dolly project. I think you'll see/learn some useful techniques to apply to your project.

Hope that helps.

--Jon
Reply all
Reply to author
Forward
0 new messages