Creating an stepper object within a class

Hi all,

I am creating a haptic glove that uses stepper motors in conjunction with other sensors. The way I am keeping everything sorted is to use a class to create objects for each finger eg.
Finger thumb(); and functions like index.getAngle();

I want this class to be able to have an AccelStepper stepper object within it (as there is a stepper motor per finger). This is what I was thinking of doing to achieve this:

#include <AccelStepper.h>

#define MAX_SPEED 500

// Class for each finger
class Finger {  
   private:
     // Pins setup
     int stepPin;
     int dirPin;

   public:
    // Constructor for each finger object
     Finger(int stepPin, int dirPin) : stepper(AccelStepper::DRIVER, stepPin, dirPin) {
         this->stepper = stepper;
         stepper.setMaxSpeed(MAX_SPEED);
     }

     AccelStepper stepper;
};

Finger Thumb(2, 3);

void loop(){
   //Example of how I want to use the stepper finger class
   Thumb.stepper.moveTo(90);
}

I don't do too much in C++ so any help would be greatly apreciated.

Thanks.

Yes, the idea is good. There are a number of ways, but since every part has exactly one stepper motor, you can put the object in the class.

A nicer way could be: 'class Finger : AccelStepper'
That way the 'AccelStepper' class is used, with your 'Finger' class as an extra. I think that 'Thumb.moveTo(90)' is nicer.

I took a look at the AccelStepper library, and it is a good, versatile and compatible class. So you can use it in every way without problems.

To distinguish the variables that are a member, they often get a underscore.

private:
  int _stepPin;
  int _dirPin;
public:
  AccelStepper _stepper;

Then you also don't need "this->" anymore.
I don't know if you need the _stepPin and _dirPin, maybe it is enough if they are in the _stepper.

1 Like

Thank you heaps, this is super useful.

How would you write class Finger : AccelStepper in the context of writing it for a class?

So every finger only has one stepper? Then this should work. Compiles without error.

#include <AccelStepper.h>

#define MAX_SPEED 500

// Class for each finger
class Finger : public AccelStepper
{
  private:


  public:
    // Constructor for each finger object
    Finger(int stepPin, int dirPin) : AccelStepper(DRIVER, stepPin, dirPin)
    {
      setMaxSpeed(MAX_SPEED);
    }
};

Finger Thumb(2, 3);

void setup() {}

void loop()
{
  //Example of how I want to use the stepper finger class
  Thumb.moveTo(90);
}
1 Like

Is the finger a stepper (Inheritance)
or
Has the finger a stepper (composition)

The finger might have even more steppers one day, a touch sensor, a temperature sensor, a bending sensor...
So I believe the stepper is just one part of the finger.

I would keep the composition.

#include <AccelStepper.h>

#define MAX_SPEED 500

// Class for each finger
class Finger {
  protected:
    // Pins setup
    const int stepPin;  // do you really need them? at least make them const
    const int dirPin;

  public:
    // Constructor for each finger object
    Finger(int stepPin, int dirPin) :
      stepPin{stepPin},
      dirPin{dirPin},
      stepper(stepPin, dirPin)
    {
      stepper.setMaxSpeed(MAX_SPEED);  // are you sure this is a good idea in the constructor?
    }
    AccelStepper stepper;
};

Finger Thumb(2, 3);

void setup() {
}

void loop() {
  //Example of how I want to use the stepper finger class
  Thumb.stepper.moveTo(90);
}
1 Like

The finger has a stepper, it also has three other sensors connected to it. So composition.
I notice in the code you have protected: what is the purpose of this?

I gather that keeping the composition would mean that I can still have Thumb.stepper.moveTo(90); which would be ideal as like you said it is more futureproof.

However in your code, the constructor for the stepper doesn't have it being set as DRIVER? Is this not required? From what I gather AccelStepper does not default to DRIVER mode?

Finally, in terms of stepPin and dirPin I don't need them if there is a better way around? They are just used for setting up the stepper object.

:wink:

default for class is private. But I find protected more comfortable if I ever have to inherit from that class. If you don't like it - use private (or leave it).

reading hint: https://stackoverflow.com/questions/860339/difference-between-private-public-and-protected-inheritance

sorry, my fault. I didn't know how you want to use it. if you need the DRIVER, add it.

then leave them away (also in the initializer list).

Thank you for you solution, I tried it and it worked (been a long while since I have seen this code compile successfully).

To answer your question, yes every finger has one stepper (as well as three other sensors which are handled by other classes I made (I did not include that code here as I saw it irrelevant)).

I was just wondering if in this code, if I wanted to run an AccelStepper function within the class (for example creating Finger.testFunction() would I need to prefix the AccelStepper fuction with anything or just do what is shown in the constructor setMaxSpeed(MAX_SPEED) eg.

class Finger : public AccelStepper
{
  public:
    Finger(int stepPin, int dirPin) : AccelStepper(DRIVER, stepPin, dirPin)
    {
      setMaxSpeed(MAX_SPEED);
    }

   //No prefix
   void testFunction(){
      moveTo(90);
   }
   //Somesort of prefix?
   void testFunction(){
      stepper.moveTo(90);
   }

};

You guessed it. :grinning:

default for class is private. But I find protected more comfortable if I ever have to inherit from that class. If you don't like it - use private (or leave it).

reading hint: https://stackoverflow.com/questions/860339/difference-between-private-public-and-protected-inheritance

Thanks, I will be sure to check that out.

sorry, my fault. I didn't know how you want to use it. if you need the DRIVER, add it.

No problem, do you think I would add it in like I did originally:
stepper(AccelStepper::DRIVER, stepPin, dirPin)

or something more like how @johnnwasser suggested:
stepper(DRIVER, setPin, dirPin)

then leave them away (also in the initializer list).

Perfect, thanks. If it ain't broke don't fix it.

it needs the namespace.

compiles, but untested:

#include <AccelStepper.h>

#define MAX_SPEED 500

// Class for each finger
class Finger {
  public:
    // Constructor for each finger object
    Finger(int stepPin, int dirPin) :
      stepper(AccelStepper::DRIVER, stepPin, dirPin)
    {
      stepper.setMaxSpeed(MAX_SPEED);  // are you sure this is a good idea in the constructor?
    }
    AccelStepper stepper;
};

Finger Thumb(2, 3);

void setup() {
}

void loop() {
  //Example of how I want to use the stepper finger class
  Thumb.stepper.moveTo(90);
}

Because the Finger class inherits the behaviors of the AccelStepper class, it can use all of the AccelStepper methods directly, like I did with setMaxSpeed() in the constructor.