Big performance issue when calling global class object within other class

I'm using AccelStepper for driving a stepper motor. For a slider I created a Slider class in which I call AccelStepper function's. This results in a big performance issue. When I call the stepper functions outside the class it works perfect but when I use the same calls within the class functions I have an unworkable situation.
I stripped and commented the code to make clear what the situation is (I hope...) Someone any idea what's going on? any help is much appreciated. I'm struggling with this for a while now.

Thnx, Fred


// in SldrWagon class (object slider) I call the global stepper object below to let the Accel stepper do it's job (SLDR_wagon.h / SLDR_wagon.cpp)

SldrWagon slider;

// stepper is defined in SLDR_wagon.cpp as global var => AccelStepper stepper( 1, STEPPER_STEP_PIN, STEPPER_DIR_PIN);

extern AccelStepper stepper;

void setup()
{
Serial.begin( 9600 );
Serial.println( "start");
}

/// ------- How I want to get it work with a good performance
/// ----------------- BAD PERFORMANCE, STEPPER HARDLY MOVES -----------------
/// all AccelStepper 'stepper' object functions are called from within the the 'slider' class object

void loop() {
if (! slider.isMoving() ) {
abuttn= keypad.ReadKeypad();
switch ( abuttn ) {
case btnRIGHT :
slider.go( 1000000.0 , 1500.0 , POSITION_LIMIT-1500,BACKWARD); // slider called
slider.isMoving( true );
break;
}
}
slider.run(); // slider called
}

//////////////////////////// WHAT I'VE ALREADY TRIED //////////////////////////
/// ----------------- BAD PERFORMANCE, STEPPER HARDLY MOVES -----------------
/// 'slider' class object is used for setting the global 'stepper' object parameters Speed, Acceleration and MoveTo
/// in loop() stepper.run() is directly called without using the slider class object to do this

void loop() {
if (! slider.isMoving() ) {
abuttn= keypad.ReadKeypad();
switch ( abuttn ) {
case btnRIGHT :
slider.go( 1000000.0 , 1500.0 , POSITION_LIMIT-1500,BACKWARD); // slider called
slider.isMoving( true );
break;
}
}
stepper.run(); // stepper called
}

/// ----------------- SAME BAD PERFORMANCE, STEPPER HARDLY MOVES -----------------
/// the object parameters Speed, Acceleration and MoveTo are directly set by calling the stepper object
/// in the loop the global stepper.run() function is called within the slider class object

void loop() {
if (! slider.isMoving() ) {
abuttn= keypad.ReadKeypad();
switch ( abuttn ) {
case btnRIGHT :
stepper.setAcceleration( 1500.0 ); // stepper called
stepper.setSpeed( 1000000.0 ); // stepper called
stepper.moveTo( -POSITION_LIMIT ); // stepper called
slider.isMoving( true );
break;
}
}
slider.run(); // slider called
}

/// ----------------- GOOD PERFORMANCE !!!! -----------------
/// 'slider' class object not used for AccelStepper functions but only global 'stepper' object
void loop() {
if (! slider.isMoving() ) {
abuttn= keypad.ReadKeypad();
switch ( abuttn ) {
case btnRIGHT :
stepper.setAcceleration( 1500.0 ); // stepper called
stepper.setSpeed( 1000000.0 ); // stepper called
stepper.moveTo( -POSITION_LIMIT ); // stepper called
slider.isMoving( true );
break;
}
}
stepper.run();
}

//////////////////////////////////// SLDR_wagon.cpp //////////////////////////////////////////
// ------------- the called stripped functions in the slider SLDR_wagon.cpp file ------------

void SldrWagon::go( const float speed, const float accel, const float pos, const unsigned char dir ) {
_direction= dir;
_currSpeed= dir ? speed : - speed;
_currAcceleration= accel;
_isMoving= true;

stepper.setAcceleration( accel );
stepper.moveTo( pos );
stepper.setSpeed( speed );
return;
}

void SldrWagon::run( void ) {
stepper.run();
return;
};

/// ----- then tried this one to see if calling the slider object is the bad guy
/// no difference in performance though!!!!
void SldrWagon::run( void ) {
unsigned int i;
for( i=10000; i; i-- ) { stepper.run(); }
return;
};

I don't see any classes in your post. Please post all your code.

http://snippets-r-us.com/

ok, Nick thanks for your reaction.

