Function return problem

Hi all,
Just wondering if anyone can help me with a small programming issue. I have written a function (below), it takes the value 'pRight' and sets it to 90 if 'num' equals 0, just as it should. The for loop also appears to work correctly.
The error is that it doesn't return the new value of 'pRight' to the main function with the value returning instead to 0. Can anyone see where I have gone wrong?

unsigned int change_pRight(unsigned int pRight) {
  int k;
  int a;
  //Define local variables
  num = random(0,2); //Generate a random number of 0 or 1
  if(num == 0) {
    k = pRight;
    pRight = 90;
    a = 1;
  }
  else if(num == 1) {
    k = pRight;
    pRight = 0;
    a = -1;
  }
  //Serial.println(pRight);
  
  for(;k <= pRight; k = k+a) {
    P_R.write(k);
    delay(10); //Wait 10 milliseconds on each loop
  }
  //Change point by looping until k < pRight 
  return pRight; 
}

Mitchell

need to see code calling change_pRight() and how is processes the return value.

Can you post your whole script so we can see how you are calling this function?

You function is returning pRight so it must be in how you are calling it. Are you calling it something like this?

unsigned int ret = change_pRight(pRight);

If so then print ret to the serial monitor and see what the value is.

Perhaps you meant to use pass-by-reference rather than pass-by-value:

void change_pRight(unsigned int & pRight) {
  int k;
  int a;
  //Define local variables
  num = random(0,2); //Generate a random number of 0 or 1
  if(num == 0) {
    k = pRight;
    pRight = 90;
    a = 1;
  }
  else if(num == 1) {
    k = pRight;
    pRight = 0;
    a = -1;
  }
  //Serial.println(pRight);
 
  for(;k <= pRight; k = k+a) {
    P_R.write(k);
    delay(10); //Wait 10 milliseconds on each loop
  }
  //Change point by looping until k < pRight
}

Here is the entire code. Based on your responses, I wonder if I might be getting confused with other programming languages and syntax, but I would imagine you would be a better judge of that.

#include <Servo.h>
Servo P_L;
Servo P_R; 
//define Servos
int Direction = 12; //Use DPDT non-latching relay
int Track = 11;
int S1 = 6;
int S2 = 7;
int S3 = 8;
int S4 = 13;
//Assign outputs to their pins

int Sen_L = 0;
int Sen_R = 1;
int Sen1 = 2;
int Sen2 = 3;
int Sen3 = 4;
int Sen4 = 5;
//Assign digital sensors to their pins
//Use reed switches

const unsigned int maxSpeed = 150; //Maximum speed of train
const unsigned int wait = 3000; //Duration braking/acceleration
unsigned int numRepeat = 0; 
int num;
//Define variables

unsigned int pLeft = 0;
unsigned int pRight = 0;
//Point servo angle values

const unsigned int stationStopMin = 4000;
const unsigned int stationStopMax = 6000;
const unsigned int sidingStop = 5000;
//Delay constants
//Delays in milliseconds

void setup() {
  pinMode(Direction, OUTPUT);
  pinMode(Track, OUTPUT);
  pinMode(S1, OUTPUT);
  pinMode(S2, OUTPUT);
  pinMode(S3, OUTPUT);
  pinMode(S4, OUTPUT);
  //Define as outputs 

  pinMode(Sen_L, INPUT_PULLUP);
  pinMode(Sen_R, INPUT_PULLUP);
  pinMode(Sen1, INPUT_PULLUP);
  pinMode(Sen2, INPUT_PULLUP);
  pinMode(Sen3, INPUT_PULLUP);
  pinMode(Sen4, INPUT_PULLUP);
  //Define as inputs with pull-up resistors enabled

  P_L.attach(9);
  P_R.attach(10);
  //Attach servo control wires to their pins

  Serial.end();

  Serial.begin(9600);
}

int Dec(const unsigned int Max, const unsigned int dly);
int Acc(const unsigned int Max, const unsigned int dly);
void SidingSet(const unsigned int pLeft, const unsigned int pRight);
int RepeatInc(unsigned int Repeats);
unsigned int change_pRight(unsigned int pRight);
int change_pLeft(unsigned int pLeft);
void fullSiding_R(const unsigned int pRight);
void fullSiding_L(const unsigned int pLeft);
void debug(void);
//Define functions

