Making a subroutine that returns a value

Hi there,
I'm trying to make a sub routine that determines the value of a sensor but I'm not 100% sure about the syntax. My understanding is that you can't use "void" if the subroutine returns a value. Also when I try and compile my code it says "a function-definition is not allowed here before '{' token". So just wondering how I can improve my code. I was also wondering can I refer to the value defined in the subroutine (eg. ds_scaledValueb1) in my main program?

void sensor(){
  ds_valueb1 = analogRead (ds_pinb1);    //s               // Reads the distance sensor
  ds_valueb2 = analogRead (ds_pinb2);    //s
  ds_values1 = analogRead (ds_pins1);    //s
  ds_values2 = analogRead (ds_pins2);    //s
  
  ds_scaledValueb1 = ((float)ds_valueb1 / 615) * 1024;    //s                 // Calculates the scaled value
  ds_scaledValueb2 = ((float)ds_valueb2 / 615) * 1024;    //s
  ds_scaledValues1 = ((float)ds_values1 / 615) * 1024;    //s
  ds_scaledValues2 = ((float)ds_values2 / 615) * 1024;    //s
}

Thanks for any help you can give :slight_smile:

You can define a function to return any type that you want.

int myFun(  int a )
{
    return (2*a) ;
}

is a function that returns an integer.

Unless you are an expert, you should avoid writing any functions that dynamically allocate memory, because it doesn't work very well on Arduino for a number of reasons.

Ok well I am completely new so I guess I will try and take you advice. When you say dynamically allocate memory are you just referring to the subroutines in general? And if this is what you mean then it probably doesn't really alter the code itself too much, I just have to rewrite the subroutines within the main code every time I want to use it?

To use michinyon's function you would call it like someNum = myFun(2); someNum will = 1. The function takes on the value of the returned value. A function can return only one value. You can set the values of any number of global variables within the function.

So what you're saying is that I should make an individual function for ds_valueb1, ds_valueb2 etc. rather than grouping them under one function?

"Dynamically allocating memory", refers to creating new values and objects within a function, by allocating memory for them during the program's execution. This is common practise in modern computer languages, and it is how programming is taught in modern times. However it is inadvisable on the arduino because of
(1) very limited memory
(2) no operating system
(3) poor exception handling
(4) intrinsically difficult skill for people with little or no programming expertise
(5) unfamiliar to java users who are accustomed to relying on automatic garbage collection.
and probably several other reasons as well.

Teamteabags:
So what you're saying is that I should make an individual function for ds_valueb1, ds_valueb2 etc. rather than grouping them under one function?

No, I answered your original question, which was whether a function can return something other than "void".

If the variables are global scope you can work on them in the function and change their values. The function doesn't return anything.

Teamteabags:
Hi there,
I'm trying to make a sub routine that determines the value of a sensor but I'm not 100% sure about the syntax. My understanding is that you can't use "void" if the subroutine returns a value. Also when I try and compile my code it says "a function-definition is not allowed here before '{' token". So just wondering how I can improve my code. I was also wondering can I refer to the value defined in the subroutine (eg. ds_scaledValueb1) in my main program?

void sensor(){

ds_valueb1 = analogRead (ds_pinb1);    //s               // Reads the distance sensor
  ds_valueb2 = analogRead (ds_pinb2);    //s
  ds_values1 = analogRead (ds_pins1);    //s
  ds_values2 = analogRead (ds_pins2);    //s
 
  ds_scaledValueb1 = ((float)ds_valueb1 / 615) * 1024;    //s                 // Calculates the scaled value
  ds_scaledValueb2 = ((float)ds_valueb2 / 615) * 1024;    //s
  ds_scaledValues1 = ((float)ds_values1 / 615) * 1024;    //s
  ds_scaledValues2 = ((float)ds_values2 / 615) * 1024;    //s
}




Thanks for any help you can give :)

You need to be clear about what you are trying to accomplish with this code.
You need to go away and read about the difference between local and global variables in general, and on the arduino in particular.

You haven't declared any of those variables, anywhere in your code. If your program only uses the first four values inside the function, then you declare them in the function. If you program is going to use the second four values in some other piece of code, then in the context of the arduino, you need to declare them as global values.

You also need to be a lot clearer about the difference between float and integer arithmetic. What are you trying to accomplish by that scaling calculation ? Go away and read about the difference between float and integer arithmetic.

It is not very practical, in this context, to return the result as a return value of the function. You could pack your four values into a struct and return that, but probably unnecessary. You could also pass pointers to the variables to the function, also unnecessary. Easier in this context to define 4 global variables and modify those inside the function.

I would write something like this

float scal1  ;
float scal2 ;                                // these are global variables for the scaled result
const float scan_con = 0.51 ;   // = 615/1024

void setup()
{
}

void loop()
{
    read_sensors() ;
    // do something else
}

void read_sensors() 
{
   int a=analogRead( pin1 );                   //  a and b are local variables
   int b=analogRead( pin2 );

   scal1 = ((float)a) * scal_con ;             //  the outcome of the function is effected  by modifying the global variables here.
   scal2 = (float)b)* scal_con ;
}