I stripped everything irrelevant coding from the original files and brought these down to make clear what it is all about. I checked this set and I have exact the same problem here.

hereby you will find the files

I defined 2 preproc variables to simulate all variations.

#define USE_SLIDER_SETTINGS
#define USE_SLIDER_RUN

As soon one of these (or both) is defined the stepper steps veeerrrrry slow. without them it works perfectly. To give an impression: once the SldrWagon class is involed it takes ca. 1 minute to move the wagon about 1inch. without that it takes less than 2secs.

(sorry for my probably somewhat poor english..)

Fred

slider.ino (695 Bytes)

SLDR_wagon.h (1.72 KB)

SLDR_wagon.cpp (2.39 KB)

When the constructor is called, the hardware is not ready, so calling initSldrWagon() from SldrWagon::SldrWagon seems inappropriate.

Defining the AccelStepper instance in SldrWagon.cpp as a global seems pointless. Define it in the sketch, and declare it extern in the SldrWagon source or header file (or, better yet), pass a pointer to the instance to the constructor).

Some Serial.print() statements on the class methods would not be amiss, either.

woooowww!!!!!

Paul I did a quick test by following your advise and now it seems to work as planned.

"Define it in the sketch, and declare it extern in the SldrWagon source or header file"

Wouldn't have discovered this myself..

Thanks a lot. Already happy!

(or, better yet), pass a pointer to the instance to the constructor).

hm, it's getting harder now.. :wink:

Don't know how exactly to do this. This is what i did. Seems to compile ok but now it runs like the bad performance variant again

this is what I've changed:
in the sketch:

SldrWagon slider( &stepper);

in the SldrWagon header file:

public:
SldrWagon( AccelStepper* );

private:
AccelStepper * stepper;

SldrWagon cpp

SldrWagon::SldrWagon( AccelStepper * stepper_p ) {
stepper= stepper_p;
stepper->setCurrentPosition( 0.0 );
stepper->setAcceleration( _currAcceleration );
stepper->setMaxSpeed( ACCELL_MAX_SPEED );
stepper->setSpeed( _currSpeed );

_initSldrWagon();
return;
}

and changed stepper. to stepper-> in all other SldrWagon class functions

It's probably not what you ment...

It's probably not what you ment...

It's exactly what I meant. But, I don't have your Arduino or your stepper or your power supply. It would be a lot easier for you to add some Serial.print() statements to the code than for me to acquire and set up your configuration.

In your initial post, I don't see any difference between the 3rd block of code, that you say provides poor performance and the 4th block, which you say provides good performance.

I haven't looked at your code as I have confidence in PaulS's ability to spot problems. However you may be suffering from the C++ static initialization order fiasco.

What it is: What's the "static initialization order fiasco"?, C++ FAQ

How to prevent it: How do I prevent the "static initialization order fiasco"?, C++ FAQ

@paul
thanks Paul

I have a problem using Serial.println in combi with the AccelStepper. AccelStepper is using time when doing it's accelerating/decelerating calculation thing. The Serial.print stuff is disturbing it's timing pretty much during stepping and prevents extracting realistic realtime stepping values. (it's holding the stepper from accelerating)

But what I did is setting the parameters (slider.acceleration(), slider.setSpeed(), slider.moveTo() ) and next used Serial.print in both AccelStepper.cpp (listing the final private fields in the AccelStepper class object holding the content for 'internal use') and my DslrWagon.cpp (using the public functions) to check the resulting content. They all showed correct and same values as intended!

So it really looks like you are right something is going wrong in setting up the constructor/creating the instance.

In the 3rd block the big difference is: In all functions I'm accessing the stepper instance directly instead of involving the slider object as I did in the other blocks.

stepper.setAcceleration( 1500.0 ); // stepper called
stepper.setSpeed( 1000000.0 ); // stepper called
stepper.moveTo( -POSITION_LIMIT ); // stepper called
stepper.run(); // stepper called

The 'funny' thing is that when setting the AccelStepper variables (accel/speed/position) are set the content is correct after checking this with Serial.print

It just feels like stepper.run() is just using another (not existing) instance....

@Nick
Also thanks to you Nick
I will certainly look into this because, as you can extract from my reply to Paul, I also have the feeling it has to be something like that. I'm pretty much unexperienced in all this though, so it's a bit hard for me to keep going when I bump in this type of problems.. :wink: