preprocessor way to define multiple functions

Dear friends

I'm trying to work with "AccelStepper" library to control 50 uni-polar step-motors using this library.
I'm using Arduino DUE for sufficient computing capability but because of lack of pins I use shift registers (74hc595) to control step motors.
The library itself can work with custom "backward function" and "forward function" so I managed to update an array for state of each coils of each stepper and custom function to change the coil state.
Currently everything works fine, however I should define 2 different "backward" and "forward" function for each stepper (so 100 function definition!!!).

I'm wondering if there is some way to define these function using preprocessor!

My working example is something like this (only for 4 steppers! for more steppers I need more dummy lines!):

void f_stepper0Forward() { sharedForwardAndBackward(0, 1); }
void f_stepper0Backward() { sharedForwardAndBackward(0, 0); }
void f_stepper1Forward() { sharedForwardAndBackward(1, 1); }
void f_stepper1Backward() { sharedForwardAndBackward(1, 0); }
void f_stepper2Forward() { sharedForwardAndBackward(2, 1); }
void f_stepper2Backward() { sharedForwardAndBackward(2, 0); }
void f_stepper3Forward() { sharedForwardAndBackward(3, 1); }
void f_stepper3Backward() { sharedForwardAndBackward(3, 0); }

void sharedForwardAndBackward(uint8_t motorNumber, bool goForward)
{
	registersUpdated = 1;
	uint8_t nextCoilState;
	if (motorNumber % 2 == 0)
	{
		goForward = !goForward;
	}
	if (goForward)
	{
		nextCoilState = (lastCoilState[motorNumber] + 1) % 8;
	}
	else
	{
		nextCoilState = (lastCoilState[motorNumber] + 7) % 8;
	}
	lastCoilState[motorNumber] = nextCoilState;

	registerPins[4 * motorNumber + 0] = (nextCoilState == 7) || (nextCoilState == 0) || (nextCoilState == 1);
	registerPins[4 * motorNumber + 1] = (nextCoilState == 1) || (nextCoilState == 2) || (nextCoilState == 3);
	registerPins[4 * motorNumber + 2] = (nextCoilState == 3) || (nextCoilState == 4) || (nextCoilState == 5);
	registerPins[4 * motorNumber + 3] = (nextCoilState == 5) || (nextCoilState == 6) || (nextCoilState == 7);
}

AccelStepper st0(f_stepper0Forward, f_stepper0Backward);
AccelStepper st1(f_stepper1Forward, f_stepper1Backward);
AccelStepper st2(f_stepper2Forward, f_stepper2Backward);
AccelStepper st3(f_stepper3Forward, f_stepper3Backward);

AccelStepper* steppers[NUMBER_OF_STEPPERS] = {
	&st0,
	&st1,
	&st2,
	&st3,
};

So I'm looking for something like this:

#define NUMBER_OF_MOTORS 50

#for ii = 0:NUMBER_OF_MOTORS 
#void f_stepper(ii)Forward() { sharedForwardAndBackward(ii, 1); }
#void f_stepper(ii)Backward() { sharedForwardAndBackward(ii, 0); }

Excuse me for poor English, It's not my native language!

you can't write a macro to generate the macros. i've used awk to generate code such as that

but do you really want 50 unique macros? isn't having a function with an argument for the motor desirable? I can see separate forward() and backward()

#include <stdio.h>

void
sharedForwardAndBackward (
    int     motor,
    int     dir )
{
    printf ("%s: mot %d, dir %d\n", __func__, motor, dir);
}

inline void forward  (int motor) { sharedForwardAndBackward (motor, 0); }
inline void backward (int motor) { sharedForwardAndBackward (motor, 1); }

int
main ()
{
    forward (0);
    backward (9);

    return 0;
}

Dear gcjr

Thanks for your reply. I know that I can use arguments for my function, but the accelStepper object only accept function pointers without arguments!
My "sharedForwardAndBackward" function needs to know which motor calls it! So I defined different function for each motor!

Do you understand me?

alitava:
accelStepper object only accept function pointers without arguments!

Who/What created those objects?
Where are they stored?
Perhaps put them in an array?

Post a minimal complete example sketch which demonstrates the problem. This trying to pin the tail on the donkey from code snippets is hard work...

AccelStepper is a standard library of Arduino for controlling stepper motors!
I've already put them in array, the problem is the definition of 50 object, not to access them throw array.

If you really need a working code, here you are, but I think it will make other confused!

#include <AccelStepper.h>

#define NUMBER_OF_STEPPERS 4