Yeah I'm sorry if it was a bit unclear, I didn't want to post the whole code since I thought it might make it cluttered but I'll add that now. And I am severely lacking in the basics of the coding language since I'm doing it for a university project in a short amount of time and we haven't actually been taught any of it, so I'm just trying to learn what I can in the time period I have.

As for the project itself:
We have to design a vehicle that is "one-button" start to navigate the track from the start to end positions, climbing the two steps. I've attached a picture of the track and the vehicle (the arrows indicate sensors). Basically the track is all flat with no walls except the low wall that I've labelled and the 2 steps. Basically the commands we want to use are:

  1. drive until the back sensors read a certain distance (eg. 5cm) and then stop {this is to detect the first step}
  2. realign the vehicle using the distance values of the 2 back sensors.
  3. Continue driving until the back sensors read the distance again (eg. 5cm), {this will occur after the vehicle has climbed the second step.}
  4. Rotate 90 degrees counter-clockwise until the value of the 2 left sensors are equal
  5. drive a certain distance to the finish line then stop.
#define ds_pinb1 0    //s   // Pin to which the distance sensor is connected
#define ds_pinb2 1    //s      //b1 refers to 1st sensor on back, b2 is second sensor on back, s1 refers to 1st pin on left side etc. Pins are counted in a clockwise direction.
#define ds_pins1 2    //s
#define ds_pins2 3    //s
#define buttonPin 4   //b



int motor_left[] = {2, 3};      //m      ////////CHECK THESE
int motor_right[] = {7, 8};     //m      ////////NUMBERS//////these are arrays, so motor_right[0]=7 and motor_right[1]=8 etc.

int ds_valueb1;      //s      // Integer to hold the sensor’s reading
int ds_valueb2;      //s
int ds_values1;      //s
int ds_values2;      //s

float ds_scaledValueb1;    //s // Distance sensor’s scaled value
float ds_scaledValueb2;    //s
float ds_scaledValues1;    //s
float ds_scaledValues2;    //s

void setup()
{
  Serial.begin (9600); // Initiates serial communication at 9600 baud
  
 
  
int i;                            //m
for(i = 0; i < 2; i++){           //m 
pinMode(motor_left[i], OUTPUT);   //m
pinMode(motor_right[i], OUTPUT);  //m
}
}
void loop (){

  sensor();
  sum_value();
  int sum_sensor;
  drive_forward();
    
if (ds_scaledValueb1 ==50 || ds_scaledValueb2 == 50)    //50 is in mm, may have to change calibration to get this value
  {
  motor_stop();
  if (sum_sensor<100){      //this vale of 100 has to be determined, it will just be a value greater than the total distance the sensor has read as the vehicle stops this first step (just to differentiate between first and second step)
    while (ds_scaledValueb1 != ds_scaledValueb2){
      if (ds_scaledValueb1 > ds_scaledValueb2)
        turn_right();
      else if (ds_scaledValueb1 < ds_scaledValueb2)
        turn_left();}
      drive_forward();
      delay(200);}
  
  else if (sum_sensor>100){
    while (ds_scaledValues1 != ds_scaledValues2){
      if (ds_scaledValues2 > ds_scaledValues1){
        turn_left();}
      else if (ds_scaledValues1 > ds_scaledValues2)    //this part is just in case the motor turns too far
        turn_right();}
    drive_forward();}
    delay(10000);    //time delay has to be determined, based on distance the vehicle needs to travel to finish in end zone.
    motor_stop();}}
       

  // --------------------------------------------------------------------------- Drive
