help needed: functions!

I need to control a motorized slide that goes back and forth along a track, inverting direction by switching HIGH or LOW (operated by the slide itself) the switches that are at each end of the track. Since between each travel (left to right and right to left) some other things happen on others outputs, I thougt to manage the sketch by function. I did 2 opposite functions like this:

void leftoright()
{
SWsxSTAT=digitalRead(SWsx); // checks the switch state at the right end
digitalWrite(TrackDir,LOW); // set left-to-right direction of motor
analogWrite(MotorSpeed,200); // gives power to motor
while (FCsxSTAT==0)
{
analogWrite(TrackSpeed,0); // off motor
}}

... and a rightoleft function, whit obviously opposite parameters.

now, it's quite difficult to me to put together these simple functions in the void loop: I thought that something like this was enough, but it doesn't work...

void loop()
{
leftoright();

//.... do other tasks, delay, ecc.///

rightoleft();
}

Where I'm wrong?

Hello there.

This is a simple option, assuming that your system can always start up with the carriage going left to right.

void setup(void)
{
  // initialise the motor speed and direction, motor going right
}

void loop(void)
{
  static bool goingRight = true;

  if (goingRight)
  {
    // check rightmost endstop and if hit, reverse motor.
    {
      //  ....
    }
    goingRight = false;
  }
  else
  {
    // check leftmost endstop and if hit, reverse motor.
    {
      //  ....
    }
    goingRight = true;
  }
}

This relies on the 'static' modifier for the direction variable. It just means that the variable keeps its value in between calls. You could also make it global. Just put your end-point handling code in the appropriate places.


You could also step up a level and do something like the following. This is a state machine. Very simply you break your problem down into blocks (or 'states') that describe where the system is at any one time and write code to describe these that runs each time the main loop is called.

Your problem would break down to these states: Moving right, Moving left. Easy. You could get fancier and add transitional states (hit right end stop, e-stop pressed) but let's start simple.

Here's the code. Sorry if it's not immediately understandable, but keep plugging at it and it should become clear. I'll be happy to explain further if you want. Apologies if there's any compiler errors, I haven't got access to an IDE right now. I'll fix any I find once I get a chance to test.

// this could have been done with classes but function pointers are neat and .. well I'm in that kind of mood :)
//
// this tells the compiler that we want to define a new type (like int, char, etc) the type is 'stateFunc' and it's a
// pointer to a function that returns an int and takes no parameters.
//
typedef int (*stateFunc)(void);

// here we have an array of pointers to functions.
//
stateFunc states[2];

// this is a shorthand way of assigning increasing values to labels.
//
enum
{
  LEFT_TO_RIGHT,   // will equal 0
  RIGHT_TO_LEFT    // will equal 1
};

// this doesn't need to be global, just doing this differently from 1st example.
//
int currentState;

void setup(void)
{
  // put the addresses of the functions that service each state into the array.
  //
  states[LEFT_TO_RIGHT] = leftToRight;
  states[RIGHT_TO_LEFT] = rightToLeft;

  // set up initial conditions
  //
  currentState = LEFT_TO_RIGHT;
  digitalWrite(TrackDir,LOW); // set left-to-right direction of motor
  analogWrite(MotorSpeed,200); // gives power to motor 
}

void loop(void)
{
  // this is (one way) to call a function indirectly via a pointer
  //
  stateFunc theFunction = states[currentState];
  currentState = (*theFunction)();
}

int leftToRight(void)
{
  // in this state we hang out until we hit the right-hand limitswitch
  //
  if(digitalRead(RIGHT_LIMIT))
  {
    // reverse the motor and start executing the other state
    //
    digitalWrite(TrackDir,LOW); // set left-to-right direction of motor
    return RIGHT_TO_LEFT;
  }

  return LEFT_TO_RIGHT;
}

int rightToLeft(void)
{
  // in this state we hang out until we hit the left-hand limitswitch
  //
  if(digitalRead(RIGHT_LIMIT))
  {
    // reverse the motor and ... you get the picture
    //
    digitalWrite(TrackDir,HIGH); // set right-to-left direction of motor
    return LEFT_TO_RIGHT;
  }

  return RIGHT_TO_LEFT;
}

I appreciate that this second example is a lot more difficult to understand, but it's a good way to add complexity to your program without making a messy inner loop. Now that the handling of the states are passed off to functions you can go ahead and expsnd as much as you like.

Have fun with it, and don't be afraid to ask if you want to know more.

Charlie

sirmorris,
many thanks for suggestions and code... I've learn a couple of new things...
Il'do some tests and report.

Super 16

No problem.

I'mn happy to help anytime.