#define SR_DATA   8  //pin 14 on the 75HC595
#define SR_LATCH 9  //pin 12 on the 75HC595
#define SR_CLOCK 10 //pin 11 on the 75HC595

uint8_t lastCoilState[NUMBER_OF_STEPPERS];
bool registerPins[NUMBER_OF_STEPPERS * 4];
bool registersUpdated;

void f_stepper0Forward() { sharedForwardAndBackward(0, 1); }
void f_stepper0Backward() { sharedForwardAndBackward(0, 0); }
void f_stepper1Forward() { sharedForwardAndBackward(1, 1); }
void f_stepper1Backward() { sharedForwardAndBackward(1, 0); }
void f_stepper2Forward() { sharedForwardAndBackward(2, 1); }
void f_stepper2Backward() { sharedForwardAndBackward(2, 0); }
void f_stepper3Forward() { sharedForwardAndBackward(3, 1); }
void f_stepper3Backward() { sharedForwardAndBackward(3, 0); }

void sharedForwardAndBackward(uint8_t motorNumber, bool goForward)
{
  registersUpdated = 1;
  uint8_t nextCoilState;
  if (motorNumber % 2 == 0)
  {
    goForward = !goForward;
  }
  if (goForward)
  {
    nextCoilState = (lastCoilState[motorNumber] + 1) % 8;
  }
  else
  {
    nextCoilState = (lastCoilState[motorNumber] + 7) % 8;
  }
  lastCoilState[motorNumber] = nextCoilState;

  registerPins[4 * motorNumber + 0] = (nextCoilState == 7) || (nextCoilState == 0) || (nextCoilState == 1);
  registerPins[4 * motorNumber + 1] = (nextCoilState == 1) || (nextCoilState == 2) || (nextCoilState == 3);
  registerPins[4 * motorNumber + 2] = (nextCoilState == 3) || (nextCoilState == 4) || (nextCoilState == 5);
  registerPins[4 * motorNumber + 3] = (nextCoilState == 5) || (nextCoilState == 6) || (nextCoilState == 7);
}


void updateRegisters()
{
  uint8_t newByte;
  if (registersUpdated)
  {
    digitalWrite(SR_LATCH, LOW);
    for (int8_t m = (NUMBER_OF_STEPPERS / 2) - 1; m >= 0; m--)//m is module number
    {
      newByte = 0;
      for (uint8_t b = 0; b < 8; b++) {
        if (registerPins[8 * m + b]) {
          newByte |= (1 << b);
        }
      }
      shiftOut(SR_DATA, SR_CLOCK, MSBFIRST, newByte);
    }
    digitalWrite(SR_LATCH, HIGH);
    registersUpdated = 0;
  }
}

AccelStepper st0(f_stepper0Forward, f_stepper0Backward);
AccelStepper st1(f_stepper1Forward, f_stepper1Backward);
AccelStepper st2(f_stepper2Forward, f_stepper2Backward);
AccelStepper st3(f_stepper3Forward, f_stepper3Backward);

AccelStepper* steppers[NUMBER_OF_STEPPERS] = {
  &st0,
  &st1,
  &st2,
  &st3,
};

void setup() {
  // put your setup code here, to run once:
  pinMode(SR_CLOCK, OUTPUT);
  pinMode(SR_DATA, OUTPUT);
  pinMode(SR_LATCH, OUTPUT);
  steppers[0]->moveTo(2000);
  steppers[1]->moveTo(2000);
  steppers[2]->moveTo(-2000);
  steppers[3]->moveTo(-2000);
}

void loop() {
  // put your main code here, to run repeatedly:

}

I think something like "Pasting Tokens" or "String-izing Tokens" in macro should works!

alitava:
AccelStepper is a standard library of Arduino for controlling stepper motors!

Maybe the solution is to write your own functions to control the stepper motors rather than using the AccelStepper library?

...R

You're using the AccelStepper's alternate constructor which accepts function pointers as callbacks. Instead try to subclass AccelStepper and define the protected virtual functions. Step0, Step1, ... Step8. This way you can define one class for all your motors, then specify exactly which motor you want to control when you instance your Subclass.

bnetbutter:
You're using the AccelStepper's alternate constructor which accepts function pointers as callbacks. Instead try to subclass AccelStepper and define the protected virtual functions. Step0, Step1, ... Step8. This way you can define one class for all your motors, then specify exactly which motor you want to control when you instance your Subclass.

+1
Definitely the way to go. Way to think OOP.

Maybe this will help. At least it only requires one line per stepper and produces the expected output.

#include <AccelStepper.h>


// This macro expands into two Lambda expressions, basically functions with no name.
#define StepFunctions(n) [](){sharedForwardAndBackward(n, true);},  [](){sharedForwardAndBackward(n, false);}


