Passing array value to a function not working

Hi,

I'm trying to pass an int from a robot's sonar sensor into its function for controlling the motors. The robot has 2 front-facing sensors - one on the left and one on the right side. In my code, the closer the robot is to an object on the right side, the slower the left motors will turn, thus creating a speed differential.

The problem I'm facing in my code is that I'm trying to pass the value of a sonar to the motor function, but I am getting an error message, as shown in the attached image.

The part of my code where I'm getting the error is passing the left sonar value, 'sonar_value[0]' and the right sonar value, 'sonar_value[1]' into the function class members 'Right_Differential' and 'Left_Differential', respectively, as shown here at the bottom of my (abridged) code.

I am unsure of how to handle the errors, and not sure what needs to be fixed since I think I properly declared the 'sonar_value' properly as an int.

// Libraries

#include <NewPing.h>  // Sonar library
#include <AFMotor.h>  // AF Motor shield library


// Sonar Declarations

// SET UP PINS & ROBOT INFO
#define SONAR_NUM     2 // Number or sensors
#define MAX_DISTANCE 500 // Maximum distance (in cm) to ping.
// or should it be 200?


// Sensor object array, defines how to use the pins
NewPing sonar[SONAR_NUM] = 
    {     
     //  (trigger pin, echo pin, and max distance to ping)
         NewPing(18, 19, MAX_DISTANCE),   // sensor 1
         NewPing(20, 21, MAX_DISTANCE),   // sensor 2
    };

int sonar_value[SONAR_NUM];
  /*  array format:   sonar_value[left sonar][right sonar]
      could be placed in class sonar, public, but couldn't then be called from loop()
   */


//GLOBAL VARIABLES for Sonars
  // these are placed to because they need to be called in main loop()
  // they could have been defined within their class, but then couldn't use variables outside of the class in loop()

// threshold for sonar to detect obstacle, inches
const static int threshold = 15;  

int error_value = 395;
   /* Note:  This number is set in the NewPing.h file, #define NO_ECHO 99999999, 
      which translates to 395 inches, which is a garbage value since sensor would never see it
      Note: default value to return was 0, but I modified the NewPing.h file.
   
      Note: If object is covering either "eye" of sensor, an error will also be returned since object inhibited a returned pulse   
    */


//Motor Declarations

// define wheels (individual)

  // front wheels
  AF_DCMotor Motor_Left_Front(4, MOTOR34_1KHZ); // motor 4
  AF_DCMotor Motor_Right_Front(3, MOTOR34_1KHZ); // motor 3

  // rear wheels
  AF_DCMotor Motor_Left_Rear(1, MOTOR12_64KHZ); // motor 1
  AF_DCMotor Motor_Right_Rear(2, MOTOR12_64KHZ); // motor 2
 
/********** GLOBAL VARIABLES for Motors **********/
int motor_delay = 10; // ms time delay, time motors should run for
                      // Autonomous Mode uses 20ms, which is set there to change
                      
int differential_speed;                      
                      
// Other Declarations
        
// LEDs, used for mode status
const int ledPin = 23;      // LED is connected to pin 23, STATUS
const int ledPin2 = 22;     // yellow LED, flickering LED

// These variables CAN change
int auto_code = -1;           // default
int incomingByte;      // a variable to read incoming serial data into
int ping_once = 0;  /* done so that robot will not always ping on manual motors to stop,
                       because next time around, x > 1, and is reset
                       each time switch from autonomous mode
                     */


// BOOLEAN VARIABLES
bool autonomous_code = false;  // default
 
  
// CLASS:  Sonar

class Sonar
{
  public:
   
  void Setup_Sonars()  // run once at setup
    {
      // nothing is currently here
    }
    
  void Read_Sonars() 
    {         
    // Loop through all the sensors  
      for (int i = 0; i < SONAR_NUM; i++)   
       { 
         int value = sonar[i].ping_in();  // ping each sensor in array
         sonar_value[i] = value;  // write current sensor's value into array slot for that sensor
         delay(80); //time between sensor pings (29ms is about the min to avoid cross-sensor echo). Larger time for debugging
       }
      
    // print values
      for (int i = 0; i < SONAR_NUM; i++) 
       {
         Serial1.print(i);
         Serial1.print("=");
         Serial1.print(sonar_value[i]);
         Serial1.print("in  |  ");
       }
   
      Serial1.println();
    }

  private:
            // nothing is currently here
            
};



//  CLASS:  Motors

class Motors
{
  public:
  
    void Setup_Motors()
    {
      
       // scale % into pwm range
       int pwm = map(speed, 0, 100, 0, 255);  
             // takes range of 0-255 and maps it to 0-100 for variable 'speed'
                                                 
     // front wheels
     Motor_Left_Front.setSpeed(pwm);
     Motor_Right_Front.setSpeed(pwm);

     // rear wheels
     Motor_Left_Rear.setSpeed(pwm);
     Motor_Right_Rear.setSpeed(pwm);

     // make sure motors are not triggered at start
     Drive_State(RELEASE);    // stop
    }