void sum_value(){
  int sum_sensor;
  sum_sensor=sum_sensor+(ds_scaledValueb1+ds_scaledValueb2)/2;
  
void sensor(){
  ds_valueb1 = analogRead (ds_pinb1);    //s               // Reads the distance sensor
  ds_valueb2 = analogRead (ds_pinb2);    //s
  ds_values1 = analogRead (ds_pins1);    //s
  ds_values2 = analogRead (ds_pins2);    //s
  
  ds_scaledValueb1 = ((float)ds_valueb1 / 615) * 1024;    //s                 // Calculates the scaled value
  ds_scaledValueb2 = ((float)ds_valueb2 / 615) * 1024;    //s
  ds_scaledValues1 = ((float)ds_values1 / 615) * 1024;    //s
  ds_scaledValues2 = ((float)ds_values2 / 615) * 1024;    //s
}

void motor_stop(){
digitalWrite(motor_left[0], LOW); 
digitalWrite(motor_left[1], LOW); 

digitalWrite(motor_right[0], LOW); 
digitalWrite(motor_right[1], LOW);
delay(25);
}

void drive_forward(){
digitalWrite(motor_left[0], HIGH); 
digitalWrite(motor_left[1], LOW); 

digitalWrite(motor_right[0], HIGH); 
digitalWrite(motor_right[1], LOW); 
}

void drive_backward(){
digitalWrite(motor_left[0], LOW); 
digitalWrite(motor_left[1], HIGH); 

digitalWrite(motor_right[0], LOW); 
digitalWrite(motor_right[1], HIGH); 
}

void turn_left(){
digitalWrite(motor_left[0], LOW); 
digitalWrite(motor_left[1], HIGH); 

digitalWrite(motor_right[0], HIGH); 
digitalWrite(motor_right[1], LOW);
}

void turn_right(){
digitalWrite(motor_left[0], HIGH); 
digitalWrite(motor_left[1], LOW); 

digitalWrite(motor_right[0], LOW); 
digitalWrite(motor_right[1], HIGH); 
}

Sorry for the lack of detail at the start of the post, hopefully this clears things up a bit

OK, so all your variables there are global variables, that's fine, you can do it that way. You seem to have a spurious } in there at the end of the setup() function.

Apart from that, it all looks plausible [ I did not bother to draw a flow chart ].

So what exactly is the problem that you have with it ?

Yeah sorry I should have posted that earlier. But my problem is that when I compile I get the following errors:

_1st_attempt_proper_code_MD1.ino: In function 'void sum_value()':
_1st_attempt_proper_code_MD1:69: error: a function-definition is not allowed here before '{' token
_1st_attempt_proper_code_MD1:81: error: a function-definition is not allowed here before '{' token
_1st_attempt_proper_code_MD1:90: error: a function-definition is not allowed here before '{' token
_1st_attempt_proper_code_MD1:98: error: a function-definition is not allowed here before '{' token
_1st_attempt_proper_code_MD1:106: error: a function-definition is not allowed here before '{' token
_1st_attempt_proper_code_MD1:114: error: a function-definition is not allowed here before '{' token
_1st_attempt_proper_code_MD1:120: error: expected `}' at end of input

I assumed that this was because I used the "void sum_value" hence my initial post, but maybe its something else?

void sum_value(){
  int sum_sensor;
  sum_sensor=sum_sensor+(ds_scaledValueb1+ds_scaledValueb2)/2;
  
void sensor(){

A function ends with a "}" symbol, which you don't have at the end of sum_value.

Also, please use spaces.

Youdon'twritelikethisdoyou?

Oh great that compiled, thanks very much!! Now hopefully the logic of it all checks out. And when you say use spaces, do you just mean throughout the code in general? My only experience in coding was with VBA which automatically put in spaces so I guess I'm a bit lazy in the respect.

Yes, I mean in general. It's your code, you can do what you like with it. But in general neat layout, spaces between symbols, lining up things, etc. makes it easy to read later on.

Ok I will take that into account for future. Thanks for all the help! :slight_smile: