For loops in subroutines/functions

Hi,

I’m trying to make use of subroutines/functions in my code so i can call functions to the main loop but i’m having difficulty getting my functions to loop with for loops. My code is getting a bit lengthy so hopefully these relevant sections will be enough, if more context is required then tell me.

An example of my functions…

void test1() {                           //Aiming to move the arm from home position into position 1 
  int i;
  for (i=0; i<3840; i++)      //Initialize the expression, test that the expression is less than the highest tick count in the loop, increment expression each time we loop
  {                              
    long ticknumber = 2040;                //set the number of ticks i want the motor to move in this operation. 1,2,3 etc. are for motors 1,2,3 etc.
    long tickNumber2 = 2560;
    long tickNumber3 = 3840;
    long tickNumber4 = 510;

    if ((count) < (tickNumber))
    {
      moveMotor(FORWARD, 204, 1);           //direction, PWM speed, 10 tick
    }
    if ((count2) < (tickNumber2))           // do i need an else telling it to do nothing and move on or will it do that automatically?
    {
      moveMotor2(FORWARD, 204, 1);
    }
    if ((count3) < (tickNumber3))
    {
      moveMotor3(BACKWARD, 204, 1);
    }
    if ((count4) < (tickNumber4))
    {
      moveMotor4(FORWARD, 204, 1);
    }
  }
}
//************************************************