     // DIFFERENTIAL - TURN LEFT (Right sonar triggered)
    void Left_Differential(int sonar_value[1])
    {
      differential_speed = autonomous_speed - (autonomous_speed *( (threshold - sonar_value[1]) / (threshold - 1) ));
    
    // front wheels
    Motor_Left_Front.run(differential_speed);
    Motor_Right_Front.run(FORWARD);
    
    // rear wheels
    Motor_Left_Rear.run(differential_speed);
    Motor_Right_Rear.run(FORWARD);
   }
    
    // DIFFERENTIAL - TURN RIGHT (Left sonar triggered)
    void Right_Differential(int sonar_value[0])
    {
      differential_speed = autonomous_speed - (autonomous_speed *( (threshold - sonar_value[0]) / (threshold - 1) ));
    
    // front wheels
    Motor_Left_Front.run(FORWARD);
    Motor_Right_Front.run(differential_speed);
    
    // rear wheels
    Motor_Left_Rear.run(FORWARD);
    Motor_Right_Rear.run(differential_speed);
   }
      
 
  private:
  
    static const int speed = 100; // % of maximum speed, used for mapping
    static const int manual_speed = 255; // % of maximum speed
    static const int autonomous_speed = 255 * 0.4 ; // % of manual speed
};

/*
     CLASSES SETUP, FORM: 
    Class [space] Object  ;
*/
// sonar class
Sonar sonar_function; 

// motors class
Motors motors_function;



void setup() 
{

  Serial1.begin(9600);           // set up Serial library at 9600 bps

pinMode(ledPin, OUTPUT);    // Set the LED pin as output
pinMode(ledPin2, OUTPUT); 

// Motors setup
motors_function.Setup_Motors();

// Sonar setup - currently not used
sonar_function.Setup_Sonars();

}


void loop() 
{
  
//Serial.println(incomingByte);

       
//  AUTONOMOUS MODE

if (autonomous_code == true)  
  {

    // read sonar
      sonar_function.Read_Sonars();

// AUTONOMOUS Movement
               

 // check if either sonar reads below threshold
   if ((sonar_value[0] < threshold) || (sonar_value[1] < threshold)) //&& (sonar_value[0] > 0) && (sonar_value[1] > 0))
     {
       // error checker.  prevents the possibility of an error of no ping returned when no object is near.
       if ((sonar_value[0] != error_value) && (sonar_value[1] != error_value))
       {
            // BOTH left & right sonars are triggered, indicating a wall
             if ((sonar_value[0] < threshold) && (sonar_value[1] < threshold))
           {
             // back up + turn, or escape (random?)?
             motors_function.Drive_State(BACKWARD);  // backward
             Serial.print("A");
           }
           
             // LEFT sonar is triggered
               else if (sonar_value[0] < threshold)
               {
       /*          // turn right
                 motors_function.Right_Turn();
                 Serial.print("B");
       */          
                 // differential, turn RIGHT
                 motors_function.Right_Differential(int sonar_value[0]);
                 Serial.print("B");
               }
               
           // RIGHT sonar is triggered
           else
            {
      /*        // turn left
              motors_function.Left_Turn();
              Serial.print("C");
      */        
             // differential, turn LEFT
             motors_function.Left_Differential(int sonar_value[1]);
             Serial.print("C");
            }
         }
     }
     
   // no obstacles near sensors
   else
   {
    motors_function.Drive_State(FORWARD);    // forward
     Serial.print("D");     
    }      
    
  }
}

motors_function.Right_Differential(int sonar_value[0]);

What is that "int" doing there?

void Left_Differential(int sonar_value[1])

Why are you passing it a one element array?

AWOL:

void Left_Differential(int sonar_value[1])

Why are you passing it a one element array?

I'm trying to pass the value obtained from the right sonar, which is stored as sonar_value[1] into the function to control the speed of the left wheels (differential_speed). In this example, the lower the right sonar's reading, the closer it is to an object, so I want to reduce the speed of the left wheels so that it will turn left, and steer the robot away from the object. That speed is determine by the differential_speed equation I have shown below.

This sonar's value is stored in this class member function:

// DIFFERENTIAL - TURN LEFT (Right sonar triggered)
    void Left_Differential(int sonar_value[1])
    {
      differential_speed = autonomous_speed - (autonomous_speed *( (threshold - sonar_value[1]) / (threshold - 1) ));
    
    // front wheels
    Motor_Left_Front.run(differential_speed);
    Motor_Right_Front.run(FORWARD);
    
    // rear wheels
    Motor_Left_Rear.run(differential_speed);
    Motor_Right_Rear.run(FORWARD);
   }

And when I try to run the code, the image I posted is the error I get. But it is not working as I thought it would. I'm not sure what I'm doing wrong, as I though this was simple enough to work.

In your for loop:

  void Read_Sonars() 
  {         
    // Loop through all the sensors  
      for (int i = 0; i < SONAR_NUM; i++)   
      { 
         int value = sonar[i].ping_in();  // ping each sensor in array
         sonar_value[i] = value;  // write current sensor's value into array slot for that sensor
         delay(80); //time between sensor pings (29ms is about the min to avoid cross-sensor echo). Larger time for debugging
      }
      // rest of code...

you define value on each pass through the loop. A more conventional way is to move the definition of value to the top of the Read_Sonars() function:

  void Read_Sonars() 
    {         
      int value;

      // Loop through all the sensors  
      for (int i = 0; i < SONAR_NUM; i++)   
      { 
         value = sonar[i].ping_in();  // ping each sensor in array
         sonar_value[i] = value;  // write current sensor's value into array slot for that sensor
         delay(80);
      }
      
      // Rest of function code...

A more conventional way is to move the definition of value to the top of the Read_Sonars() function:

I really don't see this a big deal, and the original code keeps the scope as local as possible, which is generally considered to be a Good Thingtm
Unless the type constructor is particularly onerous or expensive, I see no reason to move the definition to the outer scope.
Of course, you could take the view that the definition isn't necessary at all, and the array assignment could just come directly from the function return value.

Sure there are different ways to program it, but I still need to understand the error msg, and why I can't pass the sensor value through the function call

OK, but you're trying to pass the value into the prototype. You are declaring a function and you tell it what types of arguments you'll pass and what you'll call them inside the function:

int addTwo(int aNumber){
     int retval = aNumber +2;
     return retval;

Here we tell the function that we'll give it an int, but we don't tell it yet what int we will give it. We do that when we call the function.

int someVariable = addTwo(sensorVal[1]);

That will call our function and pass to it the value in sensorVal[1]. Inside the addTwo function it is known as aNumber, but we told it aNumber should have the value from sensorVal[1] when we called it. We can call that function with any int as the argument and it will return that value + 2.

I would suggest you find a good C++ reference or tutorial on functions and it should clear it right up for you.

@AWOL: I think it does make a difference in that's where most people expect to find the data definitions for a function block; it's a documentation thing and can play a part when debugging is necessary. I like consistency and this isn't for the way most people write code. If you insist on encapsulating it, you could move it to expression 1 of the for loop, but I think that's kinda ugly. Cleary, the best solution is to do away with value altogether:

 void Read_Sonars() 
  {         

      for (int i = 0; i < SONAR_NUM; i++)      // Loop through all the sensors   
      { 
         sonar_value[i] = sonar[i].ping_in();  // ping each sensor in array
         delay(80); 
      }
      // rest of code...

@AWOL: I think it does make a difference in that's where most people expect to find the data definitions for a function block; it's a documentation thing and can play a part when debugging is necessary.

Maybe, going back to original K&R days that was true, but now I really think it should be as local as possible.
Personally, it really bugs me to see a definition, and then only a few lines away (or even on the next line FFS), an assignment.

(I used to be an occam programmer, where keeping it local meant keeping it as fast as possible, and it's just a habit I've got into)

Delta_G:
OK, but you're trying to pass the value into the prototype. You are declaring a function and you tell it what types of arguments you'll pass and what you'll call them inside the function:

int addTwo(int aNumber){

int retval = aNumber +2;
    return retval;




Here we tell the function that we'll give it an int, but we don't tell it yet what int we will give it. We do that when we call the function.



int someVariable = addTwo(sensorVal[1]);




That will call our function and pass to it the value in sensorVal[1]. Inside the addTwo function it is known as aNumber, but we told it aNumber should have the value from sensorVal[1] when we called it. We can call that function with any int as the argument and it will return that value + 2. 

I would suggest you find a good C++ reference or tutorial on functions and it should clear it right up for you.

@Delta_G

Thanks for your input. I have tried what you have suggested, and it still seems to give me the same error.

Here's what I've done:

I created a motors class member prototype function,

 // DIFFERENTIAL SPEED FUNCTION
    int Differential_Speed(int sensor_reading)  // int sonar_value[1].  'sensor_reading' means sonar_value[n]
    {
      differential_speed = autonomous_speed - (autonomous_speed *( (threshold - sensor_reading) / (threshold - 1) ));
    
      return differential_speed;
    }

This will take in some int value, called "sensor_reading", which the function doesn't know yet.

Then, I will call the function, and pass it the sensor value from the sonar on the robot:

   // LEFT sonar is triggered
               else if (sonar_value[0] < threshold)
               {
                    int run_motors = motors_function.Differential_Speed(int sonar_value[0]);
                    Serial.print("run_motors");
                    Serial.print("B"); 
               }

However, this winds up giving me the same error msg. What I thought would occur here is that when I called the function, motors_function.Differential_Speed, it would be set to the int variable run_motors. I'd be able to verify this by then printing run_motors, but that doesn't seem to work. If this worked, then I would be able to take the run_motors value, and then pass that to the differential function to make my motors turn the speed I wanted to. But that isn't possible...yet?

I just wind up getting the same error msg, as before.

What could I be doing wrong?

int someVariable = addTwo(sensorVal[1]);
int run_motors = motors_function.Differential_Speed(int sonar_value[0]);

Notice the very subtle difference. You don't supply a type specifier when you call a function.

Lose the "int" before sonar_value[0]

got it working - thanks!