#define NUMBER_OF_STEPPERS 5


// Prototype must be seen before macro is expanded
void sharedForwardAndBackward(uint8_t motorNumber, bool goForward);


AccelStepper Steppers[NUMBER_OF_STEPPERS] =
{
  AccelStepper(StepFunctions(0)),
  AccelStepper(StepFunctions(1)),
  AccelStepper(StepFunctions(2)),
  AccelStepper(StepFunctions(3)),
  AccelStepper(StepFunctions(4))
};


void sharedForwardAndBackward(uint8_t motorNumber, bool goForward)
{
  Serial.print("Motor: ");
  Serial.print(motorNumber);
  Serial.print("  Direction: ");
  Serial.println(goForward ? "Forward" : "Backward");
}


void setup()
{
  Serial.begin(115200);
}


void loop()
{
  for (int i = 0; i < NUMBER_OF_STEPPERS; i++)
  {
    Steppers[i].runToNewPosition(1);
    Steppers[i].runToNewPosition(0);
  }
}

johnwasser:
Maybe this will help. At least it only requires one line per stepper and produces the expected output.

#include <AccelStepper.h>

// This macro expands into two Lambda expressions, basically functions with no name.
#define StepFunctions(n) {sharedForwardAndBackward(n, true);},  {sharedForwardAndBackward(n, false);}

#define NUMBER_OF_STEPPERS 5

// Prototype must be seen before macro is expanded
void sharedForwardAndBackward(uint8_t motorNumber, bool goForward);

}

Thanks a lot. At least it makes code half size!

bnetbutter:
You're using the AccelStepper's alternate constructor which accepts function pointers as callbacks. Instead try to subclass AccelStepper and define the protected virtual functions. Step0, Step1, ... Step8. This way you can define one class for all your motors, then specify exactly which motor you want to control when you instance your Subclass.

It's sounds great, but I've no idea how to do that! I was planned to duplicate main file and edit it directly but I don't know how to subclass "AccelStepper" library!

I think this is how you would subclass the AccelStepper class to create your own setOutputPins() function that updates your 'registerPins' array instead of setting output pins.

#include <AccelStepper.h>

class SRStepper : public AccelStepper
{
  public:
    SRStepper(byte mn) : AccelStepper(FULL4WIRE)
    {
      motorNumber = mn;
    };

    // You might want to override this to implement eg serial output
    // bit 0 of the mask corresponds to _pin[0]
    // bit 1 of the mask corresponds to _pin[1]
    // ....
    void setOutputPins(uint8_t mask)
    {
      const uint8_t numpins = 4;
      registersUpdated = true;

      for (uint8_t i = 0; i < numpins; i++)
      {
        registerPins[numpins * motorNumber + i] = !!(mask & (1 << i));
      }
    }

  private:
    byte motorNumber;
    byte registerPins[200];
    boolean registersUpdated;
};

void setup() {}
void loop() {}

Thank you Johnwasser, I got your general idea but I didn't understand your code, maybe because I'm not so familiar with process of "subclass"ing!

I try to read more about this and implement the code using this manner.
Thank you and thanks to every one else how shared their idea.

alitava:
Thank you Johnwasser, I got your general idea but I didn't understand your code, maybe because I'm not so familiar with process of "subclass"ing!

It's called "inheritance".

alitava:
Thank you Johnwasser, I got your general idea but I didn't understand your code, maybe because I'm not so familiar with process of "subclass"ing!

I try to read more about this and implement the code using this manner.
Thank you and thanks to every one else how shared their idea.

class SRStepper : public AccelStepper

This means "the new class SRStepper (Shift Register Stepper) is a kind of 'AccelStepper'". It will do anything an AccelStepper will do but will do some things differently.
AccelStepper has a method declared "virtual void setOutputPins(uint8_t mask);". The 'virtual' keyword says "if a derived class (like SRStepper) defines this function then that one will be called instead of this one.

johnwasser:

class SRStepper : public AccelStepper

This means "the new class SRStepper (Shift Register Stepper) is a kind of 'AccelStepper'". It will do anything an AccelStepper will do but will do some things differently.
AccelStepper has a method declared "virtual void setOutputPins(uint8_t mask);". The 'virtual' keyword says "if a derived class (like SRStepper) defines this function then that one will be called instead of this one.

Thanks a lot. I'm currently working on my project using your single line macro. As soon as I complete this project I will try for creating child class. I'm some how familiar with "parent-child" inheritance but I didn't have enough experiment and courage to start it, but I will do soon.

Thanks every one here.