void resetCounts() {

  countInit = 0;          //reset all counters in preparation for next routine
  count = 0;
  countInit2 = 0;
  count2 = 0;
  countInit3 = 0;
  count3 = 0;
  countInit4 = 0;
  count4 = 0;

//*************************************************


void test2() {                              //return to home position from last move

  int j;
  for (j=0; j<3840; j++)
  {

    long ticknumber = 2040;
    long tickNumber2 = 2560;
    long tickNumber3 = 3840;
    long tickNumber4 = 510;

    if ((count) < (tickNumber))
    {
      moveMotor(BACKWARD, 255, 1);
    }
    if ((count2) < (tickNumber2))
    {
      moveMotor2(BACKWARD, 255, 1);
    }
    if ((count3) < (tickNumber3))
    {
      moveMotor3(FORWARD, 255, 1);
    }
    if ((count4) < (tickNumber4))
    {
      moveMotor4(BACKWARD, 255, 1);
    }
  }
}

And how I am calling these…

void loop() {


  //************************************* Motor 1,2,3&4 Mixed Operations **************************************

  test1();         // calls test 1 subroutine

  resetCounts();

  test2();         // calls test 2 subroutine

  resetCounts();

 
  while (1) {}
}

What I want to happen is for test1() to be completed by the motors spinning until they have reached their required number of spins (set as “tickNumber”, counted as “count” through interrupts from motor encoders) then for all counters to be wiped by resetCounts() then for test2() to run, bringing all of the motors back to their home position.

What actually happens is the motors jerk back and forth making a fraction of a rotation each time, they are moving a fraction as far as they should be moving which makes me think my for loops are not working?

I know my system is correctly wired etc. because i have had it all moving correctly without calling functions.

Something is missing here. You set count = 0 by calling resetCounts() and then you call test2() which keeps comparing count and ticknumber, whereby ticknumber is reset to 2040 each time through the Loop.

Where are count and tickNumber ever getting changed while test2 is being executed?

What does for example moveMotor() look like?

"count" is what i use to track how far the motor has moved; every time the encoder sends a signal the interrupt code runs which adds 1 to the count, so count is being changed in the ISR.

void rencoder3()  {
  if (PD2 == LOW)   {
    count3++;
  }
  else                   {
    count3--;
  }
}

I need to reset the counters to zero after each operations (test1() etc.) so that i count from zero during the next operation (test2() etc.)

tickNumber should never get changed anywhere else, It should be the number of "ticks" that i specify the motors should move, so if i set tickNumber at 2040 i want that motor to move 2040 ticks and then stop. the only other mention of tickNumber outside of these functions is at the beginning of my code where I define my variables as follows...

long tickNumber = 0;
long tickNumber2 = 0;
long tickNumber3 = 0;
long tickNumber4 = 0;

The problem is that it's not moving as many ticks as i want it to before seeming coming out of the for loop and proceeding to the next function in void loop()

long tickNumber = 0;
long tickNumber2 = 0;
long tickNumber3 = 0;
long tickNumber4 = 0;

Do you count that way? Most people count 1, 2, 3, 4...

I would not use FOR or WHILE in any situation where it would take more than a few microseconds to complete.

I would use loop() to do the iterations and use a counter to keep track of things. When the count limit is reached another variable (perhaps countComplete = true;) can be set and will provide the authority for the next part of the program to work.

...R
Planning and Implementing a Program

Hi Robin,

I'm struggling to figure out how to implement that, I have counters for each of the motors to say how many steps they have moved, and when those counters are equal to the variable "tickNumber" the motor should stop, but I don't know how i can use those counters to loop through each subroutine/function until it is complete.

Say I have a variable that becomes true when all 4 motors have finished their movement, how do I use that to leave a function and move on to the next one without FOR or WHILE. All i can think is

While(countComplete = false)
{
test1();
}

How else can it be done to move through a serious of functions (6+) but completing each one before moving on?

Why is Count being incremented within an ISR?
If the Motor is moved with moveMotor(FORWARD, 204, 1); then why not just increment the Counter there? I'm still not seeing something, probably because I can onyl see fragments of the code.

If ticknumber is not being changed any where else, why put long ticknumber = 2040; inside a for loop? The code would be clearer then if you used const long ticknumber = 2040 at the beginning of the function instead.

JaBa, count is being incremented within an ISR because these are not stepper motors, they are brushed DC motors with encoders so I was under the impression that I cant tell them what a step is, I have to read when a step has been done, so i’m telling the motor to move, and it will stop when the ISR has read that its done the step. I hope that makes some sort of sense?

I guess tickNumber doesn’t need to go inside the for loop and wasn’t there for any particular reason, i’ve moved it to the start of the function now, but tickNumber may be different for each function I am calling.

Almost complete code (character limit so chopped some off the end):

#define InA1            11                      // INA motor pin
#define InB1            12                      // INB motor pin 
#define PWM1            13                      // PWM motor pin
#define encodPinA1      21                      // encoder A pin

#define InA2            8
#define InB2            9
#define PWM2            10
#define encodPinA2      20

#define InA3            5
#define InB3            6
#define PWM3            7
#define encodPinA3      19

#define InA4            2
#define InB4            3
#define PWM4            4
#define encodPinA4      18

#define LOOPTIME        100
#define FORWARD         1
#define BACKWARD        2

unsigned long lastMilli = 0;                    // loop timing
unsigned long lastMilliPrint = 0;               // loop timing
volatile long count = 0;                        // rotation counter
volatile long count2 = 0;
volatile long count3 = 0;
volatile long count4 = 0;
long countInit;
long countInit2;
long countInit3;
long countInit4;
long tickNumber = 0;
long tickNumber2 = 0;
long tickNumber3 = 0;
long tickNumber4 = 0;

long tick = 0;             //testing giving it 1 tick as a standard
long tick2 = 0;
long tick3 = 0;
long tick4 = 0;

int magnetPin = 22 ;

boolean run = false;                            // motor moves

void setup() {
  Serial.begin(9600); // baud rate
  Serial.flush();

  
 pinMode(magnetPin, OUTPUT);            // keep the pin high unless told to be low in void loop() this means that the magnets are always on unless told to be off
 digitalWrite(magnetPin, HIGH);         // the reason to keep magnets on is we cant do 2 things at once in loop so this is the only way to have the magnet on and be moving the robot 


  pinMode(InA1, OUTPUT);
  pinMode(InB1, OUTPUT);
  pinMode(PWM1, OUTPUT);
  pinMode(encodPinA1, INPUT);
  digitalWrite(encodPinA1, HIGH);               // turn on pullup resistor
  attachInterrupt(2, rencoder, FALLING);        //interrupt 2 is pin 21 on 2560 mega according to one source, others people say otherwise... but they are wrong

  pinMode(InA2, OUTPUT);
  pinMode(InB2, OUTPUT);
  pinMode(PWM2, OUTPUT);
  pinMode(encodPinA2, INPUT);
  digitalWrite(encodPinA2, HIGH);
  attachInterrupt(3, rencoder2, FALLING);

  pinMode(InA3, OUTPUT);
  pinMode(InB3, OUTPUT);
  pinMode(PWM3, OUTPUT);
  pinMode(encodPinA3, INPUT);
  digitalWrite(encodPinA3, HIGH);
  attachInterrupt(4, rencoder3, FALLING);

  pinMode(InA4, OUTPUT);
  pinMode(InB4, OUTPUT);
  pinMode(PWM4, OUTPUT);
  pinMode(encodPinA4, INPUT);
  digitalWrite(encodPinA4, HIGH);
  attachInterrupt(5, rencoder4, FALLING);
}

void loop() {


  //************************************* Motor 1,2,3&4 Mixed Operations **************************************

  test1();         // calls test 1 subroutine

  resetCounts();

  test2();         // calls test 2 subroutine

  resetCounts();

 
  while (1) {}
}

//*******************************************************Operations*************************************************************************

void resetCounts() {

  countInit = 0;          //reset all counters in preparation for next routine
  count = 0;
  countInit2 = 0;
  count2 = 0;
  countInit3 = 0;
  count3 = 0;
  countInit4 = 0;
  count4 = 0;
}
//************************************************

void test1() {                           //Aiming to move the arm from home position into position 1 
 
    
    
   const long ticknumber = 2040;                
   const long tickNumber2 = 2560;
   const long tickNumber3 = 3840;
   const long tickNumber4 = 510;
    
    while ((count3) < (tickNumber3))
  {                              
  

    if ((count) < (tickNumber))
    {
      moveMotor(FORWARD, 204, 1);           //direction, PWM speed, 10 tick
    }
    if ((count2) < (tickNumber2))           
    {
      moveMotor2(FORWARD, 204, 1);
    }
    if ((count3) < (tickNumber3))
    {
      moveMotor3(BACKWARD, 204, 1);
    }
    if ((count4) < (tickNumber4))
    {
      moveMotor4(FORWARD, 204, 1);
    }
  }
}

//*************************************************


void test2() {                              //return to home position from last move

  
 
  
    const  long ticknumber = 2040;
    const long tickNumber2 = 2560;
    const long tickNumber3 = 3840;
    const long tickNumber4 = 510;
  
  while (((count3) < (tickNumber3)))
  {

  
    if ((count) < (tickNumber))
    {
      moveMotor(BACKWARD, 255, 1);
    }
    if ((count2) < (tickNumber2))
    {
      moveMotor2(BACKWARD, 255, 1);
    }
    if ((count3) < (tickNumber3))
    {
      moveMotor3(FORWARD, 255, 1);
    }
    if ((count4) < (tickNumber4))
    {
      moveMotor4(BACKWARD, 255, 1);
    }
  }
}

//************************************************


//******************************************Motor control stuff***********************************************

void moveMotor(int direction, int PWM_val, long tick)  {
  countInit = count;    // abs(count)
  //  tickNumber = tick;
  if (direction == FORWARD)          motorForward(PWM_val);
  else if (direction == BACKWARD)    motorBackward(PWM_val);
}

void moveMotor2(int direction, int PWM_val, long tick2)  {
  countInit2 = count2;    // abs(count)
  // tickNumber2 = tick2;
  if (direction == FORWARD)          motorForward2(PWM_val);
  else if (direction == BACKWARD)    motorBackward2(PWM_val);
}

void moveMotor3(int direction, int PWM_val, long tick3)  {
  countInit3 = count3;    // abs(count)
  // tickNumber3 = tick3;
  if (direction == FORWARD)          motorForward3(PWM_val);
  else if (direction == BACKWARD)    motorBackward3(PWM_val);
}

void moveMotor4(int direction, int PWM_val, long tick4)  {
  countInit4 = count4;    // abs(count)
  //  tickNumber4 = tick4;
  if (direction == FORWARD)          motorForward4(PWM_val);
  else if (direction == BACKWARD)    motorBackward4(PWM_val);
}


// ******************************************** Encoder counting **************************************************

void rencoder()  {                                  // pulse and direction, direct port reading to save cycles
  if (PD0 == LOW || PD0 == HIGH)   {                 //added the || to make sure i am getting into the ISR, it counts ++ whatever the pin state.
    count++;
  }
  else                   {
    count--;
  }

  if ((count) > tickNumber)   {
    motorBrake();                               //apply the brake when the count of the motor exceeds the tick number (what we ask it to do in void loop() eg 510*1.2
  }
}

void rencoder2()  {
  if (PD1 == HIGH || PD1 == LOW )   {
    count2++;
  }
  else                   {
    count2--;
  }

  if ((count2) > tickNumber2)   {
    motorBrake2();
  }
}

void rencoder3()  {
  if (PD2 == LOW)   {
    count3++;
  }
  else                   {
    count3--;
  }

  if ((abs(count3)) > tickNumber3)   {
    motorBrake3();
  }
}

void rencoder4()  {
  if (PD3 == LOW)   {
    count4++;
  }
  else                   {
    count4--;
  }

  if ((abs(count4)) > tickNumber4)   {
    motorBrake4();
  }
}



// ***********************Code for forward backward and brake  *******************************

//************Motor 1*********************
void motorForward(int PWM_val)  {
  analogWrite(PWM1, PWM_val);
  digitalWrite(InA1, LOW);
  digitalWrite(InB1, HIGH);
  run = true;
}

void motorBackward(int PWM_val)  {
  analogWrite(PWM1, PWM_val);
  digitalWrite(InA1, HIGH);
  digitalWrite(InB1, LOW);
  run = true;
}

void motorBrake()  {
  analogWrite(PWM1, 0);
  digitalWrite(InA1, HIGH);
  digitalWrite(InB1, HIGH);
  run = false;
}

void motorOff()  {
  analogWrite(PWM1, 0);
  digitalWrite(InA1, LOW);
  digitalWrite(InB1, LOW);
  run = false;
}

Sorry its a mess and there are lines that likely no longer serve any purpose

Why "while (1) {}" at the end of your main loop? You want it to stop and hang forever after one loop? If that is the case, why not just put it to sleep at the end of the loop and save a lot of power?

ty_ger07, the while (1) {} is to stop it after one loop, I just didn't know any other way of making it stop.

I only want to visit each function once, one after the other, but some functions require looping through them before moving on to the next function.

Did you define count as volatile?
I'v learned that any variables which are changed by an ISR shall be defined as volatile:
volatile word count;

This is a simple example how you can make loop do the counting.

void loop()
{
  static int counter=0;

  if(counter < 10)
  {
    Serial.print("counter = "); Serial.println(counter);
    counter++;
  }
}

sterretje, I don't think that's really translatable to my case is it? unless i'm missing something, which is often the case.

I don't want to have to say "do 100 loops of this function" I want a function to repeat until "count" exceeds "tickNumber". Then for count and tickNumber to reset/have their value changed before starting a new function.

Also I have 4 counts and 4 tickNumbers in each function because i have 4 motors which adds complexity because i have to stay in any particular function until the last motor has finished its last move.

You can’t have code like this in loop() if the variable count is incremented by an ISR.

if ((count) < (tickNumber))

because the variable count occupies 4 bytes and one of them could change while loop() is reading the variable.

You need to copy the values into working variables like this

noInterrupts()
workingCount = count;
workingCount1 = count1;
// etc
interrupts();

and then do all your tests on the variables workingCount etc. (Obviously use any variable name you like)

I can see that your ISR will cause the motor to stop when the count is reached. But I am not clear what else you want to happen.

As far as I can see you can restart a movement by changing count to 0 (again with interrupts off) and you can change the number of “steps” just by writing a different number to (say) ticknumber immediately before you set count back to 0.

I can’t understand the need for

while (((count3) < (tickNumber3)))

which won’t work as expected as already explained.

Another approach may be to take all the decision making out of the ISRs and have them provide a simple +1 or -1 which loop() can use to increment a variable. Something like

void rencoder()  { 
  if (PD0 == LOW || PD0 == HIGH)   { 
    count = 1;
  }
  else                   {
    count = -1;
  }
}

In that case count can be a char value so there is no need for noInterrupts(). And when loop() has read the value it could change it to 0 so it would know when a new value is detected.

…R

julyjim, thanks for the reply. I'm unable to use serial monitors while the code runs unfortunately because my computer is on the other side of the building to the robot arm that i'm plugging the arduino into, and i can't move either closer to the other at the moment. I'll try to make my comments a bit more useful. And.. I couldnt copy all of the code into one comment becasue of character restrictions. I know that It all works if i take whats in test 1 and just have that in void loop() with nothing else, and declare the values for tickNumbers at the beginning of the code.

To anyone reading...

Whatever method i implement needs to be scalable because I have 4 motors and will need to have upwards of 6 functions in my loop.

All I want is to loop through functions until the if statements im currently using are no longer true, but without stacking endless if statements I just don't know how to do it?

in words this is what im trying to do:

run test1() until all 4 motors have moved as far as i am specifying in tickNumbers
run test2() until all 4 motors have moved as far as i am specifying in tickNumbers

Robin, I will change my counts to working variables, I already had the framework for this in place with the variable name "countInit" from the person i copied the base of this code from, I just never used it/knew why it was there.

The ISR does cause the motor to stop when the count is reached but it never gets reached with the code in its current state because rather than the robot moving to position 1 by looping through test1() and then moving back to home by looping through test2(), it just jerks backwards and forwards because the code is looping through test1() and test2() one after the other indefinitely, whereas it needs to keep doing test(1) until count (now countInit) is reached, and then proceed to test2().

This is where im up to, when this code is uploaded on the arduino i get absolutely no movement but probing with the mulimeter shows that “motorBrake()” is on on all motors from the start. Not sure if i’m on the right lines with this method?

#define InA1            11                      // INA motor pin
#define InB1            12                      // INB motor pin 
#define PWM1            13                      // PWM motor pin
#define encodPinA1      21                      // encoder A pin

#define InA2            8
#define InB2            9
#define PWM2            10
#define encodPinA2      20

#define InA3            5
#define InB3            6
#define PWM3            7
#define encodPinA3      19

#define InA4            2
#define InB4            3
#define PWM4            4
#define encodPinA4      18

#define LOOPTIME        100
#define FORWARD         1
#define BACKWARD        2

unsigned long lastMilli = 0;                    // loop timing
unsigned long lastMilliPrint = 0;               // loop timing
volatile long count = 0;                        // rotation counter
volatile long count2 = 0;
volatile long count3 = 0;
volatile long count4 = 0;
long countInit;
long countInit2;
long countInit3;
long countInit4;
long tickNumber = 0;
long tickNumber2 = 0;
long tickNumber3 = 0;
long tickNumber4 = 0;

long tick = 0;             //testing giving it 1 tick as a standard
long tick2 = 0;
long tick3 = 0;
long tick4 = 0;

int magnetPin = 22 ;

boolean run = false;                            // motor moves
boolean test1complete = false;
boolean test2complete = false;

void setup() {
  Serial.begin(9600); // baud rate
  Serial.flush();


  pinMode(magnetPin, OUTPUT);           
  digitalWrite(magnetPin, HIGH);         


  pinMode(InA1, OUTPUT);
  pinMode(InB1, OUTPUT);
  pinMode(PWM1, OUTPUT);
  pinMode(encodPinA1, INPUT);
  digitalWrite(encodPinA1, HIGH);               
  attachInterrupt(2, rencoder, FALLING);        
  pinMode(InA2, OUTPUT);
  pinMode(InB2, OUTPUT);
  pinMode(PWM2, OUTPUT);
  pinMode(encodPinA2, INPUT);
  digitalWrite(encodPinA2, HIGH);
  attachInterrupt(3, rencoder2, FALLING);

  pinMode(InA3, OUTPUT);
  pinMode(InB3, OUTPUT);
  pinMode(PWM3, OUTPUT);
  pinMode(encodPinA3, INPUT);
  digitalWrite(encodPinA3, HIGH);
  attachInterrupt(4, rencoder3, FALLING);

  pinMode(InA4, OUTPUT);
  pinMode(InB4, OUTPUT);
  pinMode(PWM4, OUTPUT);
  pinMode(encodPinA4, INPUT);
  digitalWrite(encodPinA4, HIGH);
  attachInterrupt(5, rencoder4, FALLING);
}

void loop() {


//************************************* Motor 1,2,3&4 Mixed Operations **************************************

  if (test1complete = false) 
    {   
    test1();         // calls test 1 subroutine
    }
   else if (test2complete = false) 
   {
    test2();
   }
   else 
   {
     while (1) {}
   }
   
}

//*******************************************************Operations*************************************************************************

void resetCounts() {

  countInit = 0;          //reset all counters in preparation for next routine
  count = 0;
  countInit2 = 0;
  count2 = 0;
  countInit3 = 0;
  count3 = 0;
  countInit4 = 0;
  count4 = 0;
}
//************************************************

void test1() {                           //Aiming to move the arm from home position into position 1

  // for (int i=0; i<3840; i++)      

  const long ticknumber = 2040;              
  const long tickNumber2 = 2560;
  const long tickNumber3 = 3840;
  const long tickNumber4 = 510;




  if ((countInit) < (tickNumber))             // do i even need the IF with the above while?... do i even ened the above while with these IFs...
  {
    moveMotor(FORWARD, 204, 1);           //direction, PWM speed, 10 tick
  }
  if ((countInit2) < (tickNumber2))           // do i need an else telling it to do nothing and move on or will it do that automatically?
  {
    moveMotor2(FORWARD, 204, 1);
  }
  if ((countInit3) < (tickNumber3))
  {
    moveMotor3(BACKWARD, 204, 1);
  }
  if ((countInit4) < (tickNumber4))
  {
    moveMotor4(FORWARD, 204, 1);
  }

if (((countInit) >= (tickNumber)) && ((countInit2) >= (tickNumber2)) && ((countInit3) >= (tickNumber3)) && ((countInit4) >= (tickNumber4)));
{
  test1complete = !test1complete;
  
  countInit = 0;          //reset all counters in preparation for next routine
  count = 0;
  countInit2 = 0;
  count2 = 0;
  countInit3 = 0;
  count3 = 0;
  countInit4 = 0;
  count4 = 0;
}
}


//*************************************************


void test2() {                              //return to home position from last move



  const long ticknumber = 2040;
  const long tickNumber2 = 2560;
  const long tickNumber3 = 3840;
  const long tickNumber4 = 510;




  if ((countInit) < (tickNumber))
  {
    moveMotor(BACKWARD, 255, 1);
  }
  if ((countInit2) < (tickNumber2))
  {
    moveMotor2(BACKWARD, 255, 1);
  }
  if ((countInit3) < (tickNumber3))
  {
    moveMotor3(FORWARD, 255, 1);
  }
  if ((countInit4) < (tickNumber4))
  {
    moveMotor4(BACKWARD, 255, 1);
  }

  if (((countInit) >= (tickNumber)) && ((countInit2) >= (tickNumber2)) && ((countInit3) >= (tickNumber3)) && ((countInit4) >= (tickNumber4)));
{
  test2complete = !test2complete;
  
  countInit = 0;          
  count = 0;
  countInit2 = 0;
  count2 = 0;
  countInit3 = 0;
  count3 = 0;
  countInit4 = 0;
  count4 = 0;
}
}


//************************************************


//******************************************Motor control stuff***********************************************

void moveMotor(int direction, int PWM_val, long tick)  {
  countInit = count;    // abs(count)
  //  tickNumber = tick;
  if (direction == FORWARD)          motorForward(PWM_val);
  else if (direction == BACKWARD)    motorBackward(PWM_val);
}

void moveMotor2(int direction, int PWM_val, long tick2)  {
  countInit2 = count2;    // abs(count)
  // tickNumber2 = tick2;
  if (direction == FORWARD)          motorForward2(PWM_val);
  else if (direction == BACKWARD)    motorBackward2(PWM_val);
}

void moveMotor3(int direction, int PWM_val, long tick3)  {
  countInit3 = count3;    // abs(count)
  // tickNumber3 = tick3;
  if (direction == FORWARD)          motorForward3(PWM_val);
  else if (direction == BACKWARD)    motorBackward3(PWM_val);
}

void moveMotor4(int direction, int PWM_val, long tick4)  {
  countInit4 = count4;    // abs(count)
  //  tickNumber4 = tick4;
  if (direction == FORWARD)          motorForward4(PWM_val);
  else if (direction == BACKWARD)    motorBackward4(PWM_val);
}


// ******************************************** Encoder counting **************************************************

void rencoder()  {                                  // pulse and direction, direct port reading to save cycles
  if (PD0 == LOW || PD0 == HIGH)   {                 //added the || to make sure i am getting into the ISR, it counts ++ whatever the pin state.
    count++;
  }
  else                   {
    count--;
  }

  if ((count) > tickNumber)   {
    motorBrake();                               //apply the brake when the count of the motor exceeds the tick number (what we ask it to do in void loop() eg 510*1.2
  }
}

void rencoder2()  {
  if (PD1 == HIGH || PD1 == LOW )   {
    count2++;
  }
  else                   {
    count2--;
  }

  if ((count2) > tickNumber2)   {
    motorBrake2();
  }
}

void rencoder3()  {
  if (PD2 == LOW)   {
    count3++;
  }
  else                   {
    count3--;
  }

  if ((abs(count3)) > tickNumber3)   {
    motorBrake3();
  }
}

void rencoder4()  {
  if (PD3 == LOW)   {
    count4++;
  }
  else                   {
    count4--;
  }

  if ((abs(count4)) > tickNumber4)   {
    motorBrake4();
  }
}



// ***********************Code for forward backward and brake  *******************************
if (test1complete = false)

Oops

  if ((countInit3) < (tickNumber3))

(Why) have (you) (got) so many (parentheses)?

nick1992:
sterretje, I don’t think that’s really translatable to my case is it? unless i’m missing something, which is often the case.

I don’t want to have to say “do 100 loops of this function” I want a function to repeat until “count” exceeds “tickNumber”. Then for count and tickNumber to reset/have their value changed before starting a new function.

Also I have 4 counts and 4 tickNumbers in each function because i have 4 motors which adds complexity because i have to stay in any particular function until the last motor has finished its last move.

I was basically showing a way after your reply #5. And yes, it’s translatable. Taking your original code for test1

/*
  move motors forward
  returns:
    true if 3840 ieterations are done, else false
*/
bool test1()
{
  long ticknumber = 2040;                //set the number of ticks i want the motor to move in this operation. 1,2,3 etc. are for motors 1,2,3 etc.
  long tickNumber2 = 2560;
  long tickNumber3 = 3840;
  long tickNumber4 = 510;

  // your counter; static variable so it's remembered between calls
  static int i = 0;

  if (i >= 3840)
  {
    // reset i for the next time that we start test1
    i = 0;
    // indicate that it's completed
    return true;
  }

  // increment i
  i++


  if ((count) < (tickNumber))
  {
    moveMotor(FORWARD, 204, 1);           //direction, PWM speed, 10 tick
  }
  if ((count2) < (tickNumber2))           // do i need an else telling it to do nothing and move on or will it do that automatically?
  {
    moveMotor2(FORWARD, 204, 1);
  }
  if ((count3) < (tickNumber3))
  {
    moveMotor3(BACKWARD, 204, 1);
  }
  if ((count4) < (tickNumber4))
  {
    moveMotor4(FORWARD, 204, 1);
  }

  // indicate that operation is not complete yet
  return false;
}

The above function basically does the same as your version; the return value can be used to check if the required number of loops has been done.

void loop()
{
  if(test1() == true)
  {
    while(1) {}
  }
}

Except for a possible small timing difference, this would be the same as using your current test1 called in loop like

void loop()
{
  test1();
  while(1) {}
}

You can do the same for your test2.

Next you can create a loop that will do the required steps in sequence. I’ve used a mode variable to indicate what needs to happen (forward, backward, stop). The below basically is a small sequencer/statemachine (read up on it because you will need it one day :wink: ).

void loop() {
  // mode; 1 to run test 1, 2 to run test 2, 3 stops the process
  static byte mode = 1;

  switch (mode)
  {
    case 1:
      // run test1 till completed
      if (test1() == true)
      {
        // reset counters
        resetCounts();
        // switch to next mode
        mode = 2;
      }
      break;
    case 2:
      // run test2 till completed
      if (test2() == true)
      {
        // reset counters
        resetCounts();
        // switch to next mode
        mode = 3;
      }
      break;
    default:
      // wait forever because mode is never modified again
      break;
  }
}

The code initializes the mode variable to 1 and in the switch, the code in case 1 will be executed on every call to loop(). Once test1() returns true, resetCounts() is called to reset your counters and mode is set to 2.
The next times loop() is called, the code in case 2 is executed till test2() returns true. Again, resetCounts() is called and mode is changed to 3.

Any successive calls to loop will now execute the code in the default case (which is empty so nothing will happen). In the default case, you can e.g. check a button state and reset mode to 1 if the button is pressed so the sequence starts again.

It’s just to give you the idea that you don’t need for or while loops as @Robin2 indicated in reply #4; he also posted a link that you should read one day.

Note that this is not written to solve possible problems that you have.

nick1992:
ty_ger07, the while (1) {} is to stop it after one loop, I just didn't know any other way of making it stop.

I only want to visit each function once, one after the other, but some functions require looping through them before moving on to the next function.

I would recommend puting it to sleep at the end of the loop instead of looping forever in a sub loop or waiting forever in the primary loop.

There are quite a few guides if you search google and it shouldn't mess with your interrup if done properly and shouldn't rewake unless you decide you want an interrupt to re-wake it from sleep.

Saves power at least and avoids accidental re-running for whatever reason.