void loop() {
  if(numRepeat == 0) {
    P_L.write(pLeft);
    P_R.write(pRight);
    //Set servos to default positions

    SidingSet(pLeft, pRight); //Set sidings
  }
  //Perform only at first loop instance

  digitalWrite(Direction, LOW); //Set direction of travel (Left-Right)
  analogWrite(Track, maxSpeed); //Write PWM to track of duty cycle maxSpeed
  
  while(digitalRead(Sen_L) == 1) {
  } //Wait until Sen_L is triggered
  Dec(maxSpeed, wait); //Decelerate train to stop
  delay(random(stationStopMin, stationStopMax)); //Wait between 'x' to 'y' seconds at station
  Acc(maxSpeed, wait); //Accelerate train

  fullSiding_R(pRight); //Wait for train to enter siding
  analogWrite(Track, 0); //Turn off track (stop train)

  change_pRight(pRight); 
  delay(sidingStop); //Wait for 'x' seconds before sending out next train

  digitalWrite(Direction, HIGH); //Reverse direction of travel (Right-Left)
  analogWrite(Track, maxSpeed); //Write PWM to track of duty cycle maxSpeed

  while(digitalRead(Sen_R) == 1) {
  } //Wait for Sen_R to trigger
  Dec(maxSpeed, wait); //Decelerate train to stop
  delay(random(stationStopMin, stationStopMax)); //Wait between 'x' to 'y' seconds at station
  Acc(maxSpeed, wait); //Accelerate train

  fullSiding_L(pLeft); //Wait for train to enter siding
  analogWrite(Track, 0); //Turn off track (stop train)

  change_pLeft(pLeft);
  delay(sidingStop); //Wait for 'x' seconds before sending out next train
  
  RepeatInc(numRepeat); 
}

int Dec(const unsigned int Max, const unsigned int dly) {
  for(int i = Max; i >= 0; i--) {
    analogWrite(Track, i); //Set Track PWM to i duty cycle
    delay((float) dly/Max); //Wait for dly milliseconds (dly/max seconds per loop
  }
  //loop until i < 0. Decrement i on each loop
}

int Acc(const unsigned int Max, const unsigned int dly) {
  for(int i = 0; i <= Max; i++) {
    analogWrite(Track, i); //Set Track PWM to i duty cycle
    delay((float) dly/Max); //Wait for dly seconds (dly/max seconds per loop
  }
  //loop until i < 0. Increment i on each loop
}

void SidingSet(const unsigned int pLeft, const unsigned int pRight) {
  if(pLeft == 0) {
    digitalWrite(S2, HIGH); //Make S2 active
    digitalWrite(S1, LOW); //Make S1 inactive
  }
  else {
    digitalWrite(S2, LOW); //Make S2 inactive
    digitalWrite(S1, HIGH); //Make S1 active
  }
  
  if(pRight == 0) {
    digitalWrite(S3, HIGH); //Make S3 active
    digitalWrite(S4, LOW); //Make S4 inactive
  }
  else{
    digitalWrite(S3, LOW); //Make S3 inactive
    digitalWrite(S4, HIGH); //Make S4 active
  }
}

int RepeatInc(unsigned int Repeats) {
  if(Repeats == 0) {
   Repeats++;
  }
}
//Increment Repeats to 1 if it equals 0

unsigned int change_pRight(unsigned int pRight) {
  int k;
  int a;
  //Define local variables
  num = random(0,2); //Generate a random number of 0 or 1
  if(num == 0) {
    k = pRight;
    pRight = 90;
    a = 1;
  }
  else if(num == 1) {
    k = pRight;
    pRight = 0;
    a = -1;
  }
  //Serial.println(pRight);
  
  for(;k <= pRight; k = k+a) {
    P_R.write(k);
    delay(10); //Wait 10 milliseconds on each loop
  }
  //Change point by looping until k < pRight 
  return pRight; 
}

int change_pLeft(unsigned int pLeft) {
  int k;
  int a;
  //Define local variables
  num = random(0,2); //Generate random number of 0 or 1
  if(num == 0) {
    k = pLeft;
    pLeft = 90;
    a = 1;
  }
  else if(num == 1) {
    k = pLeft;
    pLeft = 0;
    a = -1;
  }
 
  for(;k <= pLeft; k = k+a) {
    P_R.write(k);
    delay(10); //Wait 10 milliseconds on each loop
  }
  //Change point by looping until k < pRight
  return pLeft;
}


void fullSiding_R(const unsigned int pRight) {
  if(pRight == 0) {
    while(digitalRead(Sen3) == 1) {
    }
  }
  else {
    while(digitalRead(Sen4) == 1) {
    }
  }
  //Wait for train to enter active siding
}

void fullSiding_L(const unsigned int pLeft) {
  if(pLeft == 0) {
    while(digitalRead(Sen2) == 1) {
    }
  }
  else {
    while(digitalRead(Sen1) == 1) {
    }
  }
  //Wait for train to enter active siding
}

void debug() {
  Serial.println("Triggered");
}

All the code works as I want it to. The only issues are the aforementioned ones with change_pRight and change_pLeft.

Mitchell

You're not doing anything with the values returned from those functions. You're just ignoring them.

Steve

I think I understand what you are saying, what you should understand is that the code is designed to run repeatedly. However, I did have a Serial.println function after the function was called and that always printed a value of 0 for pRight regardless of what happened in the function. Do I need to say:

pRight = change_pRight(pRight);

Mitchell

Yes that's it. The pRight that you're changing inside the function is a variable that is local to the function and can't be seen outside that function. You want to change the other global pRight and you do it by assigning the returned value to it.

There are other ways you could have achieved the same thing but that should do what you need.

Steve

In that case, thank you.
It appears I was getting confused with other programming languages and advice I have been given in the past.

Mitchell